java反射Reflect

1、获取Class的三方式

要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java.lang.Class实例?

方式 备注
Class.forName(“完整类名带包名”) 静态方法
对象.getClass()  
任何类型.class  

注:以上三种方式返回值都是Class类型。

2、JDBC重点(Class.forName导致类加载)

如果你只是希望一个类的静态代码块执行,其它代码一律不执行,可以使用:

Class.forName("完整类名");

这个方法的执行会导致类加载,类加载时,静态代码块执行。

3.通过反射获取类的权限修饰符,类名,属性权限,类型,名称

Book实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
​
    private Integer id;
​
    private  String type;
​
    private String name;
​
    private String description;
​
}
/**
 * 测试反射获取类的定义
 * @throws ClassNotFoundException
 * @throws InstantiationException
 * @throws IllegalAccessException
 * @throws NoSuchMethodException
 */
@Test
public void testReflect() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException {
​
    //测试反射获取
    Class bookClass = Class.forName("com.jjh.pojo.Book");
​
     StringBuilder sb = new StringBuilder();
​
     sb.append(Modifier.toString(bookClass.getModifiers())+ " class " + bookClass.getSimpleName() + "{\n");
    //获取属性
    Field[] fields = bookClass.getDeclaredFields();
    for (Field field : fields) {
        sb.append("\t");
        sb.append(Modifier.toString(field.getModifiers()));
        if(field.getModifiers()!=0) sb.append(" ");
        //获取属性的类型
        sb.append(field.getType().getSimpleName());
        sb.append(" ");
        //获取属性的名称
        sb.append(field.getName());
        sb.append(";\n");
​
    }
    sb.append("}");
​
​
    System.out.println(sb);
​
​
}

运行结果:

public class Book{ private Integer id; private String type; private String name; private String description; }

4.Fields通过反射给属性赋值

/**
 * 通过反射给对象属性赋值
 */
@Test
public void setProperty() throws Exception{
​
    Class bookClass = Class.forName("com.jjh.pojo.Book");
​
    Object book = bookClass.newInstance();
​
​
    Field nameField = bookClass.getDeclaredField("name");
    //设置暴力反射赋值
    nameField.setAccessible(true);
​
    nameField.set(book,"大话西游");
​
    System.out.println(book);
​
​
}

运行结果:

Book(id=null, type=null, name=大话西游, description=null)

注意:

若类的属性使用了private修饰,则要使用setAccessible(true)方法暴力赋值

5.通过反射获取方法Methods

(1)反射获取方法的权限修饰符,返回值类型,参数列表

/**
 * 测试通过反射获取方法
 */
@Test
public void testMethodsReflect() throws Exception{
​
    Class carClass = Class.forName("com.jjh.pojo.Car");
​
    Method[] methods = carClass.getDeclaredMethods();
    StringBuilder sb = new StringBuilder();
    for (Method method : methods) {
​
         //方法的权限修饰符
        String modifier = Modifier.toString(method.getModifiers());
        sb.append(modifier+" ");
        //方法的返回值类型
        String returnType = method.getReturnType().getSimpleName();
        sb.append(returnType+" ");
        //方法的名称
        String name = method.getName();
        sb.append(name+"(");
        //参数列表
        Class[] parameterTypes = method.getParameterTypes();
         for(int i=0;i
 

运行结果:

public String getName() public String toString() public void setName(String) public Integer getId() public void setLocalDateTime(LocalDateTime) public String buy(String) public void setId(Integer) public LocalDateTime getLocalDateTime()

(2)方法的四要素

  • 要素1:对象 userService

  • 要素2:login 方法名

  • 要素3:实参列表

  • 要素4:返回值

/**
 * 测试反射调用方法
 */
@Test
public void testMethodInvoke() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
​
    Class carClazz = Class.forName("com.jjh.pojo.Car");
​
    Object car = carClazz.newInstance();
​
    Method buy = carClazz.getDeclaredMethod("buy", String.class);
​
​
​
    Field idFiled = carClazz.getDeclaredField("id");
    idFiled.setAccessible(true);
    idFiled.set(car,1);
    Field nameFiled = carClazz.getDeclaredField("name");
    nameFiled.setAccessible(true);
    nameFiled.set(car,"丰田");
    Field localDateTimeFiled = carClazz.getDeclaredField("localDateTime");
    localDateTimeFiled.setAccessible(true);
​
​
​
    localDateTimeFiled.set(car,LocalDateTime.now() );
​
​
    Object result = buy.invoke(car, "张三");
​
    System.out.println(result);
​
​
}

运行结果:

用户:张三购买了id为:1的车,在2023-06-16T19:51:19.853653600

6.Constructor类反射获取构造方法

通过Constructor的newInstance()方法构建对象,可以传参数,也可以无参数

/**
 * 通过反射构造方法创建对象
 */
@Test
public void testConstructor() throws Exception{
​
    Class carClazz = Class.forName("com.jjh.pojo.Car");
​
    Constructor constructor =    carClazz.getDeclaredConstructor(Integer.class,String.class,LocalDateTime.class);
​
    Object car = constructor.newInstance(1,"比亚迪",LocalDateTime.now());
​
    System.out.println(car);
}

运行结果:

Car{id=1, name='比亚迪', localDateTime=2023-06-16T20:09:17.424101200}

7.获取一个类的父类以及实现的接口

两个方法【Class类中的】

  1. public native Class getSuperclass()

  2. public Class[] getInterfaces()

/**
 * 获取一个类的父类和它实现的接口
 */
@Test
public void testGetSuperClassAndInterface() throws ClassNotFoundException {
​
    Class arryListClazz = Class.forName("java.util.ArrayList");
​
    Class superclass = arryListClazz.getSuperclass();
​
    Class[] interfaces = arryListClazz.getInterfaces();
​
    System.out.println("ArrayList的父类是:  "+superclass.getSimpleName());
​
    System.out.println("ArrayList实现的接口有:");
    for (Class anInterface : interfaces) {
​
        System.out.println(anInterface);
    }
}

运行结果:

ArrayList的父类是:  AbstractList
ArrayList实现的接口有:
interface java.util.List
interface java.util.RandomAccess
interface java.lang.Cloneable
interface java.io.Serializable

 

你可能感兴趣的:(java,java,开发语言)