java反射

文章介绍了Java中的反射机制,包括通过Class.forName()、对象实例的getClass()和类名.class三种方式获取Class对象。接着详细阐述了如何通过反射实例化对象,如无参构造器、有参构造器(包括私有构造器)的调用。此外,还讨论了动态方法调用和读写属性,强调了使用反射可能对封装性和安全性的影响。

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

一. 什么是反射?

概念:反射是java语言的一种机制,通过这种机制,可以动态的实例化对象、读取属性、调用方法。

二. 什么是类类

类类其实指的就是Java中的class类。
Class类是Java反射机制的核心,它用于表示一个类的字节码文件,也就是表示一个类的所有信息。
每个Java类都对应着一个Class对象,这个对象描述了该类的结构信息。它可以让程序在运行时获取类的名称、修饰符、父类、实现的接口、构造方法、字段、方法等类别信息。

三. 类类的获取方式

1.Class.forname(“类的全路径名”)

适用于从配置文件或其他动态输入中获取类的全限定名,动态加载类。

2.类实例.getclass()

适用于已经在程序中存在对象,需要获取该对象所属的类的Class对象。

3.类名.class

适用于在编写源代码时就已经确定要使用的类,且该类已经在代码中引用过。
实体类

package com.xissl.reflect;

public class Student {
	private String sid;

	private String sname;

	public Integer age;
	
	static{
		System.out.println("加载进jvm中!");
	}

	public Student() {
		super();
		System.out.println("调用无参构造方法创建了一个学生对象");
	}

	public Student(String sid) {
		super();
		this.sid = sid;
		System.out.println("调用带一个参数的构造方法创建了一个学生对象");
	}

	public Student(String sid, String sname) {
		super();
		this.sid = sid;
		this.sname = sname;
		System.out.println("调用带二个参数的构造方法创建了一个学生对象");
	}

	@SuppressWarnings("unused")
	private Student(Integer age) {
		System.out.println("调用Student类私有的构造方法创建一个学生对象");
		this.age = age;
	}

	public String getSid() {
		return sid;
	}

	public void setSid(String sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public void hello() {
		System.out.println("你好!我是" + this.sname);
	}

	public void hello(String name) {
		System.out.println(name + "你好!我是" + this.sname);
	}

	@SuppressWarnings("unused")
	private Integer add(Integer a, Integer b) {
		return new Integer(a.intValue() + b.intValue());
	}
}

获取方式:

package com.xissl.reflect;
/**
 * 类类(class类)的获取方式:一切反射的操作都从获取类对象开始
 * 1.Class.forname
 * 2.类实例.getclass()
 * 3.类名.class
 * @author xissl
 */
public class Demo01 {
	public static void main(String[] args) throws Exception {
		Student stu = new Student();
		//1.Class.forname 类的全路径名
		Class class1 = Class.forName("com.xissl.reflect.Student");
		System.out.println(class1);
		//2.类实例.getclass() 通用增删改
		Class class2 = stu.getClass();
		System.out.println(class2);
		//3.类名.class 通用查询
		Class class3 = Student.class;
		System.out.println(class3);
	}

}

四. 反射实例化

Java反射机制提供了通过Class对象实例化一个类的功能。这个功能的实现一般是通过Class类中的newInstance()方法来实现的。

1.无参构造器

newInstance()方法只能调用类的默认无参构造器,所以这种方式只能实例化没有参数的类。

2.有参构造器

如果想要调用有参构造器,使用getConstructor()方法获取Constructor对象,再用newInstance()方法来实例化有参数的类。

3.私有的有参构造器

如果要调用私有的有参构造器,可以使用getDeclaredConstructor()方法获取Constructor对象,然后,使用setAccessible()方法打开私有修饰符的访问权限,并使用newInstance()方法来实例化对象。
代码如下:

package com.xissl.reflect;

import java.lang.reflect.Constructor;

/**
 * 反射实例化
 * 反射默认调用的是无参构造器
 * @author xissl
 *
 */
public class Demo02 {
	public static void main(String[] args) throws Exception {
		Class class1 = Class.forName("com.xissl.reflect.Student");
		//1.调用无参构造器反射实例化
		Student s1 = (Student) class1.newInstance();
		System.out.println(s1);
		//2.调用有一个参数的构造器实例化
		//括号里面填的是参数的类别 
		Constructor cr1 = class1.getConstructor(String.class);
		Student s2 = (Student) cr1.newInstance("s001");
		System.out.println(s2);
		//3.调用有两个参数的构造器实例化
		Constructor cr2 = class1.getConstructor(String.class,String.class);
		Student s3 = (Student) cr2.newInstance("s002","nb");
		System.out.println(s3);
		//4.调用私有的带一个参数的构造器实例化
		Constructor cr3 = class1.getDeclaredConstructor(Integer.class);
		//打开私有修饰符的访问权限
		cr3.setAccessible(true);
		Student s4 = (Student) cr3.newInstance(20);
		System.out.println(s4);
	}

}

需要注意的是,调用私有构造函数可能会破坏封装性和安全性,所以建议在特定情况下再使用。

五. 反射动态方法调用

在Java中,方法是类的行为,定义了对象可以执行的操作。使用反射技术调用对象的方法,在不知道类信息的情况下,可以使程序更加灵活和智能。
使用反射机制动态调用对象的方法,一般是通过Method类中的invoke()方法来实现的。

1. 无参方法

通过getMethod()方法,先获取方法对象,再调用方法对象的invoke()方法。无参方法parameterTypes不需要写,直接删掉。
在这里插入图片描述
name: 要调用的方法名
parameterTypes:参数类型
在这里插入图片描述
obj:类实例
args:参数值

2.有参方法

通过getMethod()方法,先获取方法对象,再调用方法对象的invoke()方法。

3.私有的有参方法

如果方法是私有的或受保护的,也同样可以使用setAccessible()方法访问该方法。

六. 反射读写属性

在Java中,属性是对象的状态,定义了对象所具有的特征。使用反射机制读写对象的属性,在不知道类信息的情况下,可以使程序更加灵活和智能。
使用反射机制读写对象的属性,一般是通过Field类中的get()和set()方法来实现的。

package com.xissl.reflect;

import java.lang.reflect.Field;

/**
 * 反射读写属性
 * @author xissl
 *
 */
public class Demo04 {
	public static void main(String[] args) throws Exception {
		//一切反射从类类开始
		Class class1 = Class.forName("com.xissl.reflect.Student");
		Student student = new Student("s001", "yh");
		//写
		Field snameField = class1.getDeclaredField("sname");
		snameField.setAccessible(true);
		snameField.set(student, "sb");
		//获取属性对象 读
		Field[] f = class1.getDeclaredFields();
		for (Field field : f) {
			field.setAccessible(true);
			System.out.println(field.getName()+":"+field.get(student) );
		}
	}

}

在使用反射读写对象的属性时,如果访问的属性是私有的或受保护的,也需要使用setAccessible()方法将其设置为可访问。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不念那年晚春

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值