關於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 }

  數據類同上例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM