序列化与反序列化(1)Serializable —— Java原生态方法

本文为学习笔记,所用的图片、案例均为教学视频截图

源视频地址:Android开发基础教程(2019)第35集 序列化(1)
作者:longway777

何为序列化

将对象转换为字节序列,完整的保存在磁盘上,或者通过网络发送出去。

序列化与反序列化(1)Serializable —— Java原生态方法

反序列化就是将对象重新创建出来
序列化与反序列化(1)Serializable —— Java原生态方法
序列化的三种方式
序列化与反序列化(1)Serializable —— Java原生态方法

Serializable

java自带的接口,使用起来很简单,只需要一句话的标注就可以,具体实现也不需要做,全部是由jdk完成。缺点是效率不高,但对于应用程序级别已经够用。

Parcelable

专为安卓定制,深度优化,效率很高,在安卓系统的底层扮演了非常重要的角色,进程调度交换数据,交换对象等必不可少。

Json

基于文本的序列化,相对于二进制文件文本具有很高的可读性,广泛应用。

序列化与反序列化(1)Serializable —— Java原生态方法

效果演示

本篇章先使用第一个方法,Serializable 实现对象的序列化以及反序列化。

通过输入内容,点击Save按钮后将对象保存在文件中(序列化),点击load读取文件中的内容,反序列化使对象重建并显示在屏幕上。
序列化与反序列化(1)Serializable —— Java原生态方法

一、创建界面

序列化与反序列化(1)Serializable —— Java原生态方法

二、创建student类

创建student类,包含属性名字、姓名、分数等,类要实现接口:Serializable。并且设置getter、setter,实现构造方法等。(具体看最后的源码)

alt+insert,选择构造,创建他们三个的构造方法。
序列化与反序列化(1)Serializable —— Java原生态方法

完成他们的setter和gerter
序列化与反序列化(1)Serializable —— Java原生态方法

三、点击按钮创建对象写入到文件中

序列化与反序列化(1)Serializable —— Java原生态方法

try catch

没有处理可能发生的异常
序列化与反序列化(1)Serializable —— Java原生态方法这种IO的操作,包括像是网络的操作,是不可靠的,不一定成功,可能会出错(比如文件不存在,磁盘故障),所以需要做异常处理避免应用程序产生异常而崩溃。

尝试执行

尝试执行try里面的内容,如果不成功就会返回一个异常值,这里把他打印出来。

举一个很简单的例子
序列化与反序列化(1)Serializable —— Java原生态方法并且程序没有闪退
序列化与反序列化(1)Serializable —— Java原生态方法SAVE完成后,点击执行:

序列化与反序列化(1)Serializable —— Java原生态方法

在文件系统中可以找到创建的文件
序列化与反序列化(1)Serializable —— Java原生态方法

是二进制序列的字节文件,看着像是乱码
序列化与反序列化(1)Serializable —— Java原生态方法

可以用hex转换工具大致看看
序列化与反序列化(1)Serializable —— Java原生态方法
序列化与反序列化(1)Serializable —— Java原生态方法

toast的快速自动补全

输入Toast按下tab键自动补全
序列化与反序列化(1)Serializable —— Java原生态方法

四、点击按钮反序列化重建对象

可能的错误,两个catch
序列化与反序列化(1)Serializable —— Java原生态方法
快速try
序列化与反序列化(1)Serializable —— Java原生态方法
点击按钮后反序列化并且对象重建在屏幕上
序列化与反序列化(1)Serializable —— Java原生态方法

关键代码

虽然代码看似很多,但序列化真正涉及到的就是序列化后写入文件中,然后反序列化读出来,还有类要继承的接口

student.java

创建student类,包含属性名字、姓名、分数等,类要实现接口:Serializable。并且设置getter、setter,实现构造方法等。

//如果某个属性不需要序列化,可以添加关键字:transient
public class Student implements Serializable {
    private String name;
    private int age;
    private Score score;

    public Student(String name, int age, Score score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public Score getScore() {
        return score;
    }

    public void setScore(Score score) {
        this.score = score;
    }
}

class Score implements Serializable{
    private int math;
    private int english;
    private int chinese;
    private String grade;

    public Score(int math, int english, int chinese) {
        this.math = math;
        this.english = english;
        this.chinese = chinese;

        if(math>=90 && english>=90 && chinese>=90){
            this.grade = "A";
        }else if(math>=80 && english>=80 && chinese>=80){
            this.grade = "B";
        }else {
            this.grade = "C";
        }
    }

    public int getMath() {
        return math;
    }

    public void setMath(int math) {
        this.math = math;
    }

    public int getEnglish() {
        return english;
    }

    public void setEnglish(int english) {
        this.english = english;
    }

    public int getChinese() {
        return chinese;
    }

    public void setChinese(int chinese) {
        this.chinese = chinese;
    }

    public String getGrade() {
        return grade;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    EditText editTextName,editTextAge,editTextMath,editTextEnglish,editTextChinese;
    Button buttonSave,buttonLoad;
    TextView textViewGrade;
    //定义文件名为一个常量
    private static final String FILE_NAME = "myfile.data";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*引入一个错误,观察try catch的机制
        int x = 5;
        //除以0是算数上的一个错误,应用程序会马上崩溃闪退
        try {
            x = x / 0;
            //  错误类型为算数错误
        }catch (ArithmeticException e){
            Log.e("calError", "onCreate: "+e);
        }*/
        editTextName = findViewById(R.id.name);
        editTextAge = findViewById(R.id.age);
        editTextMath = findViewById(R.id.math);
        editTextEnglish = findViewById(R.id.eng);
        editTextChinese = findViewById(R.id.chinese);
        buttonSave = findViewById(R.id.button);
        buttonLoad = findViewById(R.id.button2);
        //之前因为缺少这一句,导致对象没有实例化所以软件闪退
        textViewGrade = findViewById(R.id.textView);

        buttonSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //点击保存后,创建变量,对象保存数据
                int math = Integer.valueOf(editTextMath.getText().toString());
                int english = Integer.valueOf(editTextEnglish.getText().toString());
                int chinese = Integer.valueOf(editTextChinese.getText().toString());
                Score score = new Score(math,english,chinese);
                String name = editTextName.getText().toString();
                int age = Integer.valueOf(editTextAge.getText().toString());
                Student student = new Student(name,age,score);

                try {
                    //将对象序列化写入到文件中,借助下面这个接口,针对应用程序而言,是输出,输出到文件中
                    //                                               第一个参数是文件的名称,第二个是读写的模式(这里选择覆盖)
                    ObjectOutputStream objectOutputStream = new ObjectOutputStream(openFileOutput(FILE_NAME,MODE_PRIVATE));
                    //把对象写入文件
                    objectOutputStream.writeObject(student);
                    objectOutputStream.flush();//清空缓冲区
                    objectOutputStream.close();

                    Toast.makeText(MainActivity.this,"data saved!",Toast.LENGTH_SHORT).show();

                    //sava之后把页面数据清空用来呈现load的数据
                    editTextChinese.getText().clear();
                    editTextEnglish.getText().clear();
                    editTextMath.getText().clear();
                    editTextName.getText().clear();
                    editTextAge.getText().clear();
                    textViewGrade.setText("-");

                    //抓住的错误类型为IOException
                }catch (IOException e){
                    //这里不做其他处理,仅观察
                    Log.e("IO", "IO error " , e);
                }
            }
        });

        //读取,反系列化
        buttonLoad.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    ObjectInputStream objectInputStream = new ObjectInputStream(openFileInput(FILE_NAME));
                    //                类型强制转换为Student类
                    Student student = (Student)objectInputStream.readObject();
                    //对象重建显示在页面上
                    editTextName.setText(student.getName());
                    editTextAge.setText(String.valueOf(student.getAge()));

                    editTextMath.setText(String.valueOf(student.getScore().getMath()));
                    editTextEnglish.setText(String.valueOf(student.getScore().getEnglish()));
                    editTextChinese.setText(String.valueOf(student.getScore().getChinese()));

                    textViewGrade.setText(student.getScore().getGrade());
                } catch (IOException | ClassNotFoundException e) {
                    Log.e("IO", "onClick: ", e);
                }
            }
        });
    }
}
上一篇:C#简繁体转换方法(kernel32.dll)


下一篇:MySQL数据库之预处理