关于Java的泛型在所声明的对象中如何获取class或者实例的方法的总结

前段时间写过JSON字符串解析的代码,大部分工作都是在重复的写相同逻辑的代码,心血来潮打算用泛型解决这个重复的过程,结果可想而知一路上到处遇到问题,不过还好最后还是找到了解决办法。下面总结一下,一是自己备忘一下,二是分享一下。

总得说有两种方式可以解决这个问题,一种看上去技术含量很低,但是效果很好,也很简单,另一种要高一点,而且也很麻烦,在显示开发的时候也要不停的建造子类。

  • 技术含量比较的低的方式:

    泛型类

JSONUtil
1 public class JSONUtil<T> {
2     public T analytic2Object(Class<T> tClass, String str)
3             throws InstantiationException, IllegalAccessException {
4         return tClass.newInstance();
5     }
6 }

      数据类

TestObject
1 public class TestObject {
2     public void printName() {
3         System.out.println("TestObject");
4     }
5 }

    测试类

TestMain
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的代码如下:

JSONUtil
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的目的,下面我大体说一下这个获取的方法:

  1. 创建我们的泛型类让它做基类或者抽象类,为什么不用接口呢?因为我们要在这个泛型类上写所有的解析JSON的逻辑代码;
  2. 添加通过泛型拿到class的方法;
  3. 写一个没有泛型的类继承这个泛型类,并将泛型的类型在集成的时候写明确,这样在编译的时候就知道泛型的类型了,第2步的那个代码才能生效,如果不继承直接用这个基类第2步的代码是会出异常的,不信你可以试试;
  4. 在我们的代码中调用泛型类的子类的方法就能正常了。

这个方法最大的弊病是:我们每添加一个要解析出的数据类时都要添加这么一个泛型类的子类,好处是这个子类不需要写任何代码,因为逻辑都在泛型的基类中实现了。

   泛型基类

AbsJSONUtil
 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 }

  泛型子类

JSONUtilForTestObject
1 public class JSONUtilForTestObject extends AbsJSONUtil<TestObject> {
2 
3 }

  测试类

TestMain
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 }

  数据类同上例。

posted @ 2012-08-30 16:11  铭久  阅读(15437)  评论(0编辑  收藏  举报