• 编写高质量代码:改善Java的151个建议二:11-14(序列化相关内容)


    该书籍PDF下载地址:http://download.csdn.net/download/muyeju/10001473

    保存在磁盘上的对象文件包括2个部分:

      (1):类文件描述信息:包括包路径、继承关系、访问权限、变量描述、变量访问权限、方法签名、返回值、以及变量的关联类信息。

      (2):非瞬太(transient关键字)和非静态(static关键字)的实例变量值

    11.养成良好习惯,显示声明UID

      当一个继承了Serializable接口,这个类就可以被序列化。继承Serializable的目的是为了可持久化,如果网络传输或本地存储,为系统的分布和异构部署提供先决支持条件,如果没有序列化,那么远程调用、对象数据库都不存在。

      序列化:就是将一个对象从内存块转换为可传输的数据流

      反序列化:将对象的数据流转换为一个实例对象

      问题:当序列化和反序列化所对于的版本不一致就会抛异常InvalidClassException,JVM不能将数据流转为实例对象。JVM是通过serialVersionUID来判断序列化和反序列化所对于的版本是否一致的,所以就需要声明serialVersionUID

      建议显示声明seriavalVersionUID,级,将鼠标指向该类,然后选则Add default serial version ID或者Add generated serial Version ID

      

      Add default serial version ID:其值是private static final long serialVersionUID = 1L;当对类进行了不兼容性修改时,需要修改UID,建议选择这种

      Add generated serial Version ID:如果修改了属性,不重新生成UID时,默认值是不会变的,也可以正常反序列化,但不推荐,毕竟UID的值与实际不符。 

      隐士声明UID:

    12.在序列化的类中,不使用构造函数为final变量赋值

      序列化修饰的类中,如果final修饰的属性是一个直接量(不变量),在反序列化时就会重新计算其值。

      例:下列代码name如果重新修改了值,然后在反序列化,那么结果就是修改后的值

    public class TestClass implements Serializable {
        private static final long serialVersionUID = 1L;
        private final String name = "张三" ;    
    }

      但是,如果是通过构造方法来赋值,那么修改后的值是不会变的。因为反序列化时构造函数不会执行。

      例:如果修改了name的值,其值是不会改变的

    public class TestClass implements Serializable {
    
        private static final long serialVersionUID = 1L;
        private final String name ;
        
        public TestClass(){
            this.name = "张三" ;
        }
        
    }

      反序列化的过程:JVM从数据流中获取一个Object对象,然后根据数据流中的类文件描述信息,发现name是final变量,需要重新技术其值,于是就引用TestClass中的name值,但是此时JVM发现name没有赋值,不能引用,于是它就不在初始化,保存原值状态,所以name的值就不变

      规则:

        保持新旧对象的final变量相同,是序列化的基本规则之一

        反序列化时构造函数不会执行

    13.反序列化时,final在以下情况不会被重新赋值

      (1):通过构造函数为final变量赋值 

      (2):通过方法返回值为final变量赋值

      (3):final修饰的属性不是基本类型

    14.使用序列化的私有方法,巧妙解决部分属性持久化方法,private void writeObject(ObjectOutputStream out)和private void readObject(ObjectInputStream in)

      序列化机制:序列化回调。Java调用ObjectOutputStream类把一个对象转换成数据流时,会通过反射检查被序列化的类中是否有writeObject方法,且方法是私有、无返回的

                        如果有,就委托该方法进行序列化,没有,则由ObjectOutputSream按照默认规则继续序列化。同样,在由流数据恢复成实例对象时,也会检查是否有一个私有                             的readObject()方法,有就会通过该方法读取属性值。

    public class TestClass implements Serializable {
    
        private static final long serialVersionUID = 1L;
        private String name ;
        private transient Salary salary ;
        
        public TestClass(String name,Salary salary){
            this.name = name ;
            this.salary = salary ;
        }
        
        private void writeObject(ObjectOutputStream out) throws IOException{
            out.defaultWriteObject(); 
            out.writeObject(salary.getBase());
        }
        
        private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException{
            in.defaultReadObject(); 
            salary = new Salary(in.readDouble(),0.0) ;
        }
        
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Salary getSalary() {
            return salary;
        }
        public void setSalary(Salary salary) {
            this.salary = salary;
        }
        
    }

     

      

     

  • 相关阅读:
    P2330 05四川 繁忙的都市
    Winform中实现更改DevExpress的RadioGroup的选项时更改其他控件(TextEdit、ColorPickEdit)的值
    Winform中实现读取xml配置文件并动态配置DevExpress的RadioGroup的选项
    Winform中对DevExpress的RadioGroup进行数据源绑定,即通过代码添加选项
    Winform中对自定义xml配置文件进行Xml节点的添加与删除
    Winform中自定义xml配置文件后对节点进行读取与写入
    C#中使用StreamReader实现文本文件的读取与写入
    Python编程书籍高清PDF免费下载
    Winform中自定义xml配置文件,并配置获取文件路径
    Winform中实现ZedGraph新增自定义Y轴上下限、颜色、标题功能
  • 原文地址:https://www.cnblogs.com/-scl/p/7613951.html
Copyright © 2020-2023  润新知