java程序的151个建议(一)

建议12:避免用序列化类在构造函数中为不变量赋值


public class Client implements Serializable{
	
	private static final long serialVersionUID = -5492180880303604959L;
	public final String name="sea";
}
Client对象被序列化存储后,反序列化时name会被重新计算其值(跟static 变量不一样, static 变量压根不会被序列化存储),比如类中的name改为了“sky”,那么之前序列化的对象反序列化之后name也是“sky“,保持新旧对象的final变量一致,有利于代码业务逻辑统一,这是序列化的基本原则之一。如果final变量通过构造函数赋值呢,如下:

public class Client implements Serializable{
	
	private static final long serialVersionUID = -5492180880303604959L;
	public final String name;
	
	public Client(){
		name="sea";
	}
}

上边的的类 new Cliient()之后序列化存储,之后类被重写,name变为了”sky“, 并且保持serialVersionUID不变,改变后的类如下:

public class Client implements Serializable{
	
	private static final long serialVersionUID = -5492180880303604959L;
	public final String name;
	
	public Client(){
		name="sky";
	}
}


那么反序列化之后,name的值是什么呢?

答案是”sea“。

这时候大家可能会有疑问,final变量(不是static的)不是会被重新计算吗,但是”反序列化时构造函数不会执行“,所以还是”sea“。


建议13:避免为final变量进行复杂赋值

通过方法为final变量赋值,如下:

public class Client implements Serializable{
	
	private static final long serialVersionUID = -5492180880303604959L;
	public final String name=iniName();
	
	public String iniName(){
		return "sea";
	}
}

序列化存储后,iniName()返回值改为了”sky“,如下:

public class Client implements Serializable{
	
	private static final long serialVersionUID = -5492180880303604959L;
	public final String name=iniName();
	
	public String iniName(){
		return "sky";
	}
}

反序列化后,name的值还是sea。

上边说过final变量会被重新计算赋值,但是这个值 是值简单对象赋值,包括8个基本类型,数组,字符串(不通过new String()生成的字符串 final 赋值与基本类型一样),不能通过方法。


原理:保存到磁盘上(或者网络传输)的对象文件包括两部分:

(1)类描述信息

包括 包路径、继承关系、访问权限、变量描述、变量访问权限、方法签名、返回值,以及变量的关联类信息。它并不是class文件的翻版,它不记录方法、构造函数、static变量等的具体实现。

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

这里的值是基本类型,如果是复杂对象,连该对象和关联类信息一起保存,并且递归下去(关联类也必须实现Serializable接口,否则异常),其实还是基本数据类型的保存。


最后,总结一下,final变量在一下情况不会被重新计算赋值:

(1)通过构造函数赋值

(2)通过方法赋值

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值