一,什么是反射
1,反射机制是在 运行状态 中:
对于任意一个类,都能知道这个类的所有属性和方法
对于任意一个对象,都能够调用它的任意一个方法和属性。
2,反射提供的功能:
在运行时判断任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
生成动态代理(动态代理底层用到了反射)
二,反射入口
1,获取反射对象(反射入口):就是拿到Class。有三种方法:
1.1,Class.forName("全类名");需要 包名+类名。需要处理异常
Class<?> perClazz = Class.forName("sys.person");//推荐这种方式
System.out.println(perClazz);
1.2,类名.class
Class<?> perClazz = Person.class;
System.out.println(perClazz);
1.3,对象.getClass();
Person per = new Person();
Class<?> perClazz = per.getClass(); //getClass()方法是object提供的
System.out.println(perClazz);
2,获取公共的方法
Class<?> perClazz = Class.forName("sys.person");
Method[] methods = perClazz.getMethods();
for(Method method : methods){
System.out.print(method);
}
打印结果:
public static void sys.Person.staticMethod()
pulic java.lang.String sys.Person.getName()
public final native void java.lang.Object.hashCode()
可以获取本类和父类(Object)中的public方法。
3,获取接口(多实现)
Class<?> perClazz = Class.forName("sys.person");
Class<?>[] interfaces = perClazz.getInterface();
for(Class<?> inter : interfaces){
System.out.println(inter)
}
打印结果(Person实现两个MyInterface,MyInterface2):
interface sys.MyInterface
interface sys.MyInterface2
4,获取所有父类(单继承)
Class<?> perClazz = Class.forName("sys.person");
Class<?> superClass= perClazz.getInterface();
System.out.println(superClass);
打印结果:
class java.lang.Object
5,获取所有的构造方法
Class<?> perClazz = Class.forName("sys.person");
Constructor<?>[] constructors = perClazz.getConstructors();
for(Constructor constructor : constructors){
System.out.println(constructor);
}
打印结果:
public sys.Person(int,java.lang.String);//两个参数
public sys.Person(int);//一个参数
public sys.Person();//无参
6,获取所有的公共属性
Class<?> perClazz = Class.forName("sys.person");
Field[] fields = perClazz.getFields();
for(Field field : fields){
System.out.println(field);
}
打印结果:
什么也没有,因为Person里定义的变量都是private的。
如果定义了public变量(public String title),反射才能获取到(public java.lang.String sys.Person.title)。
7,获取当前类的所有方法(要求:只能是当前类,并忽略访问修饰符限制)
Class<?> perClazz = Class.forName("sys.person");
Method[] declaredMethods = perClazz.getDeclaredMethods();
for(Method method : declaredMethods){
System.out.print(method);
}
打印结果:
public java.lang.String sys.Person.getName()
private void sys.Person.privateMethod()
public static void sys.Person.staticMethod()
8,获取所有的属性(当前类,忽略访问修饰符)
Class<?> perClazz = Class.forName("sys.person");
Field[] fields = perClazz.getDeclaredFields();
for(Field field : fields){
System.out.println(field);
}
打印结果:
private int sys.Person.id
private java.lang.String sys.Person.name
public java.lang.String sys.Person.title
9,获取当前反射所代表类(接口)的对象
Class<?> perClazz = Class.forName("sys.person");
Object instance = perClazz.newInstance();
Person per = (Person)instance;//强转
per.interfaceMehthod();//调用方法
如果调用成功,说明instance就是Person对象
三,通过反射获取对象的实例,并操作对象
Class<?> perClazz = Class.forName("sys.person");
Person per = (Person)perClazz.newInstance();
per.setId(1);
per.setAge(22);
System.out.println(per.getId() + " : "+ per.getAge());
可以打印出 id 和 age
四,通过反射获取对象的实例,操作属性
Class<?> perClazz = Class.forName("sys.person");
Person per = (Person)perClazz.newInstance();
Field idField = perClazz.getDeclaredField(" id ");
//现在要访问的是private修饰的id,但是private是私有的(私有的只能通过 public void setId()来访问),
//但是我们通过反射还是想访问private int id 。所以,我们在操作属性之前,需要修改属性访问权限。
//使用反射时,如果因为访问修饰符限制造成异常,可以通过setAccessible(true)来解决,同理操作私有方法也可以这样做
idField.setAccessible(true);
idField.set(per,1); // 相当于 ----->per.setId(1);
System.out.println( per.getId() );
五,通过反射获取对象的实例,操作方法
Class<?> perClazz = Class.forName("sys.person");
Person per = (Person)perClazz.newInstance();
1,无参方法
Method method = perClazz.getDeclaredMethod(" privateMethod ",null);//方法名:privateMethod,参数:null
//操作方法私有方法时,把访问修饰符屏蔽掉
method.setAccessible(true);
method.invoke(per,null);//方法的调用:invoke
2,有参方法
Method method2 = perClazz.getDeclaredMethod(" privateMethod2 ",String.class);//方法名:privateMethod2,参数:String类型
method2.setAccessible(true);
method2.invoke(per," 张三 ");//调用方法,并传参数
六,通过反射获取对象的实例,操作构造方法
1,获取本类全部构造方法(公有的,私有的构造方法都能拿到)
Class<?> perClazz = Class.forName("sys.person");
Constructor<?>[] constructors = perClazz.getDeclaredConstructors();
for(Constructor constructor : constructors){
System.out.println(constructor);
}
2,获取指定的构造方法(比如:public Person(int id){ this.id = id })
Class<?> perClazz = Class.forName("sys.person");
Constructor<?> constructor = perClazz.getConstructor(int.class);
System.out.println(constructor);
打印结果:
public sys.Person(int);
3,获取私有的构造方法
----->通过getDeclaredConstructor();获取。注意使用setAccessible(true)
七,