`

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

    博客分类:
  • java
阅读更多

因一时兴起看了一些有关 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反射调用实例代码

    该资源包含了一个利用反射执行的一些操作,包含了动态执行构造方法,动态运行私有方法,为属性初始化等等,简单易懂。

    Java 反射机制详解

    Java 反射机制详解,适合初学者 1.获取 对象建模类的类型 的方法: 2.获取类中定义的构造方法: 获取类中定义的方法 获取类中定义的属性: 3.获取类实现的接口 4.利用反射实现类: 5.调用私有方法

    eclipse安卓开发必备工具

    这样就可以创建只有构造函数的实例、调用私有构造方法,访问类的私有属性。 呵呵,这样好像java安全性就大大降低.如果你非常注重应用的安全性,java当然考虑到这方面,你可以在JVM启动参数增加 -Djava.security....

    AJAX 源码范例

    06/6.4.2.html 实现类的私有成员范例 06/6.6.1.html 利用共享prototype实现继承范例 06/6.6.2.html 利用反射机制和prototype实现继承范例 06/6.6.3.html prototype-1.3.1框架中的类继承实现机制...

    【。net 专业】 面试题

    利用反射,配置 将类于数据库表映射 7.用sealed修饰的类有什么特点 sealed 修饰符用于防止从所修饰的类派生出其它类。如果一个密封类被指定为其它类的基类,则会发生编译时错误。 密封类不能同时为抽象类。 sealed ...

    asp.net知识库

    利用反射来查看对象中的私有变量 关于反射中创建类型实例的两种方法 ASP.Net应用程序的多进程模型 NET委托:一个C#睡前故事 [推荐] - [原创] Microsoft .NET策略及框架概述 卸载Class? Web Form 窗体 如何实现web...

    Java开发技术大全(500个源代码).

    invokeMethod.java 利用反射机制调用成员方法 listConstructors.java 利用反射机制获取构造器列表 listFields.java 利用反射机制获取成员属性列表 listMethods.java 利用反射机制获取成员方法列表 loadClass....

    JAVA面试题最全集

    一、Java基础知识 1.Java有那些基本数据类型,String是不是基本...这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的,因此所有的类都继承了它。子类覆盖 finalize() ...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例160 利用反射重写toString()方法 208 实例161 反射与动态代理 209 7.3 常见的未检查型异常 210 实例162 算数异常 210 实例163 数组存值异常 211 实例164 数组下标越界异常 212 实例165 空指针异常 213 7.4 常见...

    Scala程序设计(第2版)

    17.3 利用Actor模型构造稳固且可扩展的并发应用 371 17.4 Akka:为Scala设计的Actor系统 372 17.5 Pickling和Spores 383 17.6 反应式编程 384 17.7 本章回顾与下一章提要 385 第18章 Scala与大数据...

    net学习笔记及其他代码应用

    6.如果在一个B/S结构的系统中需要传递变量值,但是又不能使用Session、Cookie、Application,您有几种方法进行处理? 答 : this.Server.Transfer 7.请编程遍历页面上所有TextBox控件并给它赋值为string.Empty? ...

    整理后java开发全套达内学习笔记(含练习)

    进行高精度运算可以用java.math包中BigDecimal类中的方法。 自动类型提升又称作隐式类型转换。 强制类型转换:int ti; (byte) ti ; 强制转换,丢弃高位 宣告变量名称的同时,加上“final”关键词来限定,这个...

Global site tag (gtag.js) - Google Analytics