public class ReadOnlyClass {
private String name = "hello";
public String getName(){
return name;
}
}
问题:能否将ReadOnlyClass 类的一个对象,把它的name属性的值由hello改为world?如果能,请写出实现代码。如果不能请说明理由。
解答:可以。利用java的反射。
分析:任何一个类,我们可以得到它运行时的Class实例,对于ReadOnlyClass 类,我们可以通过ReadOnlyClass .class得到它运行时的Class实例,接着我们可以通过该类的Class实例去获得这个name这个属性所对应的Field对象。我们知道对应一个类的属性都有一个和它相关的Field对象存在,对于构造方法来说有一个Constructor对象存在,对于一个方法来说有一个对应的Method对象存在。通过这些我们可以利用发射来给这些属性动态的赋值。首先我们来看jdk api中Class类的两个方法的叙述:
public Field getField(String name)throws NoSuchFieldException,SecurityException
Returns a Field object that reflects the specified public member field of the class or interface represented by this Class object. The name parameter is a String specifying the simple name of the desired field.(翻译:返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定publlic属性字段。name 参数是一个 String,用于指定所需字段的简称。)
The field to be reflected is determined by the algorithm that follows. Let C be the class represented by this object:(翻译:要反映的字段由下面的算法确定。设 C 为此对象所表示的类:)
If C declares a public field with the name specified, that is the field to be reflected.(翻译:如果 C 声明一个带有指定名的公共字段,则它就是要反映的字段。)
If no field was found in step 1 above, this algorithm is applied recursively to each direct superinterface of C. The direct superinterfaces are searched in the order they were declared.(翻译:如果在第 1 步中没有找到任何字段,则该算法被递归地应用于 C 的每一个直接超接口。直接超接口按其声明顺序进行搜索)
If no field was found in steps 1 and 2 above, and C has a superclass S, then this algorithm is invoked recursively upon S. If C has no superclass, then a NoSuchFieldException is thrown.(翻译:如果在第 1、2 两步没有找到任何字段,且 C 有一个超类 S,则在 S 上递归调用该算法。如果 C 没有超类,则抛出 NoSuchFieldException。)
See The Java Language Specification, sections 8.2 and 8.3. (翻译:请参阅《Java Language Specification》的第 8.2 和 8.3 节。 )
public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException
Returns a Field object that reflects the specified declared field of the class or interface represented by this Class object. The name parameter is a String that specifies the simple name of the desired field. Note that this method will not reflect the length field of an array class.(翻译:返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。name 参数是一个 String,它指定所需字段的简称。注意,此方法不反映数组类的 length 字段。)
从上面的jdk api我们知道,要得到name属性对应的Field对象,我们只能调用Class的getDeclaredField方法,因为getField方法只能得到一个类的public的属性对应的Field对象,而这里的name属性是private的。我们通过Class的getDeclaredField方法得到name属性对应的Field对象后,我们就可以调用Field对象的set(对象,属性值)方法给name属性赋值。由于name是private的,我们要想知道我们到底改变了name的值没有,我们可以通过Field类的父类的setAccessible(boolean flag)方法来压制java语言的访问限制。对于setAccessible方法,我们看jdk文档:
public void setAccessible(boolean flag)throws SecurityException
Set the accessible flag for this object to the indicated boolean value. A value of true indicates that the reflected object should suppress Java language access checking when it is used. A value of false indicates that the reflected object should enforce Java language access checks.(翻译:将此对象的 accessible 标志设置为指示的布尔值。值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。值为 false 则指示反射的对象应该实施 Java 语言访问检查。 )
First, if there is a security manager, its checkPermission method is called with a ReflectPermission("suppressAccessChecks") permission. (翻译:首先,如果存在安全管理器,则在 ReflectPermission("suppressAccessChecks") 权限下调用 checkPermission 方法。)
A SecurityException is raised if flag is true but accessibility of this object may not be changed (for example, if this element object is a Constructor object for the class Class). (翻译:如果 flag 为 true,并且不能更改此对象的可访问性(例如,如果此元素对象是 Class 类的 Constructor 对象),则会引发 SecurityException。)
A SecurityException is raised if this object is a Constructor object for the class java.lang.Class, and flag is true. (翻译:如果此对象是 java.lang.Class 类的 Constructor 对象,并且 flag 为 true,则会引发 SecurityException。)
从jdk文档,我们可以通过setAccessible方法将其设置为true,这样我们就可以去访问name属性了。
实现代码如下:
public class ReadOnlyClassByReflection {
public static void main(String[] args)throws Exception {
ReadOnlyClass pt = new ReadOnlyClass();
Class<?> clazz = ReadOnlyClass.class;
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
field.set(pt, "world");
System.out.println(pt.getName());
}
}
总结:对于一个类,它只有唯一的一个Class对象,它来标识这个对象。这个Class对象就能够获得这个类的结构上的特征。那么通过class对象就可以来获得这个类相应的构造方法,属性等。
获得某一个类它的class对象有4种方式:
1、使用类的.class语法
2、通过类的对象的getClass()方法。getClass()方法在Object类里面定义的。
3、通过Class对象的forName()方法
4、对于包装类,可以通过.TYPE语法方式
通过类的反射机制,我们可以去改变只读的private的属性的值。
分享到:
- 2009-02-27 22:08
- 浏览 1865
- 评论(1)
- 论坛回复 / 浏览 (1 / 2282)
- 查看更多
相关推荐
Java反射机制的实现_Reflection,适合学习了解反射机制。
Java 反射机制、Java 的类反射机制、Java 反射机制的学习、Java 反射Reflection--运行时生成实例 java反射机制的手册文档
Reflection in Java. 介绍Java中的反射机制,候捷谈Java反射机制
java反射,设置属性值,获得属性,具有多个对象同事设置,缓存的处理,
轻松掌握java反射技术,虽然讲得比较简单,但是通俗易懂。
这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public,static 等等)、superclass(例如Object)、实现之interfaces(例如Cloneable),也包括fields和...
Java Reflection (JAVA反射)详解
在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于任意 一个对象,能否调用它的任意一个方法?答案是肯定的。这种动态获取类的信息,以及动态 调用对象的方法的功能来自于Java 语言的反射...
Java反射机制及各成份所对应的Reflection APIs
反射机制允许程序在执行期间借助于Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。 框架=反射+注解+设计模式 1.是什么? 加载完类之后,在堆内的方法区中就产生了一个Class类型的...
之前上课的时候老师总结的JavaReflection反射学习资料,内容简单易懂,浅显易懂,适合小白入手学习。。
Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。例如,使用它能获得 Java 类中各成员的名称并显示出来。 Java 的这一能力在...
Java提供了一套机制来动态执行方法和构造方法,以及数组操作等,这套机制就叫——反射。反射机制是如今很多流行框架的实现基础,其中包括Spring、Hibernate等。原理性的问题不是本文的重点,接下来让我们在实例中...
Java反射机制修改私有成员变量的实现_Reflection,普通方式无法修改私有成员变量的值,但通过反射机制可以实现。
JAVA反射机制及应用例子.。。Reflection API
Java的反射机制是指在程序的运行状态中,**可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用,操作任意一个对象的属性和方法。**这种动态获取程序信息以及...
圣思园 reflection(Java反射) 课件 圣思园 reflection(Java反射) 课件 圣思园 reflection(Java反射) 课件
关于java反射机制的很好的讲解,包括Java的反射机制(Reflection)、Class类、如何获得类的相关信息和运用,并且还有相应的练习,有助于更好地学习java反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。...
是被视为动态语言的关键,反射机制允许程序在执行期借助Reflection API取得任何类的内部信息并能直接操作任意对象的内部属性及方法。 java反射机制所提供的功能: 生成动态代理 在运行时判断任意一个对象所属的类 在...