利用反射取得泛型的类名和属性名
来源:互联网 发布:免费手机qq群发软件 编辑:程序博客网 时间:2024/05/20 09:10
一般的我们方法大多都会使用到泛型,那么,我们是否可以取得泛型的实例呢?
答案是可以的。我们可以使用java中的反射技术来实现对方法中泛型对象的实例化。下面,我们来进一步探讨。
1.放射泛型需要使用到的类:
import java.lang.reflect.Field; // 取得对象中的全部属性
import java.lang.reflect.Modifier; // 取得对象中的修饰符(因为返回的是int类型,因此需要使用Modifier.toStirng()方法解析)
import java.lang.reflect.ParameterizedType; //得到泛型中对象的全部信息
import java.lang.reflect.Type; //java语言中所有类型的公共父接口(可用可不用)
二:代码图
①实体类
public class Customer {
// ---------------------->用户资料<----------------------
private String name ;
private String password ;
private int money ;
//---------------------->方法<----------------------
public Customer(String name, String password, int money) { //相当于实体层
super();
this.name = name;
this.password = password;
this.money = money;
}
public Customer() {
}
// toSytring 方法
public String toString() {
return "Customer对象实例化好了";
}
//省略了get和set方法
}
②父类接口类:
public interface BaseCustomer<T> { // DAO公共接口层
String getClassName() ; // 得到类名
String getMassage() ; // 查看类的属性的全部的名字(包括修饰符之类的)
T getInstance() ; // 得到类的实例
}
--------------------------->
③父类实现类:
public class BaseCustomerImpl<T> implements BaseCustomer<T> {//相当于DAO的公共的实现层
// ---------------------->属性<----------------------
private Class<T> clazz ; // 泛型的 class
T t ; // 泛型的实例
// ---------------------->方法<----------------------
// 得到 Class 的类的名字
public String getClassName() {
String name = clazz.getSimpleName() ;
return name;
}
// 在实例化的时候得到泛型的class
public BaseCustomerImpl() { // 相当于DAO的到公共实现层
ParameterizedType pz = (ParameterizedType) this.getClass().getGenericSuperclass() ;//子类必须明确泛型的具体类型
// 由于 ParameterizedType 中的 getActualTypeArguments() 返回的是一个数组
// 因此如果泛型只有一个,就需要指定下标
this.clazz = (Class<T>) pz.getActualTypeArguments()[0] ;
}
// 查看类的属性的全部的名字(包括修饰符之类的)
public String getMassage() {
StringBuffer beffer = new StringBuffer() ;
// 通过反射得到类中的具体信息
// 得到属性名
Field[] fields = clazz.getDeclaredFields() ;
for(int i = 0 ;i < fields.length; i++) {
// 将数组中的东西遍历出来
int mo = fields[i].getModifiers() ; // 得到修饰符的数字
String modifier = Modifier.toString(mo) ; // 还原修饰符
String type = fields[i].getType().getName() ; // 得到数据类型
beffer.append( modifier + " " + type + " " + fields[i].getName() + " ;") ;
if(i != fields.length - 1) {
beffer.append("\n") ;
}
}
return beffer.toString() ;
}
// 得到类的实例
public T getInstance() {
try {
t = clazz.newInstance() ; // 使用泛型来实例化对象
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return t ;
}
}
--------------------------------------------->
④子类实现类:
// 相当于DAO的具体实现层
public class CustomerImpl extends BaseCustomerImpl<Customer> { // 子类明确指定了Customer为泛型的具体类型---------------->重点!!!
// 必须在子类中指定泛型的具体类型,否则会在实例化ParameterizedType中
// 抛出 java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType异常
// 该异常是说将class强制转ParameterizedType错误,因为class<T>中T的类型不明确
}
--------------------------------------------->
⑤测试类:
public class test {
public static void main(String[] args) {
BaseCustomer cm = new CustomerImpl() ;
System.out.println("类的名字-------------->" + cm.getClassName()) ;
System.out.println() ;
System.out.println("类的属性-------------->") ;
System.out.println(cm.getMassage());
System.out.println("类的属性-------------->") ;
System.out.println() ;
System.out.println("类的实例-------------->" + cm.getInstance().toString()) ;
}
}
⑥结果图:
类的名字-------------->Customer
类的属性-------------->
private java.lang.String name ;
private java.lang.String password ;
private int money ;
类的属性-------------->
类的实例-------------->Customer对象实例化好了
三.分析错误及其解决办法:
出现错误:java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
原因:在BaseCustomerImpl 中指定了泛型,但是却没有在子类中明确其泛型的具体的类型时,就会报错。
例如 :
①子类在继承类或者是实现接口时没有明确指定泛型的具体类型
public class CustomerImplextends BaseCustomerImpl<T> {// 子类没有明确指定泛型的具体类型(如果将T 明确为Customer就不会报错)
// 此时就会抛出 java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType异常
// 该异常是说将class强制转ParameterizedType错误,因为class<T>中T的类型不明确
}
②直接在实例化对象时指定泛型对象(继承时没有明确指定泛型对象类型)
public class test {
public static void main(String[] args) {
BaseCustomer<Customer> cm = newBaseCustomerImpl<Customer>() ;
// 即使是这样使用,还是会抛出java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType异常
//直接在测试类中指定泛型类型,而继承时没有指定,会报错
// 重点----->所以必须有个子类明确其具体的类型,即其必须要有子类来继承 BaseCustomerImpl类 或者是 BaseCustomerImpl类 实现接口时明确泛型的具体类型
}
}
①再写一个子类继承这个类,子类可以没有任何属性和方法,但必须指明泛型类型,然后使用子类创建对象
②写一个含有Class<T>类型的构造方法,在使用该类创建对象时给出具体类型
四.谨记:
一定要在定义类的时候定义泛型的具体的类型,才能获得类的反射(即在子类继承类 或 实现接口 的时候,明确泛型的类型)
新人初写,不好之处请多多指教和包涵。
- 利用反射取得泛型的类名和属性名
- C# 利用反射,遍历获得一个类的所有属性名,方法名,成员名.
- 【动态页面】(三)之一:利用Java反射机制读取Jar包的类名和属性名
- java反射获取类的属性名和属性值
- 利用反射通过属性名获得属性的值
- java利用反射获取类属性名,获取JavaBean属性名
- 利用反射,得到javaBean中的属性名
- 反射获取属性名和属性值
- java利用反射获取对象类名以及对象属性名
- java反射得到类的属性名和属性值并且放入Map中
- as遍历对象的属性名(反射和直接遍历)
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值
- caffe---create自己的数据出现的各种bug
- JavaScript面向对象和高级05
- web-侧边栏
- Entity Framework Code First使用DbContext查询
- 基于JsonObject的消息载体JsonObjectResult
- 利用反射取得泛型的类名和属性名
- 07 OrangePi 配置telnet服务
- 树莓派+motion安装摄像头实现远程监控
- JavaScript面向对象和高级06
- <胜过幽暗>读后感
- 基础知识
- 高通sensor core培训笔记
- 【Redis学习】:Linux环境下的Redis安装与配置
- Vue2.X的路由和钩子函数