getDeclaredFields獲取到$change以及serialVersionUID成員解決

概述

最近在使用Android Studio時遇到使用getDeclaredFields獲取到$change成員的問題,代碼如下:

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Field[] fields = Demo.class.getDeclaredFields();
        for(Field f : fields) {
            Log.d(TAG, "fields : " + f.getName() + " isSynthetic:" + f.isSynthetic());
        }
    }

    static class Demo {
        int test = 0;
    }
}

得到的fields結果如下

 D/MainActivity: fields : test
 D/MainActivity: fields : $change
 D/MainActivity: fields : serialVersionUID

解決

1. $change

在Google上搜索發現有人也遇到相同的問題
鏈接:Android Java objModelClass.getClass().getDeclaredFields() returns “$change” as one field

原因就是:Android Studio中有個Instant Run功能,如果開啓的話編譯器就會對所有類都添加$change成員變量。

2. serialVersionUID

serialVersionUID和Java的序列化機制有關。Java的序列化機制是通過判斷類的serialVersionUID來驗證版本一致性的。在進行反序列化時,JVM會把傳來的字節流中的serialVersionUID與本地相應實體類的serialVersionUID進行比較,如果相同就認爲是一致的,可以進行反序列化,否則就會出現序列化版本不一致的異常,即是InvalidCastException。這裏猜測應該是AndroidStudio與Android手機安裝的應用程序進行序列化傳輸數據時用到的。

解決

解決方法有兩個:

1.關閉Android Studio的Instant Run功能

在這裏插入圖片描述
關掉後在運行一次試試:

D/MainActivity: fields : test

2.使用Field類中isSynthetic方法過濾掉編譯器自動生成的成員變量。

看一下isSynthetic方法的說明文檔:

boolean isSynthetic()
Returns true if this member was introduced by the compiler; returns false otherwise.
Returns:
true if and only if this member was introduced by the compiler.
Since:
1.5

如果是編譯器自動生成的Field的話isSynthetic會返回true,否則返回false。
雖然$change返回了true,但serialVersionUID返回的是false,所以這種方法並不好使。

D/MainActivity: fields : test isSynthetic:false
D/MainActivity: fields : $change isSynthetic:true
D/MainActivity: fields : serialVersionUID isSynthetic:false

3. 使用判斷語句過濾掉

        for(Field f : fields) {
            if(!(("$change".equals(f.getName()))||("serialVersionUID".equals(f.getName())))){
                Log.d(TAG, "fields : " + f.getName() + " isSynthetic:" + f.isSynthetic());
            }
        }

再運行:

D/MainActivity: fields : test isSynthetic:false

綜述:建議選擇第一種或第三種解決辦法

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