java 基础回顾 - 反射

2020-09-23  本文已影响0人  __Y_Q

反射就是把java类中的各种成分映射成一个个的 Java 对象
反射的主要目的是为了获取受保护的或者是隐藏的 类/字段/方法, 然后调用.
在反射中所有的功能都是基于字节码 ( class ). class 在内存中应该只有一份, 而且 class 其实也是一个对象 Class.

public class TestBean {
    private String name = "zhangsan";
    private TestBean(String name) {
        this.name = name;
    }
    private void sysName() {
        Log.e("--TestBean--", name);
    }
}

调用方式

Constructor<TestBean> constructor = TestBean.class.getDeclaredConstructor(String.class);
//如果调用了无参构造, newInstance()不需要传递参数
TestBean testBean = constructor.newInstance("王二");

getConstructors() 所有公有的构造方法
getDeclaredConstructors() 获取所有的构造方法(包括私有、受保护、默认、公有)
getConstructor(Class... parameterTypes) 获取单个的公有的构造方法
getDeclaredConstructor(Class... parameterTypes) 获取某个构造方法可以是私有的, 或受保护, 默认, 公有

 

Method method = TestBean.class.getDeclaredMethod("sysName");
//忽略访问修饰符
method.setAccessible(true);
//参数 1, 就是要调用的对象, 可以理解为, 调用发生在那个对象内, 
//参数 2..... 可为多个参数, 如果要调用的方法有参数, 在参数 2 处可输入多个实参.
method.invoke(testBean);

getMethods() 获取所有公有方法 (包含了父类的方法也包含 Object 类)
getDeclaredMethods() 获取所有的成员方法, 包括私有的(不包括继承的)
getMethod(String name,Class<?>... parameterTypes) 获取单个的.

 

Field field = TestBean.class.getDeclaredField("name");
field.setAccessible(true);
//参数 1, 要获取字段所在的对象
String name = (String) field.get(testBean);

getFields() 获取所有共有字段
getDeclaredFields() 获取所有字段, 包括: 私有, 受保护, 默认, 公有
getField(String fieldName) 获取某个公有的字段
getDeclaredField(String fieldName) 获取某个字段(可以是私有的)

这里获取到的 name 值, 就为 TestBean 中的 name 值.

Class clazz = Class.forName("android.app.ActivityThread");
Field currentActivityThread = clazz.getDeclaredField("sCurrentActivityThread");
currentActivityThread.setAccessible(true);
// 如果是静态的, 可以直接传入 Null
Object o = currentActivityThread.get(null);

使用注解和反射实现一个简单的 findViewById

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FindViewById {
    int value();
    String name() default "zhangsan";
}
public class ViewUtils {
    public static void inject(Activity activity){
        //通过反射拿到所有的字段
        Field[] fields = activity.getClass().getDeclaredFields();
        for (Field field : fields) {
            //只要加了我们这个注解的属性
            FindViewById findViewById = field.getAnnotation(FindViewById.class);
            if(findViewById != null){
                View view = activity.findViewById(findViewById.value());
                try {
                    //开始注入
                    field.setAccessible(true);
                    //第一个参数表示 属性所在类, 第二个表示属性的值
                    field.set(activity,view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
public class MainActivity extends AppCompatActivity {
    @FindViewById(R.id.tv)
    private TextView tv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewUtils.inject(this);
        tv.setText("2222");
    }
}
上一篇 下一篇

猜你喜欢

热点阅读