Java 反射机制详解:私有方法调用头大?如何通过反射调用类中的私有方法?

简介: Java 反射机制详解:私有方法调用头大?如何通过反射调用类中的私有方法?

文章目录


前言

在 Java 中如果我们使用 new 关键字调用构造函数对类进行实例化,我们就可以根据在这个类中的修饰符来访问类中定义的非私有方法。但是如果需要在其他类调用私有的方法,就可以利用 Java 中提供的反射来实现。

image.png


一、私有方法在本类中直接调用

1.1、在本类中实例化,调用私有方法

说明:被 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();
  }
}

image.png

1.2、尝试在其他类直接调用私有方法(错误示范)

如果我们直接在其他的类中实例化 Demo 类,来直接调用 demo() 方法,就会发现 IDE 直接产生编译错误,很明显我们直接在另一个类中调用私有方法是行不通的,IDE 提示我们把 private 修饰符去掉,这又是不满足我们需求的,如下图所示:

image.png

二、使用反射实例化类强制调用私有方法

2.1、使用类加载器加载被调用的类

Class<?> cls = Class.forName("com.bailu.demo.Demo");
• 1

说明:这里的Class<?> 即为 Java 中的泛型。以下是我们在开发中常见的几种泛型:

  • 表示不确定的 Java 类型
  • T 表示 Java 类型
  • K V 分别代表 Java 键值中的 Key Value
  • E 代表 Element

2.2、使用 Object 类对获取的类进行实例化

Object obj = cls.newInstance();

说明Object是所有类的根类,是具体的一个类,使用的时候可能需要类型强制转换的,但是用通配符 ?、T 、K 、V、 E 等这些的话,在实际用之前类型就已经确定了,不需要强制转换。

2.3、调用 Java 反射中的 Method 类

Method method = cls.getDeclaredMethod("demo", null);

说明Method类是java.lang.reflect中提供的一个类。我们通过实例化Method类来调用Method类中的方法,常用方法有以下几个:

  • getMethods():获得类的 public 类型的方法
  • getMethod(String name, Class[] params):获得类的特定方法,name 参数指定方法的名字,params 参数指定方法的参数类型
  • getDeclaredMethods():获取类中所有的方法(public、protected、default、private)
  • getDeclaredMethod(String name, Class[] params):获得类的特定方法,name 参数指定方法的名字,params 参数指定方法的参数类型

这里我们调用第四个获取 Demo 类的 demo() 方法,参数类型为 null。

2.4、取消 Java 语言的访问检查

method.setAccessible(true);

setAccessible(true/false):表示禁用和启用安全检查的开关。

说明:当值为true时,指反射对象在使用时应该取消 Java 语言访问检查,值为false则只是反射的对象应该试试 Java 语言访问检查。当值设置为true时,不接受检查,可以提高反射的运行速度。

2.5、使用 method 方法返回对象

使用 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();
    }
  }
}

运行结果如下图所示:

image.png


总结

在我们的开发过程中,通常只有实体类(Entity)中的成员变量使用 private 修饰,并且会提供访问这些变量的 get 和 set 方法。原则上要求不准定义私有的方法,我们使用 method.invoke(Object obj,Object args[]); 强制调用对象调用私有方法违反了我们 Java 中面向对象的特性。

image.png


我是白鹿,一个不懈奋斗的程序猿。望本文能对你有所裨益,欢迎大家的一键三连!若有其他问题、建议或者补充可以留言在文章下方,感谢大家的支持!



相关文章
|
4天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
31 4
|
15天前
|
Java API
Java 对象释放与 finalize 方法
关于 Java 对象释放的疑惑解答,以及 finalize 方法的相关知识。
35 17
|
8天前
|
Java 测试技术 Maven
Java一分钟之-PowerMock:静态方法与私有方法测试
通过本文的详细介绍,您可以使用PowerMock轻松地测试Java代码中的静态方法和私有方法。PowerMock通过扩展Mockito,提供了强大的功能,帮助开发者在复杂的测试场景中保持高效和准确的单元测试。希望本文对您的Java单元测试有所帮助。
13 2
|
14天前
|
Java
Java中的反射机制与应用实例
【10月更文挑战第22天】Java作为一门面向对象的编程语言,提供了丰富的特性来支持对象的创建、操作和交互。其中,反射机制是Java的一项核心特性,它允许程序在运行时动态地获取类的信息、创建对象、调用方法、访问属性等。本文将从三个部分探讨Java中的反射机制及其应用实例:一是反射机制的基本概念和原理;二是反射机制在Java中的应用场景;三是通过实例深入理解反射机制的使用方法和技巧。
14 4
|
16天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
13 2
|
16天前
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
13 1
|
16天前
|
存储 Java
[Java]反射
本文详细介绍了Java反射机制的基本概念、使用方法及其注意事项。首先解释了反射的定义和类加载过程,接着通过具体示例展示了如何使用反射获取和操作类的构造方法、方法和变量。文章还讨论了反射在类加载、内部类、父类成员访问等方面的特殊行为,并提供了通过反射跳过泛型检查的示例。最后,简要介绍了字面量和符号引用的概念。全文旨在帮助读者深入理解反射机制及其应用场景。
12 0
[Java]反射
|
10天前
|
Java Spring
JAVA获取重定向地址URL的两种方法
【10月更文挑战第17天】本文介绍了两种在Java中获取HTTP响应头中的Location字段的方法:一种是使用HttpURLConnection,另一种是使用Spring的RestTemplate。通过设置连接超时和禁用自动重定向,确保请求按预期执行。此外,还提供了一个自定义的`NoRedirectSimpleClientHttpRequestFactory`类,用于禁用RestTemplate的自动重定向功能。
|
3月前
|
Java 开发者
奇迹时刻!探索 Java 多线程的奇幻之旅:Thread 类和 Runnable 接口的惊人对决
【8月更文挑战第13天】Java的多线程特性能显著提升程序性能与响应性。本文通过示例代码详细解析了两种核心实现方式:Thread类与Runnable接口。Thread类适用于简单场景,直接定义线程行为;Runnable接口则更适合复杂的项目结构,尤其在需要继承其他类时,能保持代码的清晰与模块化。理解两者差异有助于开发者在实际应用中做出合理选择,构建高效稳定的多线程程序。
57 7
|
16天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
13 3
下一篇
无影云桌面