java基础之反射

本文详细讲解如何通过Java反射获取Class类,包括.getDeclaredField和getDeclaredMethod等方法,以及实例化、调用构造函数和方法的实战应用。涵盖了公共与私有成员变量的获取,构造函数的使用,以及构造复杂实例的过程。
摘要由CSDN通过智能技术生成

获取Class类

得到Class类有三种方法:

.class,在加载了某个类的情况下,直接拿它的属性即可,例如:Runtime.class。
obj.getClass()。如果存在某个类的实例obj,那么可以通过getClass()方法得到这个类对应的Class。
Class.forName,也是最常用的。知道了那个类的完整名字后(包括包名),作为参数即可:Class clazz = Class.forName("java.lang.Runtime");

获取成员变量Field

Class类有这些获取属性的方法:

//返回 字段对象,该对象反映此 类对象表示的类或接口的指定声明字段。
getDeclaredField(String name)
//返回 字段对象的数组, 字段对象反映由此 类对象表示的类或接口声明的所有字段。
getDeclaredFields()
//返回 字段对象,该对象反映此 类对象表示的类或接口的指定公共成员字段。
getField(String name)
//返回一个包含 字段对象的数组, 字段对象反映此 类对象所表示的类或接口的所有可访问公共字段。
getFields()

注意:上面两个可以获取的是所有的成员变量,下面的两个得到的只有public的成员变量。第一第三个可以传入一个名字(字符串)来得到指定的成员变量,而第二第四个只能得到一个数组,没法得到指定的。
还有一个需要注意的点,就是前两个虽然不受到public的限制,但是它不能得到父类的成员变量。后两个虽然只能得到public成员变量,但是可以得到父类的public成员变量。

举个例子

        Class clazz = Class.forName("com.a.Student");
        Field code = clazz.getDeclaredField("code");
        System.out.println(code.getName());
        
 		//我们可以用set方法去设置类
		 code.set(1,1);

获取方法Method

Class类有这些获取Method的方法:

//返回 方法对象,该对象反映此 类对象表示的类或接口的指定声明方法。
getDeclaredMethod(String name,<?>... parameterTypes);
//返回一个包含 方法对象的数组, 方法对象反映此 类对象表示的类或接口的所有已声明方法,包括public,protected,default(package)访问和私有方法,但不包括继承的方法。
getDeclaredMethods();
//返回 方法对象,该对象反映此 类对象表示的类或接口的指定公共成员方法。
getMethod(String name,<?>... parameterTypes);
//返回一个包含 方法对象的数组, 方法对象反映此 类对象所表示的类或接口的所有公共方法,包括由类或接口声明的那些以及从超类和超接口继承的那些。
getMethods();

 Class clazz = Class.forName("java.lang.Runtime");
 clazz.getMethod("exec", String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz), "calc.exe");

获取构造函数

//返回一个 构造器对象,该对象反映此 类对象所表示的类或接口的指定构造函数。
getDeclaredConstructor(<?>... parameterTypes)
//返回 构造器对象的数组, 构造器对象反映由此 类对象表示的类声明的所有构造函数。
getDeclaredConstructors()
//返回一个 构造器对象,该对象反映此 类对象所表示的类的指定公共构造函数。
getConstructor(<?>... parameterTypes)
//返回一个包含 构造器对象的数组, 构造器对象反映了此 类对象所表示的类的所有公共构造函数。
getConstructors()

        Class clazz = Class.forName("com.javalearn.summer.Employee");
        Constructor cons = clazz.getDeclaredConstructor(String.class,double.class);

实例化类

直接用class.newInstance() 的作用就是调用这个类的无参构造函数

        Class clazz = Class.forName("com.javalearn.summer.Employee");
        Object o = clazz.newInstance();
        System.out.println(o);

但是这样实例化类,相当于调用类的无参构造器,当需要调用非无参构造器来实例化类的时候,就需要用到之前得到的Constructor了:

        Class clazz = Class.forName("com.javalearn.summer.Employee");
        Constructor cons = clazz.getDeclaredConstructor(String.class,double.class);
        Object f = cons.newInstance("feng", 123);

调用方法

正常执行方法是 [1].method([2], [3], [4]…) ,其实在反射里就是method.invoke([1], [2], [3], [4]…)

那么我们调用命令执行的方法步骤拆分开来就是

Class clazz = Class.forName("java.lang.Runtime");
Method execMethod = clazz.getMethod("exec", String.class); 
Method getRuntimeMethod = clazz.getMethod("getRuntime");
Object runtime = getRuntimeMethod.invoke(clazz); 
execMethod.invoke(runtime, "calc.exe");

或者我们也可以直接用 getDeclaredConstructor 来获取这个私有的构造方法来实例化对象,进而执行命令

//这里使用了一个方法 setAccessible ,这个是必须的。我们在获取到一个私有方法后,必须用
//setAccessible 修改它的作用域,否则仍然不能调用

Class clazz = Class.forName("java.lang.Runtime"); 
Constructor m = clazz.getDeclaredConstructor(); 
m.setAccessible(true); 
clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值