一、问题
在之前的“关于使用反射机制得到泛型的字段名的问题”博客当中提到了问题,终于在看了《Effective Java》之后有所理解。
问题回顾
1、实体类
public class LSLSEntry {
private String storeguid;
private String checkguid;
private String isstoprunning;
public String _5801;
public String _5802;
public String _5803;
public String _6001;
public String _6002;
public String _6003;
public String _6101;
public String _6201;
public String _6301;
public String _6401;
public String _6501;
public String _6502;
public String _6601;
public String _6602;
public String _6701;
public String _6702;
public String _6703;
public String _6704;
public String _6801;
public String _6802;
public String _6803;
public String _6804;
public String _6805;
public String _7201;
public String _7401;
public String _7402;
public String _7403;
public String _7404;
public String _7601;
public String _7701;
public String _7702;
public String _7703;
public String _7704;
public String _7705;
public String _7706;
public String _7707;
public String _7708;
public String _7709;
public String _7801;
public String _7802;
public String _8001;
public String _8101;
public String _8102;
public String _8103;
public String _8104;
public String _8105;
public String _8106;
public String _8107;
public String _8108;
public String _8109;
public String _8110;
public String _8111;
public String _8112;
public String _8201;
public String _8301;
public String _8401;
public String _8402;
public String _8403;
public String _8404;
public String getStoreguid() {
return storeguid;
}
public void setStoreguid(String storeguid) {
this.storeguid = storeguid;
}
public String getCheckguid() {
return checkguid;
}
public void setCheckguid(String checkguid) {
this.checkguid = checkguid;
}
public String getIsstoprunning() {
return isstoprunning;
}
public void setIsstoprunning(String isstoprunning) {
this.isstoprunning = isstoprunning;
}
}
2、反射代码
import java.lang.reflect.Field;
import org.junit.Test;
public class TestReflect {
@Test
public void test() {
//可以得到字段名
LSLSEntry entry = new LSLSEntry();
printValue(entry);
}
@Test
public void test1() {
//得不到字段名,为什么???
printValue(LSLSEntry.class);
}
@Test
public void test2() {
//得不到字段名,为什么??
PrintInfo2<LSLSEntry> info = new PrintInfo2<LSLSEntry>(LSLSEntry.class);
info.printValue();
}
@Test
public void test3() {
//可以得到字段名
LSLSEntry entry = new LSLSEntry();
PrintInfo<LSLSEntry> info = new PrintInfo<LSLSEntry>(entry);
info.printValue();
}
@Test
public void test4() {
//可以得到字段名
Field[] fields = LSLSEntry.class.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
private <T> void printValue(T entry) {
Field[] fields = entry.getClass().getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
private class PrintInfo<T> {
T entry;
public PrintInfo(T entry) {
this.entry = entry;
}
private void printValue() {
Field[] fields = entry.getClass().getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
}
private class PrintInfo2<T> {
Class<?> entry;
public PrintInfo2(Class<?> entry) {
this.entry = entry;
}
private void printValue() {
Field[] fields = entry.getClass().getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
}
}
二、问题解答
1、源代码当中参数传递的错误。
public PrintInfo(T entry) {
this.entry = entry;
}
这种编写方式中T entry这样的参数表示的是引用的概念,同时这表示一个特定的类型。
类型推导
而这个类型的推导过程是由entry的类型所推导出来的。编译器通过检查方法参数的类型来计算类型参数的值。对于如public static <E> Set<E> union(Set<E> s1, Set<E> s2);
而言,编译器发现union的两个参数都是Set<String>类型,因此知道类型参数E必须为String。这个过程称作类型推导。
泛型特性
泛型在运行时会擦除掉的,因此T在运行时会被擦除掉,例如List<Integer>和List<String>在运行时都会解释为List。在向printValue传递*.class时传递的是类型信息,而非对具体实例的引用,而这时的类型信息被擦除掉了,entry成了Object。因此调用
entry.getClass().getFields();时得不到东西。
这样的错误同时在只传递*.class的方法或类的调用当中出现,因此出现了以上错误。
2、为什么class<?>可以
private void printValue12(Class<?> clazz){
System.out.println(clazz.getName());
Field[] fields = clazz.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
private <T> void printValue13(Class<T> clazz){
System.out.println(clazz.getName());
Field[] fields = clazz.getFields();
for (Field f : fields) {
System.out.println(f.getName());
}
}
两段代码可以呢?
原因还是在以上的解答,在这里,Class<?>存储的是类型信息,而传递来的.class正是类型信息。不管是Class<?>还是Class<T>都是类型信息,而T entry 这种方式传递的是引用。
三、总结
Class<?>是类型信息的概念。T entry 这种是引用的概念,在这种方式下有类型推导的过程。
正是因为对两者概念的不清楚导致了错误的产生。
分享到:
相关推荐
运用反射机制与泛型处理字符串 大家也可以看下练习下。
对java泛型以及反射机制进行原理和应用上的讲解,帮助初学者对这两个概念进行更轻松的掌握
反射和泛型是一种重要的解决途径。 此代码是一个生成泛型对象的类。 比如: Pool<Point> pool = new Pool(){}; Point p = pool.get(x, y); //在此构造Point对象 ... pool.put(p); 希望能帮助那些为查找泛型构造器、...
在C#中通过反射操作一个List泛型。。
泛型 反射 概念 方法 使用
java泛型+反射使用的源码,比较详细,欢迎下载
Java泛型和反射机制
通过反射创建带有泛型参数的类 1.Limin.Reflector.DLL中的BaseDal.cs里包含要创建的带泛型参数的类 2.Limin.Reflector.Invoke中的Factory.cs完成泛型类的创建 代码写的不是很好,不足之处,请多多指教
DataReader反射泛型实体对象。数据库已有。完整的例子。
java的基于泛型+反射的通用DAO例子,原创,没事写着玩的,请多指教哈。。。
详细介绍了JAVA泛型和反射,对学习JAVA很有帮助哦!!!!
Java试题-3:反射和泛型的综合应用 Java反射 泛型都是比较高级的应用技术
反射处理java泛型_.docx
本示例展示了使用工厂方法设计模式,利用反射,通过泛型接口获取具体类型的列表。比如,要返回一张表的数据,通常使用List<具体表名>,本示例源码展示了通过类型参数传递表名,使用List的形式返回具体的表数据
当我们声明了一个泛型的接口或类,或需要一个子类继承至这个泛型类,而我们又希望利用反射获取这些泛型参数信息。这是本文将要介绍的ReflectionUtil是为了解决这类问题的辅助工具类,为java.lang.reflect标准库的...
先说一下遇到的问题:通过使用GSON泛型进行报文转换的时候想要对部分关键字段加密,发现在封装好的方法中,对个别字段的加密满足不了。 解决过程:首先通过反射获取到bean下的对象名称。 对象名称获取到了之后需要...
C#泛型、反射实例,分层,自动生成sql语句
详细演示Java编程中通过子类获取传入父类DAO的泛型参数,并通过反射创建对象,并对其原理进行深度剖析