未完 Java Marker interfaces | 标识接口 | 序列化 & 克隆

Marker interfaces:
又叫Tagging Interfaces。标识接口是没有任何方法和属性的接口。标识接口不对实现它的类有任何语义上的要求,它仅仅表明实现它的类属于一个特定的类型。常见的有Serializable Cloneable Remote EventListener
你当然可以任意定义没有任何方法和属性的接口,但肯定不应该称为标识接口,因为JDK里的“标识接口”不光是“只有个名字”这么简单,更重要的是,实现这些标志接口的类,确实多了功能,尽管你看不到这些功能是怎么实现的。比如,Serializable,实现了这个接口,那这个序列化的工作,到底是谁做的那?Cloneable,实现了这个接口,并在重写的clone()方法里只是调用了一下super.clone(),就产生了一个全新的对象,要知道Object里的clone()方法是没有任何实现的,这个克隆的工作,到底是谁完成的那?JVM or Reflection,但是你看不到它们。
关于标志接口的对于错,争论是有的:
标志接口是对接口的误用,应该被避免,使用标志接口的类,都是一些相当古老的类。Java 5 加入 注解 特性后,标志接口更不会再有出现的必要。
[url]http://www.coderanch.com/how-to/java/Java-FAQ#marker[/url]
[url]http://www.artima.com/intv/issuesP.html[/url]
也有持不同意见的,详见 Effective Java Item 37.


[b]常用的标识接口:[/b]
[b]Serializable:[/b]
1 类变量和标记为transient的变量不会被序列化;
2 序列化使用 ObjectOutputStream ,反序列化使用FileInputStream
3 如果对象在序列化及反序列化的过程中需要做一些特殊的处理,那么你需要在对象所在类里加入下面的方法:

private void writeObject(ObjectOutputStream oos)
throws IOException {
oos.defaultWriteObject();
// Write/save additional fields
oos.writeObject(new java.util.Date());
}

// assumes "static java.util.Date aDate;" declared
private void readObject(ObjectInputStream ois)
throws ClassNotFoundException, IOException {
ois.defaultReadObject();
// Read/initialize additional fields
aDate = (java.util.Date)ois.readObject();
}

[url]http://java.sun.com/developer/technicalArticles/ALT/serialization/[/url]
[url]http://www.tutorialspoint.com/java/java_serialization.htm[/url]
[url]http://bluepopopo.iteye.com/blog/486548[/url]
[url]http://www.ibm.com/developerworks/cn/java/j-lo-serial/index.html[/url]


[b]Cloneable & Object.clone():[/b]
1
[quote]浅拷贝:只复制一个对象(包括其为基本类型、String的属性),对象内部存在的指向其他对象数组或者引用则不复制

深拷贝:对象,对象内部的引用均复制


为了更好的理解它们的区别我们假设有一个对象A,它包含有2对象对象A1和对象A2:
[img]http://dl.iteye.com/upload/attachment/223405/beccc0f3-5fa4-30d3-b098-ac0f7a50d27d.jpg[/img]

对象A进行浅拷贝后,得到对象B但是对象A1和A2并没有被拷贝:
[img]http://dl.iteye.com/upload/attachment/223407/99530535-429e-3727-95ad-40fcdc92681a.jpg[/img]

对象A进行深拷贝,得到对象B的同时A1和A2连同它们的引用也被拷贝:
[img]http://dl.iteye.com/upload/attachment/223409/72656925-0994-36c1-a727-781a4dfa35f7.jpg[/img]

在理解了深拷贝和浅拷贝后,我们来看看Java的深拷贝和浅拷贝实现。java.lang.Object的clone()方法默认是返回一个浅拷贝对象。因此如果要用clone()方法实现一个深拷贝,我们必须对每个对象的clone()方法进行特别实现。当对象层次复杂的时候,这样做不但困难而且浪费时间和容易出现错误,特别有时候你不但需要深拷贝同时你也对这个对象进行浅拷贝的时候,你会发现写这个clone()方法真不是一个好的解决方案。

那么除了clone()方法,我们还可以怎么实现呢?答案是序列化,实现步骤和思路是把要拷贝的对象输出成byte array,然后再利用ObjectInputStream转换出新的对象。下面是代码:

public static Object copy(Object oldObj) {
Object obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(oldObj);
out.flush();
out.close();

// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream in = new ObjectInputStream(bis);
obj = in.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
[/quote]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值