2.3 泛型、序列化、复制

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和 List等类型,在编译之后都会变成 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;
        }
      }
      
      • 序列化
        • 当被复制对象中的引用变量比较多时,可以使用序列化进行复制
        • 将对象序列化然后再从流里读取,便可以重建对象

      你可能感兴趣的:(Java基础)