2.3 泛型、序列化、复制
泛型
-
泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型
-
泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
-
泛型方法
public static <E> void function(E[] input){ ... }
-
泛型类
class className<T>{ }
-
泛型接口
interface InterfaceName<T>{ }
-
类型通配符
publiv void test(List<? extends ... super ...> l){}
-
类型擦除
- Java 中的泛型基本上都是在编译器这个层次来实现的。在生成的 Java 字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉
- 基本过程:首先是找到用来替换类型参数的具体类。这个具体类一般是 Object。如果指定了类型参数的上界的话,则使用这个上界。把代码中的类型参数都替换成具体的类
- 如在代码中定义的 List<Object>和 List<String>等类型,在编译之后都会变成 List。JVM 看到的只是 List,而由泛型附加的类型信息对 JVM 来说是不可见的
序列化
- 为了在JVM停止运行之后能够保持指定的对象,并在将来重新读取被保存的对象
- 序列化对象以字节数组保持(静态成员不保存)
- 实现java.io.Serializable接口的类可被序列化
- ObjectOutputStream和ObjectInputStream对对象进行序列化和反序列化
- writeObject和readObject自定义序列化策略
- 虚拟机是否允许反序列化,不仅取决于类路径和功能代码是否一致,一个非常重要的一点是两个类的序列化 ID 是否一致(就是 private static final long serialVersionUID)
- Transient关键字可以阻止变量被序列化到文件中,在反序列化后,变量被设为初始默认值,如int为0,对象型为null
//序列化 Student stu = new Student();//实现Serializable接口 ... FileOutputStream f = null; ObjectOutputStream outp = null; try{ f = new FileOutputStream("file_path");//按照约定后缀为.ser outp = new ObjectOutputStream(f); outp.writeObject(stu); outp.close(); f.close(); }catch(IOException e){ ... } //反序列化 Student stu = null; FileIutputStream f = null; ObjectOutputStream ip = null; try{ f= new FileInputStream("file_path"); ip = new ObjectInputStream(f); stu = (Student)ip.readObject(); ip.close(); f.close(); }catch(IOException e){ ... }
复制
- 共三种方式
直接赋值复制
- 直接将一个变量赋值给另一个变量,如A=B,当B变化时,A也跟着变化
浅拷贝
- 被复制对象实现Clonenable接口
- 被复制对象的成员变量是值类型,则会复制一份拷贝;如果是引用类型c,复制的是地址,c变化时,被复制对象和复制对象的c也会改变
class Student implements Cloneable{ .. } Student s1 = new Student(); ... Student s2 = (Student)s1.clone();
深拷贝
- 重写引用成员变量的clone方法,再在被复制类中重写clone方法,对每个引用变量进行clone方法的调用
class A implements Cloneable{
...
@Override
public Object clone(){
A a = null;
try{
a = (A)super.clone();
}catch(CloneNotSuportedException e){..}
return a;
}
}
class B implements Cloneable{
...
A a;
@Override
public Object clone(){
B b = null;
try{
b = (B)super.clone();
}catch(CloneSupportedException e){..}
b.a = (A)a.clone();
return b;
}
}
- 序列化
- 当被复制对象中的引用变量比较多时,可以使用序列化进行复制
- 将对象序列化然后再从流里读取,便可以重建对象