1. 概念
定义:反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。在计算机科学领域,反射是一类应用,它们能够自描述和自控制。这类应用通过某种机制来实现对自己行为的描述和检测,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。
做一些做不了的事情 一些不正规的手段 。 所有的功能都是基于我们的字节码(class) 一个类的class在内存中应该只有一份 而且class 其实也是一个对象
2.实例化对象
2.1实例化一个无参的构造方法
- class.newInstance(); 实例化一个无参的构造方法
代码示例:
写一个测试的 TestBean.class
public class TestBean {
private String name = "LorenzoGao";
private TestBean() {
}
public void sysName() {
System.out.print(name);
}
}
//使用反射
try {
TestBean testBean=TestBean.class.newInstance();
testBean.sysName();
}catch (Exception e) {
e.printStackTrace();
}
2.2实例一个有参数的构造方法
- getConstructor(Class<?>... parameterTypes) 参数是你构造方法的参数的类型
只返回制定参数类型访问权限是public的构造器
- getDeclaredConstructor (Class<?>... parameterTypes) 参数是你构造方法的参数的类型
这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的
public class TestBean{
private String name = "LorenzoGao";
private TestBean(String name) {
this.name = name;
}
public void sysName() {
System.out.print(name);
}
}
//使用反射
try {
Constructor constructor = TestBean.class.getDeclaredConstructor(String.class);
constructor.setAccessible(true);
TestBean bean = (TestBean) constructor.newInstance("Hello");//调用构造方法传的参数,前提是不是用private修饰 等同于new TestBean("Hello")
bean.sysName();
} catch (Exception e) {
e.printStackTrace();
}
2.3 实例化一个连XXX.class都拿不到的构造方法 ,如ActivityThread.class
try {
Class clazz = Class.forName("android.app.ActivityThread");
Field field = clazz.getDeclaredField("sCurrentActivityThread");
field.setAccessible(true);
Object object =field.get(null); //static 修饰 跟对象是没关系 ,跟类是有关系 所以可以传个null
System.out.print(object.toString());
} catch (Exception e) {
e.printStackTrace();
}
3.方法调用
- getDeclaredMethod(String name, Class<?>... parameterTypes) ,
获得对象所声明的public的和非public的,当然也包括private的
- getDeclaredMethods()
返回所有的方法,包括public的和非public的,当然也包括private的
- getMethod(String name, Class<?>... parameterTypes)
获得对象所声明的public方法
- getMethods()
返回所有是public的方法
- invoke(Object obj, Object... args)
执行方法 obj表示执行者,args表示传入方法参数,无参方法,可不传。
name 表示方法名,parameterTypes 表示的有参方法的参数类型
3.1获取一个无参方法
public class TestBean {
private String name = "LorenzoGao";
public TestBean(String name) {
this.name = name;
}
private void sysName() {
System.out.print(name);
}
}
//反射获取方法
try {
TestBean bean=new TestBean("Hello");
Method method = TestBean.class.getDeclaredMethod("sysName");
method.setAccessible(true);
method.invoke(bean); //表示bean去执行这个方法
} catch (Exception e) {
e.printStackTrace();
}
3.2获取一个有参方法
public class TestBean {
private String name = "LorenzoGao";
public TestBean(String name) {
this.name = name;
}
private void sysName() {
System.out.print(name);
}
private void sysName(String params) {
System.out.print(params);
}
}
//反射
try {
TestBean bean=new TestBean("Hello");
Method method =TestBean.class.getDeclaredMethod("sysName",String.class);
method.setAccessible(true);
method.invoke(bean,"哈哈哈");
} catch (Exception e) {
e.printStackTrace();
}
4.获取属性
- getDeclaredField(String name)
获取对象里面指定名字的public和private 修饰的属性
- getDeclaredFields()
获取对象里面所有public和private 修饰的属性
- getField(String name)
获取对象里面指定名字的public 修饰的属性
- getFields()
获取对象里面所有的public 修饰的属性
name 表示属性名字
public class TestBean {
private String name = "LorenzoGao";
public TestBean(String name) {
this.name = name;
}
private void sysName() {
System.out.print(name);
}
private void sysName(String params) {
System.out.print(params);
}
}
//反射获取属性
try {
TestBean testBean = new TestBean("123");
Field field = TestBean.class.getDeclaredField("name");
field.setAccessible(true);
String name = (String) field.get(testBean);//获取值
System.out.print(name);
} catch (Exception e) {
e.printStackTrace();
}
}
总是对反射概念很模糊,写一篇手记来总结一下。