廖雪峰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 Abcpublic class Main {
public static void main(String[] args) throws Exception{
//创建一个泛型对象,通过其创建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[] 数组,需要强制转型