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

综述:建议选择第一种或第三种解决办法

发布了87 篇原创文章 · 获赞 28 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/MakerCloud/article/details/102529094