Day42 Java反射(一)

发布于:2024-05-02 ⋅ 阅读:(30) ⋅ 点赞:(0)

Day42 Java反射(一)

前言

使用到一个类,JVM会将该类的class文件加载到方法区(类加载机制),同时会在堆内存中创建该类的class对象,class对象的作为class文件的访问入口。

在Java中,反射是指在运行时检查、获取和操作类、对象、方法等程序结构的能力。通过反射机制,可以在运行时动态获取类的信息、调用方法、访问字段等,而不需要在编译时确定这些信息。

基本概念

  1. Class类:在Java中,每个类都有一个对应的Class对象,可以通过类名.class或对象.getClass()方法获取。
  2. 获取Class对象:可以通过类的全限定名、对象的getClass()方法、Class类的静态方法forName()来获取Class对象。
  3. 反射API:Java提供了反射相关的API,如Class类、Constructor类、Method类、Field类等,用于操作类的结构。

理解

反射实际上就是获取class对象,通过class对象访问class文件中的内容

访问内容: 属性,构造方法,普通方法(成员方法、静态方法、抽象方法…),方法上的参数,方法上的返回值,数组

应用场景

  1. 框架开发:许多框架(如Spring、Hibernate)利用反射实现依赖注入、ORM映射等功能。
  2. 工具类:编写通用工具类时,可以利用反射来实现动态调用、配置等功能。
  3. 测试框架:测试框架(如JUnit)利用反射来执行测试方法。
  4. 动态代理:通过反射可以实现动态代理,实现AOP等功能。
  5. 配置文件解析:可以通过反射读取配置文件中的类名、方法名等信息

利用反射获取class对象

Class对象的正确理解:每个类在内存中只有一份class文件

注意
该类的class文件只在一次到方法区中,
该类的class对象在程序中是唯一的。
所以不管使用那种方式获取class对象都是同一个

public class Test01 {
	
	public static void main(String[] args) throws ClassNotFoundException {
		
		//获取class对象方式1
		Class<? extends Student> clazz1 = Student.class;
		
		//获取class对象方式2
		Student stu = new Student();
		Class<? extends Student> clazz2 = stu.getClass();
		
		//获取class方式3
		Class<?> clazz3 = Class.forName("com.qf.reflex01.Student");
		
		System.out.println(clazz1 == clazz2);//true
		System.out.println(clazz1 == clazz3);//true
	}
}
public class Student extends Person{
	
	private String classId;
	private String id;
	
	public static final String str = "用良心做教育";
	
	public Student() {
	}

	private Student(String name, char sex, int age) {
		super(name, sex, age);
	}
	
	public Student(String name, char sex, int age, String classId, String id) {
		this(name, sex, age);
		this.classId = classId;
		this.id = id;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "Student [classId=" + classId + ", id=" + id + ", toString()=" + super.toString() + "]";
	}
}

利用反射操作属性

基本步骤:

  1. 获取Class对象:首先需要获取要操作的类的Class对象,可以通过类名.class或对象.getClass()方法获得。
  2. 获取字段对象:通过Class对象的getField()、getDeclaredField()等方法获取字段对象。
  3. 操作字段:通过Field对象的get()、set()方法可以获取和设置字段的值。

示例代码:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.io.IOException;

import com.qf.utils.ReflexUtil;

public class Test03 {
	/**
	 * 知识点:利用反射操作属性
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
		
		//通过反射工具类设置对象里的属性
		Student stu = new Student();
		ReflexUtil.setField(stu, "name", "小伟");
		ReflexUtil.setField(stu, "sex", '男');
		ReflexUtil.setField(stu, "age", 23);
		ReflexUtil.setField(stu, "classId", "2401");
		ReflexUtil.setField(stu, "id", "001");
		
		System.out.println(stu);
	}
}
public class Student extends Person{
	
	private String classId;
	private String id;
	
	public static final String str = "用良心做教育";
	
	public Student() {
	}

	private Student(String name, char sex, int age) {
		super(name, sex, age);
	}
	
	public Student(String name, char sex, int age, String classId, String id) {
		this(name, sex, age);
		this.classId = classId;
		this.id = id;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "Student [classId=" + classId + ", id=" + id + ", toString()=" + super.toString() + "]";
	}
}
public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
}

利用反射操作构造方法

基本步骤:

  1. 获取Class对象:首先需要获取要操作的类的Class对象,可以通过类名.class或对象.getClass()方法获得。
  2. 获取构造方法对象:通过Class对象的getConstructor()、getDeclaredConstructor()等方法获取构造方法对象。
  3. 创建对象实例:通过构造方法对象的newInstance()方法创建类的对象实例。

示例代码:

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import com.qf.utils.ReflexUtil;

public class Test04 {
	/**
	 * 知识点:利用反射操作构造方法
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		

		
		//利用反射工具类去创建对象 -- 底层调用有参构造
		Class<?>[] parameterTypes = {String.class,char.class,int.class,String.class,String.class};
		Object[] paremeters = {"巴得伟",'男',23,"2401","001"};
		Student stu = ReflexUtil.newInstance(Student.class, parameterTypes, paremeters);
		System.out.println(stu);
	}
}
public class Student extends Person{
	
	private String classId;
	private String id;
	
	public static final String str = "用良心做教育";
	
	public Student() {
	}

	private Student(String name, char sex, int age) {
		super(name, sex, age);
	}
	
	public Student(String name, char sex, int age, String classId, String id) {
		this(name, sex, age);
		this.classId = classId;
		this.id = id;
	}

	public String getClassId() {
		return classId;
	}

	public void setClassId(String classId) {
		this.classId = classId;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "Student [classId=" + classId + ", id=" + id + ", toString()=" + super.toString() + "]";
	}
}
public class ReflexUtil {

	/**
	 * 获取当前类及其父类的属性对象
	 * @param clazz class对象
	 * @param name 属性名
	 * @return 属性对象
	 */
	public static Field getField(Class<?> clazz,String name){
		
		for(Class<?> c = clazz;c != null;c = c.getSuperclass()){
			try {
				Field field = c.getDeclaredField(name);
				return field;
			} catch (NoSuchFieldException e) {
			} catch (SecurityException e) {
			}
		}
		return null;
	}
	
	/**
	 * 设置对象中的属性
	 * @param obj 对象
	 * @param name 属性名
	 * @param value 属性值
	 */
	public static void setField(Object obj,String name,Object value){
		
		Field field = getField(obj.getClass(), name);
		if(field != null){
			field.setAccessible(true);
			try {
				field.set(obj, value);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 创建对象
	 * @param clazz class对象
	 * @param paremeterType 构造方法中的参数类型数组
	 * @param paremeters 构造方法中的参数数据
	 * @return 对象
	 */
	public static <T> T newInstance(Class<T> clazz,Class<?>[] parameterTypes,Object[] paremeters){
		
		try {
			Constructor<T> constructor = clazz.getDeclaredConstructor(parameterTypes);
			constructor.setAccessible(true);
			T obj = constructor.newInstance(paremeters);
			return obj;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		return null;
	}
}


网站公告

今日签到

点亮在社区的每一天
去签到