理解java反射

本文介绍Java反射的基本原理,演示如何通过三种方式获取Class对象,并详细解析如何利用反射技术获取类的各种信息,包括路径、属性、方法及构造器等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Java中每个类被加载后,系统会为该类生成一个Class对象,且是唯一的。通过Class对象就可以访问到JVM中的这个类。我们就可以拿到万恶之源——Class对象,去获得这个类的所有信息。

例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖。

one

新建一个类,去拿到这个类在JVM中的Class对象。同时验证一下此万恶之源是唯一的。

提供一个类,我们去反射它。

package cn.liu.review;


public class Student {
	private int id;
	private String studentName;
	private int age;
	
	
	public Student() {}
	
	public Student(int id, String studentName, int age) {
		super();
		this.id = id;
		this.studentName = studentName;
		this.age = age;
	}
	
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getStudentName() {
		return studentName;
	}
	public void setStudentName(String studentName) {
		this.studentName = studentName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
}

三种获取类信息的方式。

1.类名.class           说明: JVM将使用类装载器, 将类装入内存(前提是:类还没有装入内存),不做类的初始化工作.返回Class的对象

2.Class.forName("类名字符串")  (注:类名字符串是包名+类名)  说明:装入类,并做类的静态初始化,返回Class的对象

3.实例对象.getClass()  说明:对类进行静态初始化、非静态初始化;返回引用运行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类的Class的对象

package cn.liu.review;

/**
 * 测试反射
 * @author Administrator
 *
 */
public class Demo01 {
	public static void main(String[] args) throws Exception {
		//拿到此类的Class对象,此Class对象在堆内存中存着此类的信息
		//1.
		Class clz = Class.forName("cn.liu.review.Student");
		System.out.println(clz.hashCode());
		//2.
		Student s = new Student();
		Class aa = s.getClass();
		System.out.println(aa.hashCode());
		//3.
		Class bb = Student.class;
		System.out.println(bb.hashCode());
	}
}

two

通过反射获得类的信息(属性,构造器,方法等等)

package cn.liu.review;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
 * 通过反射获得类的信息(属性,构造器,方法等等)
 * @author Administrator
 *
 */
public class Demo02 {
	public static void main(String[] args) throws Exception {
		Class clz = Class.forName("cn.liu.review.Student");
		
		//1.获得类的路径
		System.out.println(clz.getName());//获得包名+类名
		System.out.println(clz.getSimpleName());//获得类名
		//2.获取属性信息
		Field[] dfs = clz.getDeclaredFields();//返回所有属性
		for(Field temp :dfs) {
			System.out.println("属性:"+temp);
		}
		System.out.println("----------------------------");
		Field[] fs = clz.getFields();//返回只能获得public的属性
		for(Field temp:fs) {
			System.out.println(temp);
		}
		System.out.println("----------------------------");
		//3.获得方法信息
		// Class对象所表示的类(包括那些由该类声明的以及从超类和超接口继承的那些的类或接口)的公共 member 方法
		Method[] ms= clz.getMethods();
		for(Method temp:ms) {
			System.out.println(temp);
		}
		System.out.println("----------------------------");
		//如果方法有参数,必须传递类型
		Method dm = clz.getDeclaredMethod("setStudentName", String.class);
		System.out.println(dm);
		//4.获得构造方法信息
		Constructor[] dcs = clz.getDeclaredConstructors();
		for(Constructor temp:dcs) {}
		System.out.println(dcs);
		System.out.println("----------------------------");
		Constructor cs = clz.getConstructor(null);//获得特定参数的构造器
		System.out.println(cs);
	}
	
}

 

 three

package cn.liu.review;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * 利用反射动态调用构造器,对象,属性等等
 * @author Administrator
 *
 */
public class Demo03 {
	public static void main(String[] args) throws Exception {
		//拿到万恶之源Class对象
		Class<Student> clz = (Class<Student>)Class.forName("cn.liu.review.Student");
		
		//利用反射动态调用构造器
		//调用构造参数,构造对象
		Student s1 = clz.newInstance();//本质是调用了无参构造器
		System.out.println("s1:"+s1.getStudentName());
		//1.获得想要的构造器
		Constructor dc = clz.getDeclaredConstructor(int.class,int.class,String.class);
		//2.构造对象
		Student s2 = (Student) dc.newInstance(2,2,"three");
		System.out.println("s2:"+s2.getStudentName());
		
		//通过反射调用普通方法
		//1.创建对象
		Student s3 = (Student) dc.newInstance(55,12,"小明");
		//2.获得想要的方法
		Method me = clz.getDeclaredMethod("setStudentName", String.class);
		//3.传参,调用
		me.invoke(s3, "小红");
		System.out.println("s3:"+s3.getStudentName());
		
		//通过反射操作属性
		//1.获得指定的属性
		Field f = clz.getDeclaredField("studentName");
		f.setAccessible(true);//属性不需要做安全检查了可以访问private
		//2.传参
		f.set(s3, "小王");
		System.out.println("s3:"+f.get(s3));//也是通过反射
		
	}
}

 four

反射操作注解,反射操作泛型等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值