常犯指数3颗星-泛型序列化

发布时间 2023-06-19 00:39:29作者: shine-rainbow

泛型、反射、编译优化

实现了Serializable接口缺报错怎么办?

序列化和反序列化

  • 序列化:将对象写入到IO流中
  • 反序列化:从IO流中恢复对象

Serializable接口:是一个标记接口,不用实现任何方法,标记当前类对象是可以序列化的

序列化需要考虑哪些问题?

  • 子类实现序列化接口,父类没有实现,那么,子类可以序列化吗?

只要父类实现了无参构造函数,子类可以序列化

  • 类中存在引用对象,那么,这个类对象在什么情况下可以实现序列化呢?

类中所有的对象都是可序列化的,才可以实现序列化

  • 同一个对象多次序列化(之间有属性更新),会影响序列化吗?

会影响到序列化

泛型不仅仅是规定集合中的类型那么简单

  • 什么是泛型

泛型就是参数化类型,就是将类型由原来的具体的类型参数化

  • 为什么要使用泛型

能够在不创建新类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型

类型擦除:编译期间,编译中不包含类型信息

 private static void easyUse() throws Exception {

//        List<String> left = new ArrayList<>();
//        List<Integer> right = new ArrayList<>();
//
//        System.out.println(left.getClass());
//        System.out.println(left.getClass() == right.getClass());

//        if(left instanceof ArrayList<String>){
//
//        }

        // 正确写法
//        if(left instanceof ArrayList){
//
//        }
//        if(left instanceof ArrayList<?>){
//
//        }
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.getClass().getMethod("add",Object.class).invoke(list,"abcd");
        list.getClass().getMethod("add",Object.class).invoke(list,"1.2");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }

运行结果: 对于left.getClass()会返回ArrayList,对于两个类型是否相等,自然会返回true,因为都是ArrayList。利用反射在运行期间塞入不同类型的值,是可以通过成功输出的。原因就在泛型参数类型擦除

image-20230619000750627

  • 泛型是先检查在编译的

如下图,在编译前先检查已经出现报错了

image-20230619001410099

  • 泛型不支持继承
private static void genericityCanNotExtend(){
        // 第一类错误 引用传递不支持继承
//        ArrayList<String> first = new ArrayList<Object>();
//
//        ArrayList<Object> list1 = new ArrayList<>();
//        list1.add(new Object());
//        ArrayList<String> list2 = list1;

        // 第二类错误
        ArrayList<Object> second = new ArrayList<String>();

        ArrayList<String> list1 = new ArrayList<>();
        list1.add(new String());
        ArrayList<Object> list2 = list1;


}

image-20230619002122502

  • 泛型类型变量不能是基本数据类型
/**
  * 泛型类型变量不能是基本数据类型: 类型擦除后是Object类型,不能存储int数据类型
  */
private static void baseTypeCanNotUseGenericity(){
    List<int> invalid = new ArrayList<>();

}
  • 泛型的参数类型只能是类类型
 /**
   * 泛型的类型参数只能是类类型,不能是简单类型
   */
private static <T> void doSomeThing(T... values){
    for(T value:values){
        System.out.println(value);
    }
}

举例:泛型类相参数 分别是 类类型和 简单类型

 /**
   * 泛型的类型参数只能是类类型,不能是简单类型
   */
private static <T> void doSomeThing(T... values){
    for(T value:values){
        System.out.println(value);
    }
}

    public static void main(String[] args) throws Exception {
        Integer [] inst1 = new Integer[]{1,2,3};
        int[] inst2 = new int[]{1,2,3};

        doSomeThing(inst1);

        System.out.println("---------------");
        doSomeThing(inst2);
    }

输出结果:类类型被正确打印,而简单类型将数组整体作为泛型类型值打印。

image-20230619003020794