前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用 Java 中的反射机制调用类中的私有方法原理详解

使用 Java 中的反射机制调用类中的私有方法原理详解

作者头像
白鹿第一帅
修改2021-03-03 14:13:05
3.5K0
修改2021-03-03 14:13:05
举报

文章目录

  • 前言
  • 一、私有方法在本类中直接调用
    • 1、在本类中实例化,调用私有方法
    • 2、尝试在其他类直接调用私有方法(错误示范)
  • 二、使用反射机制实例化类强制调用私有方法
    • 1、使用类加载器加载被调用的类
    • 2、使用 Object 类对获取的类进行实例化
    • 3、调用 Java 反射中的 Method 类
    • 4、取消 Java 语言的访问检查
    • 5、使用 method.invoke(Object obj,Object args[]);返回对象
  • 三、完整实现代码、运行结果及总结
  • 总结

前言

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

在这里插入图片描述
在这里插入图片描述

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

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

说明:被 private 关键字修饰的构造方法、方法或者数据域只在其所在的类中可见。

如下:我们创建一个Demo类,并定义一个私有的方法demo(),使用main函数在本类中使用new关键字实例化类,去调用demo()方法,运行成功输出结果。

代码语言:javascript
复制
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();
	}
}
在这里插入图片描述
在这里插入图片描述

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

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

在这里插入图片描述
在这里插入图片描述

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

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

代码语言:javascript
复制
Class<?> cls = Class.forName("com.bailu.demo.Demo");

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

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

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

代码语言:javascript
复制
Object obj = cls.newInstance();

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

3、调用 Java 反射中的 Method 类

代码语言:javascript
复制
Method method = cls.getDeclaredMethod("demo", null);

说明: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 参数指定方法的参数类型

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

代码语言:javascript
复制
method.setAccessible(true);

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

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

5、使用 method.invoke(Object obj,Object args[]);返回对象

使用 method.invoke(Object obj,Object args[]);返回对象,强制执行对象中的目标方法。

代码语言:javascript
复制
method.invoke(obj, null);

说明:Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回。

三、完整实现代码、运行结果及总结

Demo 类:

代码语言:javascript
复制
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 类:

代码语言:javascript
复制
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();
		}
	}
}

运行结果如下图所示:

在这里插入图片描述
在这里插入图片描述

总结

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

在这里插入图片描述
在这里插入图片描述

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 前言
  • 一、私有方法在本类中直接调用
    • 1、在本类中实例化,调用私有方法
      • 2、尝试在其他类直接调用私有方法(错误示范)
      • 二、使用反射机制实例化类强制调用私有方法
        • 1、使用类加载器加载被调用的类
          • 2、使用 Object 类对获取的类进行实例化
            • 3、调用 Java 反射中的 Method 类
              • 4、取消 Java 语言的访问检查
                • 5、使用 method.invoke(Object obj,Object args[]);返回对象
                • 三、完整实现代码、运行结果及总结
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档