以前,只是对反射有个大致的了解,用的也比较少,后面差不多都忘记了。在前几天的面试中有人问我反射相关的知识,我只回答出反射的基本原理和一些方法的名字,具体的细节都已经忘记。现在回顾一下,加深学习一下。
反射的概念
主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接。但是反射使用不当会成本很高!
通过反射创建对象
//类名要写全类名
Class clazz = Class.forName("com.example.reflectiondemo.User");
Object user = clazz.newInstance();
注意:这个地方的类名一定要写全类名,否则会报找不到User类异常。
通过反射获取属性并修改值
//如果是private类型的方法和属性需要暴力破解
Field nameF = clazz.getDeclaredField("name");
//private修饰的方法和字段需要设置setAccessible为true
nameF.setAccessible(true);
nameF.set(user,"张三");
注意:私有属性需要暴力破解并且修改值得时候需要setAccessible为true
通过反射获取方法并调用方法
Method method = clazz.getDeclaredMethod("talk");
method.setAccessible(true);
method.invoke(user);
同样的,private修饰的方法也需要暴力破解
上写的一点代码,其实很简单,就两个类。实现动态修改User的名字,并且通过反射调用方法把名字显示出来。
public class User implements Serializable {
private String name;
public int age;
private int id;
public User(String name) {
this.name = name;
}
public User() {
}
private void talk(){
Log.e("User","名字: "+name+"\n"
+"年龄: "+age
);
}
}
public class MainActivity extends AppCompatActivity {
private String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取user对象
try {
//类名要写全类名
Class clazz = Class.forName("com.example.reflectiondemo.User");
//如果是private类型的方法和属性需要暴力破解
Field nameF = clazz.getDeclaredField("name");
Method method = clazz.getDeclaredMethod("talk");
Object user = clazz.newInstance();
//private修饰的方法和字段需要设置setAccessible为true
nameF.setAccessible(true);
nameF.set(user,"张三");
method.setAccessible(true);
method.invoke(user);
} catch (Exception e) {
e.printStackTrace();
}
}
}
打印的log的结果
04-19 16:02:23.191 2269-2269/? E/User: 名字: 张三
年龄: 0
刚开始写博客,如果有错误,请指正。共同学习进步。