1700439456
1700439457
//序列化委托方法
1700439458
1700439459
private void writeObject(java.io.ObjectOutputStream out)throws IOException{
1700439460
1700439461
out.defaultWriteObject();
1700439462
1700439463
out.writeInt(salary.getBasePay());
1700439464
1700439465
}
1700439466
1700439467
//反序列化时委托方法
1700439468
1700439469
private void readObject(java.io.ObjectInputStream in)throws IOException, Class-
1700439470
1700439471
NotFoundException{
1700439472
1700439473
in.defaultReadObject();
1700439474
1700439475
salary=new Salary(in.readInt(),0);
1700439476
1700439477
}
1700439478
1700439479
}
1700439480
1700439481
其他代码不做任何改动,我们先运行看看,结果为:
1700439482
1700439483
姓名:张三 基本工资:1000 绩效工资:0。
1700439484
1700439485
我们在Person类中增加了writeObject和readObject两个方法,并且访问权限都是私有级别,为什么这会改变程序的运行结果呢?其实这里使用了序列化独有的机制:序列化回调。Java调用ObjectOutputStream类把一个对象转换成流数据时,会通过反射(Reflection)检查被序列化的类是否有writeObject方法,并且检查其是否符合私有、无返回值的特性。若有,则会委托该方法进行对象序列化,若没有,则由ObjectOutputStream按照默认规则继续序列化。同样,在从流数据恢复成实例对象时,也会检查是否有一个私有的readObject方法,如果有,则会通过该方法读取属性值。此处有几个关键点要说明:
1700439486
1700439487
(1)out. defaultWriteObject()
1700439488
1700439489
告知JVM按照默认的规则写入对象,惯例的写法是写在第一句话里。
1700439490
1700439491
(2)in. defaultReadObject()
1700439492
1700439493
告知JVM按照默认规则读入对象,惯例的写法也是写在第一句话里。
1700439494
1700439495
(3)out. writeXX和in.readXX
1700439496
1700439497
分别是写入和读出相应的值,类似一个队列,先进先出,如果此处有复杂的数据逻辑,建议按封装Collection对象处理。
1700439498
1700439499
可能有读者会提出,这似乎不是一种优雅的处理方案呀,为什么JDK没有对此提供一个更好的解决办法呢?比如访问者模式,或者设置钩子函数(Hook),完全可以更优雅地解决此类问题。我查阅了大量的文档,得出的结论是:无解,只能说这是一个可行的解决方案而已。
1700439500
1700439501
再回到我们的业务领域,通过上述方法重构后,其代码的修改量减少了许多,也优雅了许多。可能你又要反问了:如此一来,Person类也失去了分布式部署的能力啊。确实是,但是HR系统的难点和重点是薪水计算,特别是绩效工资,它所依赖的参数很复杂(仅从数量上说就有上百甚至上千种),计算公式也不简单(一般是引入脚本语言,个性化公式定制),而相对来说Person类基本上都是“静态”属性,计算的可能性不大,所以即使为性能考虑,Person类为分布式部署的意义也不大。
1700439502
1700439503
1700439504
1700439505
[
上一页 ]
[ :1.700439456e+09 ]
[
下一页 ]