泛型和Class类

在反射中使用泛型Class<T>可以避免强制类型转换,下面是一个简单例子,如果不使用泛型的话,需要显示转换,

 package aop;

 import java.util.Date;

 import javax.swing.JFrame;

 public class ObjectFactory {
public static Object getInstance(String clsName) {
try {
Class cls = Class.forName(clsName);
return cls.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public static void main(String[] args) {
Date d = (Date)ObjectFactory.getInstance("java.util.Date");
JFrame f = (JFrame)ObjectFactory.getInstance("java.util.Date");
}
}

上面的例子第19行和20行都需要将Class的newInstance返回的Object结果强制转换成目标类型,这不仅麻烦,更重要的是有些情况下无法发现错误,

例如第20行,强制转换可以通过编译的,但是运行期间可能会报错,原因是强制将Date类型转换成JFrame类型,类型不匹配,下面是执行结果,

1 Exception in thread "main" java.lang.ClassCastException: java.util.Date incompatible with javax.swing.JFrame
2 at aop.ObjectFactory.main(ObjectFactory.java:20)

下面用泛型来实现getInstance,  即  public static <T> T getInstance(Class<T> cls)

 package aop;

 import java.util.Date;

 import javax.swing.JFrame;

 public class ObjectFactory2 {
public static <T> T getInstance(Class<T> cls) {
try {
return cls.newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
} public static void main(String[] args) {
Date d = ObjectFactory2.getInstance(Date.class);
JFrame f = ObjectFactory2.getInstance(JFrame.class);
}
}

上面的第19行如果类型不符,例如写成了JFrame f = ObjectFactory2.getInstance(Date.class); , 则无法通过编译,

必须要修改成匹配的类型才能通过编译, 很好地编码了隐形错误。

泛型和数组

泛型中的数组虽然也使用了泛型编程,但却没有实现泛型功能, 泛型数组的newInstance方法签名是这样的,

 public static Object newInstance(Class<?> componentType, int... dimensions)

虽然上面的定义也使用了泛型,但是却没有真正实现泛型,所以这个方法返回的对象arr依然是个Object类型,要当成数组使用的话还是需要强制转换成数组类型。

如果将上面的方法签名改成这样,

 public static <T> T[] newInstance(Class<T> componentType, int length)

这样返回的arr就是个数组类型了,无需强制转换就可以当作数组用。

下面是一个将反射(reflect)中的Array的newInstance包装成泛型之后再使用的例子,

 package aop;

 import java.lang.reflect.Array;

 public class MyArray {
public static <T> T[] newInstance(Class<T> componentType, int length) {
return (T[])Array.newInstance(componentType, length);
} public static void main(String[] args) {
//使用MyArry的newInstance创建数组
String[] arr = MyArray.newInstance(String.class, 10);
//使用MyArray的newInstance创建二维数组
int[][] intArr = MyArray.newInstance(int[].class, 5);
arr[5] = "天王盖地虎";
intArr[1] = new int[]{23,12};
System.out.println(arr[5]);
System.out.println(intArr[1][1]);
}
}

输出结果, 可以看到上面已经刻在无需强制转换成数组的情况下,直接将arr和intArr作为数组来使用了,

 天王盖地虎
12

使用反射来获取泛型信息

通过反射可以获取指定类的成员变量, 方法是 Field f = clazz.getDeclaredField("成员变量名称");

之后,可以用f对象获取它的类型,对于普通类型的成员变量,可以用Class<?> a = f.getType(); 方式获取

但是对于泛型的成员变量,例如 Map<String, Integer> score; getType()只能获取原始类型,这里是Map

如果要获取泛型类型(即尖括号里面的参数类型),

  1. 首先需要获取成员变量的泛型类型, 通过Type gType = f.getGenericType();
  2. 然后将泛型对象gType强制转换成参数化类型ParameterizedType的对象pType;  (ParameterizedType包含两个方法,getRawType(), 返回原始类型,和上面的getType一样。getActualTypeArguments(), 返回泛型参数的类型,也就是Map<String, Integer> 括号里的类型)
  3. 使用getActualTypeArguments()返回泛型信息

下面来演示一下使用反射来获取泛型信息,

 package aop;

 import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map; public class GenericTest {
private Map<String, Integer> score;
public static void main(String[] args) throws Exception {
Class<GenericTest> clazz = GenericTest.class;
Field f = clazz.getDeclaredField("score");
//getType只能取出普通类型,因此下面的a只能得到java.util.Map类型
Class<?> a = f.getType();
System.out.println("score的类型是: " + a);
//获取泛型类型
Type gType = f.getGenericType();
// 如果gType类型是ParameterizedType对象
if (gType instanceof ParameterizedType) {
//泛型对象强制转换成参数化类型对象
ParameterizedType pType = (ParameterizedType)gType;
//获取原始类型,即java.util.Map
Type rType = pType.getRawType();
System.out.println("原始类型: "+rType);
//获取泛型括号里面参数的类型
System.out.println("泛型参数类型:");
Type[] tArgs = pType.getActualTypeArguments();
for (int i = 0; i < tArgs.length; i++ ) {
System.out.println("第["+i+"]个参数的泛型类型是: "+tArgs[i]);
}
} else {
System.out.println("获取泛型类型错误");
}
}
}

输出结果,

 score的类型是: interface java.util.Map
原始类型: interface java.util.Map
泛型参数类型:
第[0]个参数的泛型类型是: class java.lang.String
第[1]个参数的泛型类型是: class java.lang.Integer

JAVA基础知识之JVM-——反射和泛型的更多相关文章

  1. C# 基础知识系列- 10 反射和泛型(二)

    0. 前言 这篇文章延续<C# 基础知识系列- 5 反射和泛型>,继续介绍C#在反射所开发的功能和做的努力.上一篇文章大概介绍了一下泛型和反射的一些基本内容,主要是通过获取对象的类型,然后 ...

  2. JAVA基础知识之JVM-——使用反射生成并操作对象

    Class对象可以获取类里的方法,由Method对象表示,调用Method的invoke可以执行对应的方法:可以获取构造器,由Constructor对象表示,调用Constructor对象的newIn ...

  3. JAVA基础知识之JVM-——通过反射查看类信息

    Class实例 当类被加载之后,JVM中就会生成一个Class实例,通过这个实例就可以访问JVM中的这个类.有三种方式可以获取Class对象 使用Class的静态方法forName(完整包名) 调用类 ...

  4. Java基础知识笔记(二:泛型和枚举)

    1.泛型 与面向对象的多态性相类似,应用泛型可以提高程序的复用性.与多态性不同的是,应用泛型可以减少数据的类型转换,从而提高代码的运行效率.泛型实际上是通过给类或接口增加类型参数实现的.不带泛型的类的 ...

  5. java 基础知识学习 JVM虚拟机参数配置

    1) 设置-Xms.-Xmx相等: 2) 设置NewSize.MaxNewSize相等: 3) 设置Heap size, PermGen space: Tomcat 的配置示例:修改%TOMCAT_H ...

  6. Java开发培训基础知识解析之反射机制

    Java是老牌编程语言,是当前应用最广泛的编程语言之一.想要学习Java你就一定要掌握Java基础知识,而反射对于初学Java的人来说绝对是非常重要的知识点.什么是反射?如何理解反射机制?如何使用反射 ...

  7. 学习Spring必学的Java基础知识(1)----反射(转)

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  8. 学习Spring必学的Java基础知识(1)----反射

    引述要学习Spring框架的技术内幕,必须事先掌握一些基本的Java知识,正所谓"登高必自卑,涉远必自迩".以下几项Java知识和Spring框架息息相关,不可不学(我将通过一个系 ...

  9. JAVA基础知识|java虚拟机(JVM)

    一.JVM简介 java语言是跨平台的,兼容各种操作系统.实现跨平台的基石就是虚拟机(JVM),虚拟机不是跨平台的,所以不同的操作系统需要安装不同的jdk版本(jre=jvm+类库:jdk=jre+开 ...

  10. Java基础知识总结(超级经典)

    Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java ...

随机推荐

  1. F面经prepare:strstr变种

    * Given an integer k>=1 and two strings A and B (length ~n each); * Figure out if there is any co ...

  2. angular 和jq 的AJAX的请求区别

    最近项目中使用angular,结果发现后台没法获取参数,所以,稍微研究了一下两者在发送ajax时的区别. 注意angular和jquery的ajax请求是不同的. 在jquery中,官方文档解释con ...

  3. 两条直线(蓝桥杯)二分枚举+RMQ

    算法提高 两条直线   时间限制:1.0s   内存限制:256.0MB        问题描述 给定平面上n个点. 求两条直线,这两条直线互相垂直,而且它们与x轴的夹角为45度,并且n个点中离这两条 ...

  4. 【你吐吧c#每日学习】11.10 C# Data Type conversion

    implicit explicit float f=12123456.213F int a = Convert.ToInt32(f); //throw exception or int a = (in ...

  5. javascript 一些常用的验证

    只能输入数字          onkeyup="this.value=this.value.replace(/[^\d]/g,'')" onafterpaste="th ...

  6. vs2010打包系统必备选择.net framework 3.5sp1编译错误的解决方法

    利用visual studio 2010进行打包程序,默认安装的是Framework 4.0,如果需要将3.5sp1打包到系统中一起安装(选择了"从与我的应用程序相同的位置下载系统必备组件& ...

  7. ArrayList和LinkList区别

    ArrayList和LinkList区别 前者是数组的数据结构,后者是链表的数据结构 前者应用于排序和查找,后者应用于插入删除

  8. paper 81:HDR成像技术

    什么是HDR?谈HDR照片的制作方法和效果 HDR,是英文High-Dynamic Range的缩写,意为“高动态范围”.这是一个简单的术语,HDR照片是使用多张不同曝光的图片,然后再用软件将其叠加合 ...

  9. js this 闭包

    var myObject = { value :, increment:function (inc){ ; } }; myObject .increment(); console.log(myObje ...

  10. oracle ebs request一直pending

    如果提交请求以后,状态一直是pending状态,可以在“工具”打开“Manager”,查看一下Maximum是否有设置错,另外pending的数量当前是多少. 如果Maximum是1,pending是 ...