因一时兴起看了一些有关
Java
反射(
Reflection
)的东西。以下要说明的问题是如何直接对某个特定类的私有属性(
private field
)不使用其暴露的
set
方法而是直接进行设值操作,或调用类的私有方法(
private method
)。
首先要说明的是,这在
java
里是允许这么做的。虽然这样直接访问私有属性或调用私有方法,会破坏了
OO
的一大基本原则:封装,但
Java
里是千真万确的提供了这么做的基础的。一些
Open source framework
的“豪华”功能也是依赖于此的。
此前在网上看到不少兄弟提出过这样的问题,有人略带讽刺的回复说这样做是不可以的。在这里不才给出一个简单的示例来说明如何完成的这个被看成
Mission Imposable
的。
首先我们建立一个测试用的类(
TargetClass
):
package
org.rossalee.test;
public
class
TargetClass
{
public
String
name
;
private
String
age
;
public
TargetClass() {
super
();
}
public
void
showName() {
System.
out
.println(
name
);
}
private
void
showAge() {
System.
out
.println(
age
);
}
}
这个目标类里有一个
public
权限
String
类型
“
name
”
属性和一个
private
权限
String
类型的“
age
”属性,以及一个
public
方法“
showName()
”和
private
方法“
showAge()
”。
一般来说我们是可以直接操作该类的
name
属性或调用
showName()
方法的。这都是很正常。但如果想要对
age
属性进行设值的话,那就只能依靠
TargeClass
提供一个修饰为
public
的
setAge(String age)
的设值方法,才能进行设值。但我们上面这个类里并没有提供,所以那这个
age
属性基本上是没有办法进行再设值的了。同样,我们也不可以调
TargetClass
类的
shwoAge()
方法。因为他也是
private
的。
但我们使用
Java Core API
提供的
Reflect
就可以完成这个功能。
以下是实现对私有属性进行操作的基本步骤:
<!---->一、
<!---->使用
Class
对象提供的
static
方法
forName()
方法,将类进行加载,成为
Java
里一种特殊的对象——类对象。
<!---->二、
<!---->使用
Class
对象提供的方法
getDeclaredFields()
,此方法
返回
Field
对象的一个数组,这些对象反映此
Class
对象所表示的类或接口所声明的所有字段。即有公共的也有私有的。
<!---->三、
<!---->调用对于要进行操作的
field
对象的
setAccessible()
。参数传入“
true
”。此方法从
java.lang.reflect.AccessibleObject
对象中继承而来。执行该方法后,就可以对
age
属性进行操作了。但设值是要有特定的方法来实现的。另外,还有一点要说明的是,此时加载的类对象是没有实例化的,所以最终我们要进行设值的并不是这个类对象,而
TargetClass
类型的对象。这个对象你可以自己
new
出来,也可以通过调用类对象的
newInstance()
方法实例出来。在这里我们暂定这个
new
出来的
TargetClass
对象为
tc
,即:
TargetClass tc=new TargetClass()
。
<!---->四、
<!---->这时我们要用
Field
对象提供的
set(Object obj, Object value)
方法进行设置。这个方法有两个参数:
obj
就传入我们在一步
new
出来的
tc
。
Value
就传入
age
所属类型的值,这里的
age
是
String
类型,这里传一个
String
进来就可以了。
对于私有方法的调用也基本相同,但只是最后使用的是
Method
对象的
invoke(Object obj, Object... args)
方法。
Obj
一样也是
tc
,
args
则是
showAge()
方法的参数,这里是无参的,所以传一个
null
进去就可以了。
实现代码如下:
package
org.rossalee;
import
java.lang.reflect.Field;
import
java.lang.reflect.InvocationTargetException;
import
java.lang.reflect.Method;
import
org.rossalee.test.TargetClass;
public
class
TestMain {
public
static
void
main(String[] args) {
Class clazz =
null
;
try
{
clazz = Class.forName
(
"org.rossalee.test.TargetClass"
);
}
catch
(ClassNotFoundException e) {
e.printStackTrace();
}
Field[] f = clazz.getDeclaredFields();
for
(
int
i = 0; i < f.
length
; i++) {
System.
out
.println(
"Field
"
+ i +
" : "
+ f[i].getName());
}
Method[] m = clazz.getDeclaredMethods();
for
(
int
i = 0; i < m.
length
; i++) {
System.
out
.println(
"Method
"
+ i +
" : "
+ m[i].getName());
}
TargetClass tc =
null
;
try
{
tc = (TargetClass) clazz.newInstance();
}
catch
(InstantiationException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
f[1].setAccessible(
true
);
try
{
f[1].set(tc,
"kenshin"
);
}
catch
(IllegalArgumentException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
m[1].setAccessible(
true
);
try
{
m[1].invoke(tc,
null
);
}
catch
(IllegalArgumentException e) {
e.printStackTrace();
}
catch
(IllegalAccessException e) {
e.printStackTrace();
}
catch
(InvocationTargetException e) {
e.printStackTrace();
}
}
}
分享到:
相关推荐
尽管可以利用反射访问私有成员,但这应被视为一种特殊情况下的权宜之计,而不是常规编程实践。在单元测试中,适度使用反射可以帮助验证私有方法的行为,但也要注意保持测试的独立性和稳定性。在设计和实现代码时,应...
在Java编程语言中,反射(Reflection)是一种...通过阅读和分析这个文件,你可以更深入地理解如何利用反射来获取和设置私有属性的值。在实际学习中,你可以尝试运行这个程序,观察其输出,以便更好地掌握反射的用法。
在本篇文章中,我们将深入探讨如何利用C#中的反射机制来访问类中的私有变量或方法。通过一个具体的示例代码,我们将详细了解反射的基本概念、使用场景以及如何具体操作。 ### 一、C#反射机制简介 #### 1.1 什么是...
本文主要讲解了在遇到需要操作Java对象的参数或返回值时,如何利用Frida这一动态代码插桩工具来进行反射调用,包括调用对象的方法和获取对象的字段。Frida是一个强大的动态代码插桩工具,它可以注入到几乎所有的进程...
然而,对于类的私有成员(包括私有方法和私有属性),由于其封装性,通常不易直接进行测试。但实际情况中,私有成员可能对类的行为产生关键影响,因此测试它们也是必要的。本文将介绍如何使用JUnit4结合Java的反射...
Java反射是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射主要用于在运行时分析类和对象,包括类的方法、字段、构造器等信息。这篇博文将带你...
4. 设置访问权限:如果要访问私有字段,需要先调用`Field`对象的`setAccessible(true)`方法,以绕过访问控制检查。 5. 赋值:最后,使用`Field`对象的`set()`方法,传入目标对象和要赋的值,即可完成属性赋值。例如...
在Java编程语言中,反射(Reflection)是一种强大的工具,它允许程序在运行时检查和操作对象的内部结构,包括类的属性、方法以及构造器。...通过上述步骤,你可以有效地利用反射获取和操作类的父类属性和方法。
一旦我们有了`Class`对象,我们就可以利用反射来创建对象,调用方法和访问属性。例如,我们可以使用`newInstance()`方法创建一个新对象,但前提是没有参数的构造函数: ```java Person person = (Person) person...
通过反射,我们可以访问私有属性,甚至可以调用无公开接口的方法。 ```java public class ReflectionCopy { public static void copyProperties(Object source, Object target) throws Exception { Class<?> ...
在.NET框架中,反射是一种强大的工具,它允许程序在运行时检查自身并执行各种操作,如创建对象、访问属性和方法、以及调用未知类型的成员。在这个实例中,我们将探讨如何使用反射来调用DLL(动态链接库)中的方法。 ...
本文将详细介绍如何利用Java反射机制来访问和操作父类的所有属性和方法。 #### 二、Java反射基础 在深入讨论如何操作父类之前,我们先简要回顾一下Java反射的基本概念: - **Class**: 每个类都有一个与之对应的`...
在给定的场景中,我们利用反射机制实现了动态调用计算器的加法和减法函数,并修改了学生对象的私有数据成员。下面将详细讲解这些知识点。 首先,让我们关注`Calculator`类中的加法和减法函数。假设`Calculator`类有...
Java反射机制是Java语言提供的一种强大功能,它允许我们在运行时检查类、接口、字段...在上述示例中,我们展示了如何利用反射来实现计算器的动态调用和修改私有学生对象的属性,这些都展示了反射机制的灵活性和实用性。
Java反射机制是Java编程语言中一个强大的特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具备了在运行时动态地获取类的信息(如类名、方法名、参数类型等)以及创建和...
Java动态调用方法是Java反射机制的一个重要应用,它允许我们在程序运行时,根据需要动态地获取类的信息并调用其方法。这种能力为代码的灵活性和可扩展性...在实际使用中,应结合具体需求权衡利弊,合理利用反射功能。
总的来说,尽管私有属性和方法在设计上是不可直接访问的,但是通过反射API,我们可以进行必要的测试,以确保这些隐藏的实现细节也能正常工作。然而,这种方法应当谨慎使用,因为过度依赖反射可能会影响代码的清晰性...
在Android开发中,反射常用于访问私有成员、调用私有方法或改变私有状态,以实现对系统组件的定制。 在"MediaController反射修改"这个主题中,开发者可能遇到以下关键知识点: 1. **MediaController类的理解**:...
注意,对于私有方法,需要设置`Method`的`accessible`属性为`true`。 以下是一个简单的示例代码片段,展示了如何通过反射调用assets下JAR文件中的方法: ```java // 获取AssetManager AssetManager assetManager =...
本示例中的"实体对象属性动态化(私有属性来源为map)"是一个具体的应用场景,它利用Map来存储实体类的私有属性,从而实现属性的动态添加、修改和访问。下面我们将详细探讨这一技术。 1. **Map接口**:在Java中,Map...