`
Rossalee
  • 浏览: 3969 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

利用反射对私有属性/方法进行设置/调用

阅读更多


因一时兴起看了一些有关 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();

       }

    }

}

 

 

0
0
分享到:
评论

相关推荐

    C#私有成员反射调用类库

    尽管可以利用反射访问私有成员,但这应被视为一种特殊情况下的权宜之计,而不是常规编程实践。在单元测试中,适度使用反射可以帮助验证私有方法的行为,但也要注意保持测试的独立性和稳定性。在设计和实现代码时,应...

    java 反射取得类的私有属性,通过私有属性取得属性值

    在Java编程语言中,反射(Reflection)是一种...通过阅读和分析这个文件,你可以更深入地理解如何利用反射来获取和设置私有属性的值。在实际学习中,你可以尝试运行这个程序,观察其输出,以便更好地掌握反射的用法。

    C#net反射实现访问类中的私有变量或者方法

    在本篇文章中,我们将深入探讨如何利用C#中的反射机制来访问类中的私有变量或方法。通过一个具体的示例代码,我们将详细了解反射的基本概念、使用场景以及如何具体操作。 ### 一、C#反射机制简介 #### 1.1 什么是...

    frida反射调用对象中的方法与字段.pdf

    本文主要讲解了在遇到需要操作Java对象的参数或返回值时,如何利用Frida这一动态代码插桩工具来进行反射调用,包括调用对象的方法和获取对象的字段。Frida是一个强大的动态代码插桩工具,它可以注入到几乎所有的进程...

    JUnit4利用反射机制测试类的私有成员

    然而,对于类的私有成员(包括私有方法和私有属性),由于其封装性,通常不易直接进行测试。但实际情况中,私有成员可能对类的行为产生关键影响,因此测试它们也是必要的。本文将介绍如何使用JUnit4结合Java的反射...

    java 反射入门-属性方法调用实例

    Java反射是Java编程语言中的一个强大特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射主要用于在运行时分析类和对象,包括类的方法、字段、构造器等信息。这篇博文将带你...

    利用反射给属性赋值

    4. 设置访问权限:如果要访问私有字段,需要先调用`Field`对象的`setAccessible(true)`方法,以绕过访问控制检查。 5. 赋值:最后,使用`Field`对象的`set()`方法,传入目标对象和要赋的值,即可完成属性赋值。例如...

    用反射的方式获取父类中的所有属性和方法

    在Java编程语言中,反射(Reflection)是一种强大的工具,它允许程序在运行时检查和操作对象的内部结构,包括类的属性、方法以及构造器。...通过上述步骤,你可以有效地利用反射获取和操作类的父类属性和方法。

    Java反射机制,通过对象访问调用类的私有成员或方法

    一旦我们有了`Class`对象,我们就可以利用反射来创建对象,调用方法和访问属性。例如,我们可以使用`newInstance()`方法创建一个新对象,但前提是没有参数的构造函数: ```java Person person = (Person) person...

    通过构造及反射实现类属性赋值

    通过反射,我们可以访问私有属性,甚至可以调用无公开接口的方法。 ```java public class ReflectionCopy { public static void copyProperties(Object source, Object target) throws Exception { Class&lt;?&gt; ...

    反射实例反射调用DLL里的方法

    在.NET框架中,反射是一种强大的工具,它允许程序在运行时检查自身并执行各种操作,如创建对象、访问属性和方法、以及调用未知类型的成员。在这个实例中,我们将探讨如何使用反射来调用DLL(动态链接库)中的方法。 ...

    java反射操作父类所有属性和方法

    本文将详细介绍如何利用Java反射机制来访问和操作父类的所有属性和方法。 #### 二、Java反射基础 在深入讨论如何操作父类之前,我们先简要回顾一下Java反射的基本概念: - **Class**: 每个类都有一个与之对应的`...

    Java反射机制的动态调用计算器的加法,减法函数;修改一个学生对象的私有数据成员

    在给定的场景中,我们利用反射机制实现了动态调用计算器的加法和减法函数,并修改了学生对象的私有数据成员。下面将详细讲解这些知识点。 首先,让我们关注`Calculator`类中的加法和减法函数。假设`Calculator`类有...

    JAVA反射机制动态调用 计算器对象的加法,减法函数;JAVA反射机制修改一个学生对象 的私有数据成员

    Java反射机制是Java语言提供的一种强大功能,它允许我们在运行时检查类、接口、字段...在上述示例中,我们展示了如何利用反射来实现计算器的动态调用和修改私有学生对象的属性,这些都展示了反射机制的灵活性和实用性。

    Java反射机制修改私有成员变量的实现_Reflection

    Java反射机制是Java编程语言中一个强大的特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。这个特性使得Java具备了在运行时动态地获取类的信息(如类名、方法名、参数类型等)以及创建和...

    java动态调用方法

    Java动态调用方法是Java反射机制的一个重要应用,它允许我们在程序运行时,根据需要动态地获取类的信息并调用其方法。这种能力为代码的灵活性和可扩展性...在实际使用中,应结合具体需求权衡利弊,合理利用反射功能。

    PHPUnit测试私有属性和方法功能示例

    总的来说,尽管私有属性和方法在设计上是不可直接访问的,但是通过反射API,我们可以进行必要的测试,以确保这些隐藏的实现细节也能正常工作。然而,这种方法应当谨慎使用,因为过度依赖反射可能会影响代码的清晰性...

    MediaController反射修改

    在Android开发中,反射常用于访问私有成员、调用私有方法或改变私有状态,以实现对系统组件的定制。 在"MediaController反射修改"这个主题中,开发者可能遇到以下关键知识点: 1. **MediaController类的理解**:...

    反射调用assets下的jar

    注意,对于私有方法,需要设置`Method`的`accessible`属性为`true`。 以下是一个简单的示例代码片段,展示了如何通过反射调用assets下JAR文件中的方法: ```java // 获取AssetManager AssetManager assetManager =...

    实体对象属性动态化(私有属性来源为map)代码.rar

    本示例中的"实体对象属性动态化(私有属性来源为map)"是一个具体的应用场景,它利用Map来存储实体类的私有属性,从而实现属性的动态添加、修改和访问。下面我们将详细探讨这一技术。 1. **Map接口**:在Java中,Map...

Global site tag (gtag.js) - Google Analytics