Java反射机制

本文深入讲解Java反射机制,包括其定义、功能、获取字节码对象的三种方式及实际应用场景,如Spring IOC、动态代理等。

什么是反射?

  • 反射机制是在运行状态中,对于任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。
  • 想要使用反射机制就必须获得该类的字节码对象(.class)。

反射机制能做什么?

  • 在运行时判断一个对象所属的类
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时构造任意一个类的对象
  • 在运行时调用任意一个对象的方法
  • 生成动态代理

获取字节码对象的三种方式

  1. 通过实例对象的getClass()方法获取
Persion p = new Persion();
Class class = p.getClass();
....
  1. 通过类的静态属性获取
Class class = Persion.class;
  1. 通过全限定名直接获取到一个类的字节码文件对象,此时还是源文件阶段,还没有变成字节码文件。
Class class = Class.forName("com.demo.Persion");

开发中最常用的是方式3,它只需要提供全限定名即可创建对象,通常可以配置在配置文件中,更加方便扩展性强。

简单实用例子

创建对象实例

public class Persion{
	String name;
	//省略get/set
}

@Test
public void test(){
	Class class = Class.forName("com.demo.Persion");
	Object obj = class.newInstance();
}

获取构造器创建对象实例

public class Persion{
	String name;
	//省略get/set
	public Persion(String name) {
		this.name = name;
	}
}

@Test
public void test(){
	Class class = Class.forName("com.demo.Persion");
	Constructor	constructor = class.getConstructor(String.class);
	Persion persion = (Persion)constructor.newInstance("tom");
	
	//获取所有构造方法
    Constructor[] constructor = persion.getConstructors();
    for (Constructor cons : constructor) {
       //获得构造函数中的所有参数类型的字节码对象
       Class[] parameterTypes = cons.getParameterTypes();
    }
}

获得成员变量

public class Persion{
	String name;
	public String addr;
	//省略get/set
}

@Test
public void test(){
	Class persion = Class.forName("com.demo.Persion");
    Object obj = persion.newInstance();
    //获得指定成员变量,如果是public修饰的可以使用getFile()获取
    Field file = persion.getDeclareField("name");
	//如果是私有属性,需要打开可见权限
	file.setAccessible(true);
    //设置指定对象的成员变量值
    file.set(obj,"tom");
	
	//获得所有成员变量
	Filed[] fileds = persion.getDeclareFields();
	for(Filed res : fileds) {
		res.setAccessible(true);
		
	}
}

获取对象中的方法

public class Persion{
	//省略属性和get/set
	
	public void print(String message){
		System.out.print("print " + message);
	}
}

	@Test
    public void test() {
        String name = "com.demo.Persion";
        Class serviceClass = Class.forName(name);
        Object obj = serviceClass.newInstance();
        //获得指定名称方法,如果有参数填上参数类型的Class类型
        Method print = serviceClass.getDeclareMethod("print",String.class);
        //私有方法如需要打开可见权限
        print.setAccessible(true);
        //指定某个对象调用方法,有参数就加上参数
        print.invoke(obj,"hahaha");

		//获得所有方法
		Method print = serviceClass.getDeclareMethods();
		for (Method method : methods) {
			method.setAccessible(true);
			//获得方法的参数
            Class<?>[] parameterTypes = method.getParameterTypes();
        }
		
    }

反射的实际使用场景

  1. Spring中的IOC控制反转。容器通过配置文件生产和DI都是依赖反射来实现的。传送门SpringIOC和DI
  2. 动态代理。Java的动态代理中生成代理对象就是通过反射获取接口和获取指定实现类创建实例。
  3. 编辑器的代码提示也是通过反射获取到类中的方法和属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值