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[] 数组,需要强制转型

廖雪峰Java4反射与泛型-3泛型-7泛型和反射的更多相关文章

  1. 廖雪峰Java4反射与泛型-3范型-4擦拭法

    1.擦拭法是Java泛型的实现方式. 编译器把类型视为Object. * 泛型代码编译的时候,编译器实际上把所有的泛型类型T统一视为Object类型.换句话说,虚拟机对泛型一无所知,所有的工作都是编译 ...

  2. 廖雪峰Java4反射与泛型-3范型-6super通配符

    1.super通配符 1.1super通配符第一种用法 泛型的继承关系 Pair<Integer>不是Pair<Number>的子类,如 static void set(Pai ...

  3. 廖雪峰Java4反射与泛型-3范型-5extends通配符

    1.泛型的继承关系: Pair<Integer>不是Pair<Number>的子类 add()不接受Pair<Integer> Pair.java package ...

  4. 廖雪峰Java4反射与泛型-3范型-3编写泛型

    编写泛型类比普通的类要麻烦,而且很少编写泛型类. 1.编写一个泛型类: 按照某种类型(例如String)编写类 标记所有的特定类型例如String 把特定类型替换为T,并申明 Pair.java pa ...

  5. 廖雪峰Java4反射与范型-3范型-1什么是泛型

    1.为什么需要泛型? JDK提供了ArrayList,可以看作"可变长度"的数组: 比数组使用方便 示例1:如果使用ArrayList存储String类型: 需要强制转型 不方便, ...

  6. 廖雪峰Java4反射与泛型-2注解-3处理注解

    1.处理注解 注解本身对对代码逻辑没有任何影响 SOURCE类型的注解在编译期就被丢掉了 CLASS类型的注解仅保存在class文件中 RUNTIME类型的注解在运行期可以被读取 如何使用注解由工具决 ...

  7. 廖雪峰Java4反射与泛型-1反射-2访问字段Field和3调用方法Method

    2.字段Field 2.1.通过Class实例获取字段field信息: getField(name): 获取某个public的field,包括父类 getDeclaredField(name): 获取 ...

  8. 廖雪峰Java4反射与泛型-1反射-1Class类

    1.Class类与反射定义 Class类本身是一种数据类型(Type),class/interface的数据类型是Class,JVM为每个加载的class创建了唯一的Class实例. Class实例包 ...

  9. 廖雪峰Java4反射与泛型-2注解-2定义注解

    1.定义注解 使用@interface定义注解Annotation 注解的参数类似无参数方法 可以设定一个默认值(推荐) 把最常用的参数命名为value(推荐) 2.元注解 2.1Target使用方式 ...

随机推荐

  1. linux---文件颜色含义

    下面是linux系统约定不同类型文件默认的颜色: 白色:表示普通文件 蓝色:表示目录 绿色:表示可执行文件 红色:表示压缩文件 浅蓝色:链接文件 红色闪烁:表示链接的文件有问题 黄色:表示设备文件 灰 ...

  2. CTEX(LaTeX) 编译 中文

    CTEX 中文编码&编译问题 #win10 tex 文档为 GBK 编码 https://zhidao.baidu.com/question/93645685.html \documentcl ...

  3. python argv传递参数

    test.pyimport sysprint(sys.argv) python test.py arg1 arg2 arg3 打印["test.py","arg1&quo ...

  4. HNOI2019 简要题解

    HNOI 2019 简要题解 没想到自己竟也能有机会写下这篇题解呢. LOJ Luogu Day1T1 鱼 枚举\(AD\)两点后发现\(BC\)与\(EF\)相对独立,因此只需要计算合法的\(BC\ ...

  5. day39KNN算法和其他的算法

    PS: 1.现在明白为什么其他的同学一直都在做数字图像处理,matlab这种东西了,因为机器学习,其他底层主要是做预先处理,然后调用某一个算法 2.感觉knn算法就是根据先验数据计算下一个跟自己一样不 ...

  6. Centos7——selinux配置

    临时关闭selinux setenforce 0 永久关闭selinux vi /etc/selinux/config 修改enforcing为disabled 情景一: httpd修改网站文件目录的 ...

  7. readv与writev

    [root@bogon mycode]# cat writev.c #include<stdio.h> #include<string.h> #include<unist ...

  8. UWA 转载

    性能优化,进无止境-内存篇 https://blog.uwa4d.com/archives/optimzation_memory_1.html https://blog.uwa4d.com/archi ...

  9. 网易的Airtest

    使用心得:https://testerhome.com/topics/12391 下载路径:https://airtest.netease.com/

  10. jquery 实现的全选demo

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script sr ...