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
- 浏览 1931
- 评论(1)
- 论坛回复 / 浏览 (1 / 2311)
- 查看更多
相关推荐
- 动态代理:Java的`java.lang.reflect.Proxy`类可以利用反射创建动态代理对象。 - 测试工具:JUnit等测试框架利用反射来调用私有方法进行测试。 - 数据库操作:ORM框架如Hibernate通过反射将数据库记录映射为...
* 实现依赖注入:Java 反射机制可以用来实现依赖注入,例如在 Spring 框架中。 * 实现 AOP:Java 反射机制可以用来实现面向方面编程(Aspect-Oriented Programming),例如在 Spring 框架中。 * 实现动态代理:Java ...
在Java中,反射主要用于以下几种情况: 1. 动态类型检查:反射可以在运行时检查对象的实际类型,这在多态编程和泛型中非常有用。 2. 调用私有方法和访问私有字段:通过反射,开发者可以绕过封装性,直接访问和修改...
`Class`对象是反射的起点,它代表了Java中的类或接口。我们可以通过以下三种方式获取`Class`对象: 1. 使用`Class.forName("全限定类名")`,传入类的完全限定名(包括包名)。 2. 调用对象的`getClass()`方法,例如...
`Class`类在Java反射机制中扮演着核心角色,它是所有Java类的运行时表示。`Class`对象可以由以下几种方式获取: 1. **通过类的`Class`属性获取**:如`String.class`。 2. **通过对象的`getClass()`方法获取**:如`...
Java反射机制的主要作用包括:获取类的所有属性和方法、构造动态实例、调用类的方法等。通过反射,程序可以动态地创建对象和调用其方法,从而实现更灵活的功能。 #### 二、Java反射机制的由来与发展 Java反射机制...
9. **分析Java反射Class类型的源代码**:深入理解反射机制的工作原理,了解Class文件的结构以及JVM如何加载类对象以支持反射操作。 #### 四、Java反射原理分析 1. **Class文件结构**:每个编译后的Java类都会生成...
1. **Class类**:在Java中,每一个类都有一个与之对应的Class对象。`Class`类是反射的核心,它代表了一个类的所有元数据,如类名、属性、构造器、方法等。通过`Class.forName()`方法或`Object.getClass()`方法可以...
例如,在Java中,反射允许程序动态地获取类的信息、创建对象、调用方法等,这对于框架设计、插件架构等方面极为有用。 #### 二、Java中的类反射 Java的反射机制是一种强大的工具,允许程序在运行时检查和操作类、...
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时获取和操作任何已知名称的类的内部信息。这一机制使得Java具备了一定的动态性,虽然在传统的分类中Java被视为静态类型语言。通过反射,开发者可以在...
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并操作类的对象。这种机制使得Java具有高度的灵活性和动态性,可以在编译时未知类的情况下进行类的加载、实例化、方法调用等操作...
在Java中,反射主要涉及到`java.lang.Class`类、`java.lang.reflect`包下的类如`Constructor`、`Method`和`Field`等。通过这些类,我们可以实现对Java对象的深度控制,比如访问私有属性、调用私有方法、创建对象等。...
### Java中的反射机制 #### 一、反射的概念 反射的概念最早由Smith于1982年提出,是指程序能够访问、检测和修改其自身状态或行为的能力。这一概念的引入促进了计算机科学领域对反射性的研究,并迅速被应用于程序...
Java反射机制允许程序在运行时通过`Reflection APIs`获取类的内部信息,包括修饰符(如`public`、`static`等)、父类(如`Object`)、接口(如`Cloneable`)以及字段和方法的信息,并能够在运行时改变字段的值或调用...
Java反射机制是Java语言的一种功能,可以在程序运行时获取类的信息和调用类的方法。Java反射机制的实现需要借助于四个类:Class、Constructor、Field和Method。通过这些类,可以获取类的所有属性和方法,并调用类的...
### Java 利用反射获取内部类静态成员变量的值操作 #### 一、引言 在Java编程中,反射是一个非常强大的工具,它允许程序在运行时检查类、接口、字段和方法的信息,并且能够创建和操作对象。本文将详细介绍如何使用...
Java 反射机制是 Java 语言提供的一种强大的工具,它允许程序在运行时动态地获取类的信息(如类名、属性、方法等)并进行操作。这种能力使得 Java 应用程序更加灵活,能够在运行时发现和修改自身的行为。然而,反射...
Java反射机制是Java编程语言中的一个重要特性,它允许程序在运行时检查和操作类、接口、字段和方法的信息。通过反射API,开发者可以获取到类的内部细节,包括访问修饰符、超类、实现的接口,以及字段和方法的详细...