反射
Java反射是指程序在运行时,能够访问、检测和修改它本身的状态或行为的一种能力。这种能力使得Java代码能够动态地创建、管理和操纵对象,而无需在编译时进行硬编码。
在Java中,反射机制主要通过类、对象、方法和属性的动态访问来实现。利用反射,开发人员可以在运行时动态地调用类的方法、访问和修改对象的属性,从而构建更加灵活和动态的代码。然而,需要注意的是,过度使用反射可能导致代码效率降低和性能问题。
1. 概述
反射技术,指的是加载类的字节码到内存,并以编程的方法解刨出类中的各个成分(成员变量、方法、构造器等)
2. Java反射中常用的类包括:
Class类:表示一个类,提供了访问类和对象属性的方法,以及获取类方法、构造函数、枚举、注解等的能力。
Method类:表示一个方法,提供了调用方法、获取方法参数、设置方法访问权限等的能力。
Field类:表示一个属性,提供了访问和修改属性值的能力。
Constructor类:表示一个构造函数,提供了创建对象实例的能力。
3. 获得类名(Class)
获取Class对象一共有3种方式
1. 已知类名:User,使用场景:一般在反射声明方法类型时调用。
2. 已知对象:user,使用场景:一般在一个普通方法内,通过变量进行反射操作。
3. 已知全限定类名:xxx.xx.User 字符串,一般用于框架加载类时。
代码实现:
创建User实体类:以下代码通用实体类
package reflect;
public class User {
// 成员变量
private String username = "jack";
public int age = 18;
private User(String username,int age) {
System.out.println("有参构造" + username);
}
public User() {
System.out.println("无参构造");
}
public void info(String username) {
System.out.println("公共 -> info");
System.out.println("姓名为:" + username);
}
private void show(String username) {
System.out.println("私有 -> show");
System.out.println("姓名为:" + username);
}
}
测试类:
public class TestGetClass {
public static void main(String[] args) throws ClassNotFoundException {
// 1. 已知类名
Class<User> c1 = User.class;
// 2. 已知变量
User user = new User();
Class<? extends User> c2 = user.getClass();
// 3. 已知包名
Class<?> c3 = Class.forName("reflect.User");
System.out.println(c1);
System.out.println(c2);
System.out.println(c3);
// c1 c2 c3 相等
System.out.println(c1 == c2); // true
System.out.println(c2 == c3); // true
on System.out.println(c3 == c1); // true
}
}
4. 获取构造器(Constructor )
1. 公共构造
代码实现:
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestPublicConstructor {
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1. 获取Class
Class clazz = User.class;
// 2. 获取构造器 User()
Constructor constructor = clazz.getConstructor();
// 3. 通过构造器创建对象 new
Object o = constructor.newInstance();
System.out.println(o);
}
}
2. 私有构造
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestPrivateConstructor {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1. 获取类名
Class<?> clazz = Class.forName("reflect.User");
// 2. 获取构造器 【获取声明的构造器】 User(String username)
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
// 3. 设置访问权限 因为声明的User(String username)构造器是私有的,私有不能访问,会报错,所以要设置访问权限
declaredConstructor.setAccessible(true);
// 4. 创建实例
Object o = declaredConstructor.newInstance("rose");
System.out.println(o);
}
}
3. 反射获取构造器的作用
其实构造器的作用:初始化对象并返回。
这里我们需要用到如下的两个方法,注意:这两个方法时属于Constructor的,需要用Constructor对象来调用。
5. 获取成员方法(Method)
Method提供的方法:
1. 公共成员方法
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestPublicMethod {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1. 获取类名
Class clazz = Class.forName("reflect.User");
// 2. 获取构造器 User()
Constructor constructor = clazz.getConstructor();
// 3. 通过构造器创建对象 new
Object o = constructor.newInstance();
// 4. 获取方法 info()
Method method = clazz.getMethod("info", String.class);
// 5. 执行方法 user. ("jack")
method.invoke(o, "jack");
}
}
2. 私有成员方法
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestPrivateMethod {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// 1. 获取class
Class clazz = Class.forName("reflect.User");
// 2. 获取构造器
Constructor constructor = clazz.getConstructor();
// 3. 通过构造器创建对象
Object o = constructor.newInstance();
// 4. 获取方法
Method method = clazz.getDeclaredMethod("show", String.class);
// 5. 设置访问权限
method.setAccessible(true);
// 6. 执行方法
method.invoke(o,"rose");
}
}
6. 获取成员变量(Field)
Field提供的方法:
1. 公共成员变量
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class TestPublicField {
public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 1. 获取类名
Class clazz = Class.forName("reflect.User");
// 2. 获取构造器
Constructor constructor =clazz.getConstructor();
// 3. 通过构造器创建对象实例
Object o = constructor.newInstance();
// 4. 获取公共成员变量
Field field = clazz.getField("age");
// 5. 设置
field.set(o,13);
// 6. 获取
System.out.println(field.getInt(o)); // 获取的类型是字符就用get()
}
}
2. 私有成员变量
package reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class TestPrivateField {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
// 1. 获取类名
Class clazz = Class.forName("reflect.User");
// 2. 获取构造器
Constructor constructor = clazz.getConstructor();
// 3. 通过构造器创建对象实例
Object o = constructor.newInstance();
// 4. 获取私有成员变量
Field username = clazz.getDeclaredField("username");
// 5. 设置访问权限
username.setAccessible(true);
// 6. 设置内容
username.set(o, "rose");
// 7. 获取内容
Object o1 = username.get(o);
System.out.println(o1);
}
}
总之,Java反射机制是一种强大的工具,它允许我们在运行时动态地访问、修改和应用对象的状态和行为。然而,需要注意的是,反射机制的使用应当谨慎,避免过度使用导致代码效率下降和性能问题。