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. 2017.4.5 OpenStack简介

    OpenStack 管理的资源不是单机的而是一个分布的系统,把分布的计算.存储.网络.设备.资源组织起来,形成一个完整的云计算系统:OpenStack 也提供一个 UI,这里包括一个图形化的 UI:H ...

  2. 【BZOJ2300】【SCOI2011】糖果

    差点就忘了还有差分约束这个东西……看见了就要学习一个 原题: 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要 ...

  3. ios存储图片注意

    以下方法可以解决 ios不能长按图片保存到手机的问题 -webkit-touch-callout:default;

  4. imrersize函数

    imrersize函数: 用法:imresize(图像I,method,倍数) 'nearest'(默认值)最近邻插值'bilinear'双线性插值'bicubic'双三次插值 使用方法: clear ...

  5. gorm-Duplicate-entry

    gorm  insert  data to mysql tips: (Error 1062: Duplicate entry '267857' for key 'PRIMARY') reason: u ...

  6. 取消svn关联文件夹

    svn没有自带取消svn关联功能,所以我们需要以下脚本 Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SOFTWARE\Classe ...

  7. NPOI之Excel——设置单元格背景色

    NPOI Excel 单元格颜色对照表,在引用了 NPOI.dll 后可通过 ICellStyle 接口的 FillForegroundColor 属性实现 Excel 单元格的背景色设置,FillP ...

  8. System.Windows.Forms.Timer、System.Timers.Timer、System.Threading.Timer的 区别和用法

    System.Windows.Forms.Timer执行的时候,如果你在过程中间加一个sleep整个的界面就死掉了,但是另外两个没有这个情况,System.Timers.Timer.System.Th ...

  9. 短信验证登陆-中国网建提供的SMS短信平台

    一.JAVA发送手机短信常见的有三种方式(如下所列): 使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册 使用短信mao的方式进行短信 ...

  10. windows删除文件或目录CMD命令

    rd/s/q 盘符:\某个文件夹  (强制删除文件文件夹和文件夹内所有文件)del/f/s/q 盘符:\文件名  (强制删除文件,文件名必须加文件后缀名)