• 廖雪峰Java4反射与泛型-3泛型-7泛型和反射


    1.部分反射API是泛型

    1.1获取反射API的泛型

    部分反射API是泛型,如Class<T>是泛型
    
           //如果使用Class,不带泛型,出现compile warning编译警告
            Class clazz1 = String.class;
           String str1 = (String) clazz1.newInstance();
            //改写为带泛型的Class,如Class<T>是泛型,
           Class<String> clazz2 = String.class;
           String str2 = clazz2.newInstance();//不用转型,直接得到
            Class<? super String> sup = clazz2.getSuperclass();
    

    1.2获取Constructor的泛型

    Constructor<T>是泛型
    
            Class<Integer> clazz = Integer.class;
            Constructor<Integer> cons = clazz.getConstructor(int.class);
            Integer i = cons.newInstance(123);
    

    2.泛型数组

    可以声明带泛型的数组,但不能用new创建带泛型的数组:

            Pair<String>[] ps1 = null;//声明带泛型的数组
            Pair<String>[] ps2 = new Pair<String>[2];//用new创建带泛型的数组,报错
    

    必须通过强制转型实现带泛型的数组:

            @SuppressWarnings("unchecked")
            Pair<String>[] ps3 = (Pair<String>[]) new Pair[2];
    

    使用泛型数组要特别小心

    2.1不安全的使用泛型数组

    public class Main {
        public static void main(String[] args) {
            Pair[] arr = new Pair[2];
            Pair<String>[] ps = (Pair<String>[]) arr;//arr和ps是同一个对象
    
            ps[0] = new Pair<String>("a","b");//指定ps[0]
            arr[1] = new Pair<Integer>(1,2);//指定ps[1]
            /**
             * Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
             * 	at com.testArray.Main.main(Main.java:15)
             */
            Pair<String> p = ps[1];
            String s = p.getFirst();//ps[1]是Integer类型,报错
        }
    }
    

    2.2安全的使用泛型数组

    public class Main {
        public static void main(String[] args) {
            //扔掉arr的引用,就只能针对ps进行操作,这种引用就是安全的
            @SuppressWarnings("unchecked")
            Pair<String>[] ps = (Pair<String>[]) new Pair[2];
    
            ps[0] = new Pair<String>("a","b");
            Pair<String> p = ps[1];
            String s = p.getFirst();
        }
    }
    

    2.3带泛型的数组实际上是编译器的类型擦除

    public class Main {
        public static void main(String[] args) {
            Pair[] arr = new Pair[2];
            Pair<String>[] ps = (Pair<String>[]) arr;
    
            ps[0] = new Pair<String>("a","b");//指定ps[0]
            System.out.println(ps.getClass() == arr.getClass());
            String s1 = (String) arr[0].getFirst();
            String s2 = ps[0].getFirst();
            System.out.println(s1);
            System.out.println(s2);
        }
    }
    
    ### 2.4不能直接创建T[]数组 ```#java //不能直接创建T类型的数组,因为擦拭后代码变为new Object的数组,即new Object[5] class Abc{ T[] createArray(){ return new T[5]; } } ``` ```#log 方法一:必须借助Class ``` ```#java class Abc{ T[] createArray(Class cls){ return (T[]) Array.newInstance(cls,5); } } ``` ```#log 方法二:利用可变参数创建T[]数组 ``` ```#java public class ArrayHepler { @SafeVarargs static T[] asArray(T... objs){ return objs; } public static void main(String[] args){ String[] ss = asArray("a","b","c"); Integer[] ii = asArray(1,2,3); } } ``` ## 3.实例 ```#java import java.lang.reflect.Constructor; import java.util.Arrays;

    public class Main {
    public static void main(String[] args) throws Exception{
    //创建一个泛型对象,通过其创建String对象
    Class clazz = String.class;
    String s1 = clazz.newInstance();
    System.out.println(s1);

        //创建一个范型的Constructor对象,通过其创建String对象
        Constructor<String> cons = clazz.getConstructor(String.class);
        String s2 = cons.newInstance("Hello");
        System.out.println(s2);
    
        //创建一个泛型数组
        Pair<String>[] ps = (Pair<String>[]) new Pair[2];//先创建Pair数组再转型
        ps[0] = new Pair<>("a","b");
        ps[1] = new Pair<>("x","y");
        System.out.println(Arrays.toString(ps));
    }
    

    }

    <img src="https://img2018.cnblogs.com/blog/1418970/201903/1418970-20190305215015922-1467877953.png" width="500" />
    
    ##    4.总结:
    *    部分反射API是范型:
    ```#log
            Class<T> 
            Constructor<T>
    
    • 可以声明带泛型的数组,但不能直接创建带泛型的数组,必须强制转型
    • 可以通过Array.newInstance(Class, int)创建T[] 数组,需要强制转型
  • 相关阅读:
    转:va_list、va_start、va_arg、va_end的原理与使用
    学习Docker的记录
    Google Code 优秀的开源工具
    转载(程序在内存中运行的奥秘)
    C# 和 Java 之争之我见
    揭秘ASP.NET 2.0的Eval方法(转)
    IIS6.0 架构(二)
    IE6 position:fixed bug (固定窗口方法)(转载)
    用FileStream上传图片转换成二进制,在本地用行,传到服务器上去出现如下错误
    异常处理
  • 原文地址:https://www.cnblogs.com/csj2018/p/10426470.html
Copyright © 2020-2023  润新知