一、基本概念
1.反射机制:在运行状态中,可以动态的获取类信息及动态的调用类对象方法的功能。
2.反射常用的几个方法
(1)getDeclaredMethod(方法名,参数):返回对应的方法;
(2)Field属性:getType()返回字段类型,getName()返回字段名称,set()设置新值
3.反射的作用?
(1)在运行时判断任意一个对象所属的类、判断任意一个类所具有的成员变量和方法。
(2)在运行时构造任意一个类的对象;
(3)在运行时调用任意一个对象的方法。
4.反射的应用场景?
(1)Spring IOC的对象注入;
5.反射的性能?如何优化?
(1)反射性能比直接的java代码要慢,反射相当于一系列解释操作,通知jvm要做哪些事情。反射主要性能损耗是在对方法或变量的获取时。
二、反射应用
1.通过反射获取类的方法、属性、构造器
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
//1.根据一个类的全名字符串来获得一个类的对象
Class<?> clazz=Class.forName("java.lang.String");
//2.获得传递过来类的所有方法
Method[] methods=clazz.getDeclaredMethods();
//System.out.println(Arrays.toString(methods));
for(Method m:methods){
System.out.println(m);
}
System.out.println("--------------------");
//3.获取类的所有属性
Field[] fields=clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println(field);
}
System.out.println("--------------------");
//4.获取类的所有构造器
Constructor[] constructors=clazz.getDeclaredConstructors();
for (Constructor constructor : constructors) {
System.out.println(constructor);
}
}
}
2.通过反射获得class对象3种方式
public class getClassThree {
//1.知道类字符串
public static void test1() throws ClassNotFoundException {
//获得一个类的类对象
Class<?> clazz=Class.forName("java.util.HashMap");
}
//2.知道是一个对象,但不知道是什么对象
public static void test2(Object obj) {
//获得一个类的类对象
Class<?> clazz=obj.getClass();
//2.获得传递过来类的所有方法
Method[] methods=clazz.getDeclaredMethods();
//System.out.println(Arrays.toString(methods));
for(Method m:methods){
System.out.println(m);
}
System.out.println("--------------------");
//3.获取类的所有属性
Field[] fields=clazz.getDeclaredFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("--------------------");
//4.获取类的所有构造器
Constructor[] constructors=clazz.getDeclaredConstructors();
for (Constructor c : constructors) {
System.out.println(c);
}
}
//3.知道类名
public static void test3() {
Class<?> clazz=Map.class;
//获得类的所有方法
Method[] methods=clazz.getDeclaredMethods();
System.out.println(Arrays.toString(methods));
}
}
3.通过反射调用方法(静态、非静态)、访问私有属性、私有方法,拷贝对象
(1)person测试类
package reflectTest;
public class Person {
private Integer id;
private String name;
private String address;
/*构造函数*/
public Person() {
}
public Person(Integer id, String name, String address) {
super();
this.id = id;
this.name = name;
this.address = address;
}
private static void printInfo(){
System.out.println("静态方法的反射调用成功");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", address=" + address
+ "]";
}
}
(2)通过反射调用非静态方法、调用静态方法
//invoke():就是去调用方法
public class ReflectDemo1 {
//调用非静态方法
public static void main(String[] args) throws Exception {
Class<?> class1 = Class.forName("reflectTest.Person");
//获得构造器
Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
//根据类的默认构造器来获得一个对象
Object instance = constructor.newInstance(new Object[]{});
/*--------------调用非静态方法----------------- */
System.out.println("调用非静态方法:");
//获得method对象
Method method1 = class1.getDeclaredMethod("setName", new Class[]{String.class});
//执行对象的某个方法
Object invoke = method1.invoke(instance, new Object[]{"张三"});
System.out.println("调用非静态方法 setName():"+invoke);
Method method2 = class1.getDeclaredMethod("getName", null);
//Method mget = class1.getDeclaredMethod("getName", new Class[]{});
Object invoke2 = method2.invoke(instance, new Object[]{});
System.out.println("调用非静态方法 getName():"+invoke2);
/*----------------调用静态方法--------------------*/
System.out.println("-----------------------");
System.out.println("调用静态方法:");
Method method3 = class1.getDeclaredMethod("printInfo", null);
//破坏私有方法,让我们能调用
method3.setAccessible(true);
Object invoke3 = method3.invoke(null, null);
}
}
(3)通过反射访问私有属性、访问静态私有方法
//设置私有属性
public static void main(String[] args) throws Exception {
Class<?> class1 = Class.forName("reflectTest.Person");
//获得构造器
Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
//根据类的默认构造器来获得一个对象
Object instance = constructor.newInstance(new Object[]{});
//根据方法名字来获得属性对象
Field field = class1.getDeclaredField("name");
//破坏掉私有属性
field.setAccessible(true);
field.set(instance, "张三");
//获得属性的类型
Class<?> type = field.getType();
System.out.println(type);
}
//访问静态私有方法
System.out.println("调用静态方法:");
Method method3 = class1.getDeclaredMethod("printInfo", null);
//破坏私有方法,让我们能调用
method3.setAccessible(true);
Object invoke3 = method3.invoke(null, null);
(4)通过反射拷贝对象
public class ReflectDemo3 {
public static void main(String[] args) throws Exception {
Class<?> class1 = Class.forName("reflectTest.Person");
//获得构造器
Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
//根据类的默认构造器来获得一个对象
Object instance = constructor.newInstance(new Object[]{});
System.out.println(instance);
//获得类的所有方法
Method[] methods = class1.getDeclaredMethods();
for(Method m :methods){
//获得方法的名字
String name = m.getName();
//获得是否以set开始
boolean startsWith = name.startsWith("set");
if(startsWith){
//获得到了set字符串的后面的值
String fieldName = name.substring(3);
//获得属性的名字
fieldName = fieldName.substring(0, 1).toLowerCase()+fieldName.substring(1);
//获得方法所对应的属性
Field field = class1.getDeclaredField(fieldName);
//获得属性的具体类型,获得属性对应的类型
Class<?> type = field.getType();
if(type == Integer.class){
//反射调用set方法
m.invoke(instance, new Object[]{1});
}
if(type == String.class && "address".equals(fieldName)){
//反射调用set方法
m.invoke(instance, new Object[]{"北京"});
}
if(type == String.class && "name".equals(fieldName)){
//反射调用set方法
m.invoke(instance, new Object[]{"张三"});
}
}
}
System.out.println(instance);
/*Constructor<?> constructor1 = class1.getDeclaredConstructor(new Class[]{Integer.class, String.class, String.class});
Object instance2 = constructor1.newInstance(new Object[]{1, "李四","北京"});
System.out.println(instance2);*/
}
}