关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结
2016-08-31 15:55
721 查看
前段时间写过JSON字符串解析的代码,大部分工作都是在重复的写相同逻辑的代码,心血来潮打算用泛型解决这个重复的过程,结果可想而知一路上到处遇到问题,不过还好最后还是找到了解决办法。下面总结一下,一是自己备忘一下,二是分享一下。
总得说有两种方式可以解决这个问题,一种看上去技术含量很低,但是效果很好,也很简单,另一种要高一点,而且也很麻烦,在显示开发的时候也要不停的建造子类。
技术含量比较的低的方式:
泛型类
数据类
测试类
看完这个代码后你可能会问,为什么要在方法中传个class进去呢?为什么不通过T这个泛型来获取呢?既然要传class进去干吗还用泛型呢?下面来回答一下几个问题:
为什么要在方法中传个class进去呢,原因很简单,在我们的这个工具类中根本没法根据T这个泛型来获取它的class;无法的获取的原因是:泛型是在编译期获得的,而且有擦除机制。所以在编译前不知道T是啥,编译后又被擦除了;那么这个还有必要使用泛型么?回答是可以不用泛型,因为拿到class后一切问题都解决了,但是有一个问题就是你的方法返回的对象只能是Object,然后在调用的地方进行强制类型转换了。
不用泛型传递class的代码如下:
通过泛型来获取class的方法:
这时你可能会疑问:你上边不是说不能通过泛型来获取么?这里怎么又可以了?请注意前面我那句话“在我们的这个工具类中根本没法根据T这个泛型来获取它的class”,也就是说我们可以通过另一中方式来实现这个获取class的目的,下面我大体说一下这个获取的方法:
创建我们的泛型类让它做基类或者抽象类,为什么不用接口呢?因为我们要在这个泛型类上写所有的解析JSON的逻辑代码;
添加通过泛型拿到class的方法;
写一个没有泛型的类继承这个泛型类,并将泛型的类型在集成的时候写明确,这样在编译的时候就知道泛型的类型了,第2步的那个代码才能生效,如果不继承直接用这个基类第2步的代码是会出异常的,不信你可以试试;
在我们的代码中调用泛型类的子类的方法就能正常了。
这个方法最大的弊病是:我们每添加一个要解析出的数据类时都要添加这么一个泛型类的子类,好处是这个子类不需要写任何代码,因为逻辑都在泛型的基类中实现了。
泛型基类
泛型子类
测试类
总得说有两种方式可以解决这个问题,一种看上去技术含量很低,但是效果很好,也很简单,另一种要高一点,而且也很麻烦,在显示开发的时候也要不停的建造子类。
技术含量比较的低的方式:
泛型类
1 public class JSONUtil<T> { 2 public T analytic2Object(Class<T> tClass, String str) 3 throws InstantiationException, IllegalAccessException { 4 return tClass.newInstance(); 5 } 6 }
数据类
1 public class TestObject { 2 public void printName() { 3 System.out.println("TestObject"); 4 } 5 }
测试类
1 public class TestMain { 2 public static void main(String[] args) throws InstantiationException, 3 IllegalAccessException { 4 JSONUtil<TestObject> util = new JSONUtil<TestObject>(); 5 TestObject obj = util.analytic2Object(TestObject.class, ""); 6 obj.printName(); 7 } 8 }
看完这个代码后你可能会问,为什么要在方法中传个class进去呢?为什么不通过T这个泛型来获取呢?既然要传class进去干吗还用泛型呢?下面来回答一下几个问题:
为什么要在方法中传个class进去呢,原因很简单,在我们的这个工具类中根本没法根据T这个泛型来获取它的class;无法的获取的原因是:泛型是在编译期获得的,而且有擦除机制。所以在编译前不知道T是啥,编译后又被擦除了;那么这个还有必要使用泛型么?回答是可以不用泛型,因为拿到class后一切问题都解决了,但是有一个问题就是你的方法返回的对象只能是Object,然后在调用的地方进行强制类型转换了。
不用泛型传递class的代码如下:
1 public class JSONUtil { 2 public Object analytic2Object(Class tClass, String str) throws InstantiationException, IllegalAccessException { 3 return tClass.newInstance(); 4 } 5 }
通过泛型来获取class的方法:
这时你可能会疑问:你上边不是说不能通过泛型来获取么?这里怎么又可以了?请注意前面我那句话“在我们的这个工具类中根本没法根据T这个泛型来获取它的class”,也就是说我们可以通过另一中方式来实现这个获取class的目的,下面我大体说一下这个获取的方法:
创建我们的泛型类让它做基类或者抽象类,为什么不用接口呢?因为我们要在这个泛型类上写所有的解析JSON的逻辑代码;
添加通过泛型拿到class的方法;
写一个没有泛型的类继承这个泛型类,并将泛型的类型在集成的时候写明确,这样在编译的时候就知道泛型的类型了,第2步的那个代码才能生效,如果不继承直接用这个基类第2步的代码是会出异常的,不信你可以试试;
在我们的代码中调用泛型类的子类的方法就能正常了。
这个方法最大的弊病是:我们每添加一个要解析出的数据类时都要添加这么一个泛型类的子类,好处是这个子类不需要写任何代码,因为逻辑都在泛型的基类中实现了。
泛型基类
1 import java.lang.reflect.ParameterizedType; 2 import java.lang.reflect.Type; 3 4 public abstract class AbsJSONUtil<T> { 5 public T getT() throws InstantiationException, IllegalAccessException { 6 Type sType = getClass().getGenericSuperclass(); 7 Type[] generics = ((ParameterizedType) sType).getActualTypeArguments(); 8 Class<T> mTClass = (Class<T>) (generics[0]); 9 return mTClass.newInstance(); 10 } 11 }
泛型子类
1 public class JSONUtilForTestObject extends AbsJSONUtil<TestObject> { 2 3 }
测试类
1 public class TestMain { 2 public static void main(String[] args) throws InstantiationException, 3 IllegalAccessException { 4 JSONUtilForTestObject go = new JSONUtilForTestObject(); 5 TestObject obj = go.getT(); 6 obj.printName(); 7 } 8 }
相关文章推荐
- 关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结
- 关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- 在其他class或者view中获取MainActivity实例,以便调用其函数的方法:
- java中获取class实例的三种方法
- Java通过Class的对象来获取泛型的class示例
- Java中获取Class对象的三种方法
- java反射之——获取Class对象的方法
- java获取泛型参数的类型的方法 - 实例讲解
- java获取Class对象的几种方法
- 反射机制_介绍_Class对象获取_动态操作_构造器_方法_属性JAVA211-212
- java中关于文本文件的读写方法实例总结
- 使用反射创建Bean、Spring中是如何根据类名配置创建Bean实例、Java提供了Class类获取类别的字段和方法,包括构造方法
- Java 获取Class对象的三种方法
- 【ThinkingInJava】27、关于class对象引用的各种关于class的方法
- 关于Java获取子方法的新建实例引用的心得
- 波哥学JAVA,定义类 声明属性 创建对象 实例化对象 对象调用属性或者方法
- Java获取泛型的Class对象
- 关于java中子类,父类中,静态代码块: staic{},动态代码块:{},构造方法,类属性,对象属性等执行顺序做个总结:
- 关于android studio中使用class.forname()方法动态获取类实例报NO CLASS FOUND异常的几种处理方法