Android下的Java之interface接口泛型 動態獲取泛型的類型

# Android的泛型有多坑?

## 先來看看該問題的場景

將String轉換成具體對象時,需要進行的關鍵點就是獲取到對象的類型

``` java
// 這裏定義了一個泛型R,那運行時如何獲取到這個類型呢?
// 第一眼看上去,你會感覺,這不是很簡單嗎?
// 在onSuccess的方法中參數就能讀取到具體類型啊
// 問題的關鍵就是調用onSuccess前,如何創建R類型的參數
public interface Listener<R extends Result> {
    void onSuccess(R result);
}

```

這個問題在jvm虛擬機上可以通過簡單的反射即可獲取到具體的泛型R類型,如下:


``` java
Type t = object.getClass().getGenericSuperclass();
Type claz = ((ParameterizedType) t).getActualTypeArguments()[0];
Class claz = object.getResultType();
```


但是上述代碼並不能很好的在Dalvik上運行,根本無法獲取到R的真實類型。
我們可以通過反射某個具體方法來獲取參數類型,間接的獲取到了R類型,如下:


``` java
Class claz = Default.class;
Method[] ms = object.getClass().getDeclaredMethods();
for (Method m : ms) {
    if (!"methodName".equals(m.getName())) continue;
    Class[] paramTypes = m.getParameterTypes();
    if (paramTypes.length == 1 &&
            Default.class.isAssignableFrom(paramTypes[0])) {
        claz = paramTypes[0];
        if(!paramTypes[0].isAssignableFrom(Default.class)) {
            break;
        }
    }
}

```

當你真實的運行了上述代碼後,你會發現在java虛擬機看來,不同的參數類型,不同的返回類型,都是函數重載。只用完全相同的參數類型和返回類型才能算是重寫,也就是函數名與函數簽名必須完全一致。java字節碼的規則遠比IDE的規則要複雜。

## 逼格知識點

> java函數只有返回類型不同,是重載還是重寫?

普通程序員會說IDE編譯報錯,並能夠區分出重寫與重載,但是解析不具有深度

請一定記住以下有深度的解析

1. IDE不一定完全報錯
2. jdk6以下是可以構成重載成功的,主要是參數爲泛型時,表達了兩個不同的具體類型時,能繞過編譯器的檢查
3. jdk7及以上是編譯不通過的,但是已經編譯成功的字節碼中,仍然會因返回類型的變化構成重載函數。
4. 在jni開發時應該要注意這種特殊的重載

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章