使用 Java 中的反射机制调用类中的私有方法原理详解
文章目录
- 前言
- 一、私有方法在本类中直接调用
- 1、在本类中实例化,调用私有方法
- 2、尝试在其他类直接调用私有方法(错误示范)
- 二、使用反射机制实例化类强制调用私有方法
- 1、使用类加载器加载被调用的类
- 2、使用 Object 类对获取的类进行实例化
- 3、调用 Java 反射中的 Method 类
- 4、取消 Java 语言的访问检查
- 5、使用 method.invoke(Object obj,Object args[]);返回对象
- 三、完整实现代码、运行结果及总结
- 总结
说明:被 private
关键字修饰的构造方法、方法或者数据域只在其所在的类中可见。
如下:我们创建一个Demo
类,并定义一个私有的方法demo()
,使用main
函数在本类中使用new
关键字实例化类,去调用demo()
方法,运行成功输出结果。
package com.bailu.demo;
public class Demo {
private void demo() {
System.out.println("私有方法!");
}
// 私有方法只有在本类中可以访问
public static void main(String[] args) {
Demo demo = new Demo();
demo.demo();
}
}
如果我们直接在其他的类中实例化Demo
类,来直接调用demo()
方法,就会发现 IDE 直接产生编译错误,很明显我们直接在另一个类中调用私有方法是行不通的,IDE 提示我们把private
修饰符去掉,这又是不满足我们需求的。
说明:这里的Class<?>
即为 Java 中的泛型。以下是我们在开发中常见的几种泛型:
- ? 表示不确定的 java 类型
- T 表示 java 类型
- K V 分别代表java键值中的Key Value
- E 代表Element
说明:Object
是所有类的根类,是具体的一个类,使用的时候可能需要类型强制转换的,但是用通配符 ?、T 、K 、V、 E
等这些的话,在实际用之前类型就已经确定了,不需要强制转换。
说明:Method
类是java.lang.reflect
中提供的一个类。我们通过实例化Method
类来调用Method
类中的方法。常用方法有以下几个。这里我们调用第四个获取 Demo 类的 demo() 方法,参数类型为 null。
- getMethods():获得类的 public 类型的方法
- getMethod(String name, Class[] params):获得类的特定方法,name 参数指定方法的名字,params 参数指定方法的参数类型
- getDeclaredMethods():获取类中所有的方法(public、protected、default、private)
- getDeclaredMethod(String name, Class[] params):获得类的特定方法,name 参数指定方法的名字,params 参数指定方法的参数类型
setAccessible(true/false)
:表示禁用和启用安全检查的开关。
说明:当值为true
时,指反射对象在使用时应该取消 Java 语言访问检查,值为false
则只是反射的对象应该试试 Java 语言访问检查。当值设置为true
时,不接受检查,可以提高反射的运行速度。
使用 method.invoke(Object obj,Object args[]);返回对象,强制执行对象中的目标方法。
method.invoke(obj, null);
说明:Method
类的invoke(Object obj,Object args[])
方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()
方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()
方法会把它转换为相应的包装类型的对象,再将其返回。
Demo 类:
package com.bailu.demo;
public class Demo {
private void demo() {
System.out.println("私有方法!");
}
// 私有方法只有在本类中可以访问
public static void main(String[] args) {
Demo demo = new Demo();
demo.demo();
}
}
TestDemo 类:
package com.bailu.demo;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestDemo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
// 1、使用类加载器加载被调用的类
Class<?> cls = Class.forName("com.bailu.demo.Demo");
// 2、使用Object类对获取的类进行实例化
Object obj = cls.newInstance();
// 将异常抛出
try {
// 3、调用Java反射中的Method类,将私有方法封装在obj中
Method method = cls.getDeclaredMethod("demo", null);
// 取消 Java 语言的访问检查
method.setAccessible(true);
// 4、使用method.invoke(Object obj,Object args[]);返回对象
method.invoke(obj, null);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
运行结果如下图所示:
我是白鹿,一个不懈奋斗的程序猿。望本文能对你有所裨益,欢迎大家的一键三连!若有其他问题、建议或者补充可以留言在文章下方,感谢大家的支持!
- 点赞
- 收藏
- 关注作者
评论(0)