`
冇心人
  • 浏览: 56437 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

Java常见笔试面试题目解析(六): 利用java的反射机制(reflection)改变类中只读属性

阅读更多
public class ReadOnlyClass {  
        private String name = "hello";  
    public String getName(){  
        return name;  
    }  
}  
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属性了。

实现代码如下:

Java代码
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());  
    }  
}  
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的属性的值。
分享到:
评论

相关推荐

    Java常见笔试_面试题目深度剖析

    Java常见笔试_面试题目深度剖析

    Java常见笔试、面试题目深度剖析

    提供的资源如"Java常见笔试、面试题目深度剖析一(未加密).exe"和"Java常见笔试,面试题目深度剖析.ppt"应包含了对这些知识点的详细解析和实例,对于复习和准备是非常有价值的。建议考生结合这些资料进行系统性学习,...

    Java常见笔试,面试题目深度剖析

    Java常见笔试,面试题目深度剖析

    Java常见笔试、面试题目深度剖析第二、三讲下载地址

    根据提供的信息,我们可以深入探讨与“Java常见笔试、面试题目深度剖析第二、三讲”相关的知识点。虽然直接的视频或文档链接无法在此处查看,但根据标题和描述中提到的信息,我们可以推测出讲座可能涉及的一些核心...

    经典Java笔试算法解析和代码:二分查找.zip

    经典Java笔试算法解析和代码:二分查找.zip 经典Java笔试算法解析和代码:二分查找.zip 经典Java笔试算法解析和代码:二分查找.zip 经典Java笔试算法解析和代码:二分查找.zip 经典Java笔试算法解析和代码:二分查找...

    ]Java常见笔试、面试题目深度剖析

    ]Java常见笔试、面试题目深度剖析

    Java常见笔试、面试系列深度剖析第3讲

    在本节"Java常见笔试、面试系列深度剖析第3讲"中,我们将深入探讨Java编程语言的一些关键概念和常见问题,这些内容对于准备Java相关的笔试和面试至关重要。讲解由张龙和风中叶两位专家主讲,他们将分享丰富的经验与...

    风中叶 Java常见笔试、面试题目深度剖析Java 笔试 面试 题目

    《风中叶 Java常见笔试、面试题目深度剖析》是一份专为Java开发者准备的资源,旨在帮助他们在求职过程中更好地应对各种笔试和面试挑战。这份资料包含了大量的Java编程相关的题目,涵盖了从基础知识到高级概念的各个...

    Java常见笔试面试题目深度剖析

    以上是Java常见笔试面试题目所涵盖的主要知识点,通过深入学习和实践,可以提高Java程序员的专业技能和面试竞争力。在面试中,不仅要能够准确回答问题,还要能结合实际项目经验进行案例分析,展现自己的问题解决能力...

    Java常见笔试、面试题目深度剖析 反射详解

    在Java的笔试和面试中,反射是一个常见的考察点,因此理解并掌握反射机制对于开发者来说至关重要。下面我们将深入探讨Java反射的概念、用途以及如何使用。 1. **反射的概念** Java反射机制是在运行状态中,对于...

    Java常见笔试、面试系列深度剖析第三讲

    - 反射是Java提供的一种强大的元数据访问机制,它允许程序在运行时检查类的结构,包括类名、属性、方法等信息。 - 反射API包含在`java.lang.reflect`包中,主要包括Class类、Constructor类、Method类和Field类。 ...

    香港JAVA面试笔试题目

    3. **异常处理**:Java的异常处理机制是面试中经常被问到的话题,包括try-catch-finally语句块、异常类型、自定义异常以及如何优雅地处理异常。 4. **集合框架**:熟悉ArrayList、LinkedList、HashSet、HashMap等...

    Java常见笔试、面试系列深度剖析第2讲

    在本讲“Java常见笔试、面试系列深度剖析第2讲”中,主讲人张龙与风中叶共同探讨了Java编程语言在实际面试和笔试中的核心知识点,旨在帮助求职者提升对Java技术的理解和应用能力。以下是本讲中涵盖的一些关键知识点...

    java常见笔试面试题

    1. **作用域**:Java中的访问修饰符包括`public`, `private`, `protected`以及默认的(friendly)。`public`成员在所有类中都是可见的,`private`成员只能在定义它们的类中访问,`protected`成员可以在同一包内或...

    Java面试笔试题大汇总(最全+详细答案)

    4. **多线程**:Java提供了Thread类和Runnable接口来支持多线程编程,还包括同步机制(如synchronized关键字、wait()、notify())和并发工具类(如Semaphore、CyclicBarrier、ExecutorService)。 5. **异常处理**...

    java常见面试笔试题目

    14. **动态代理**:Java动态代理利用反射机制在运行时创建代理对象,可以用来实现AOP(面向切面编程)或者为接口提供默认行为。 15. **反射在JUnit框架中的应用**:反射可以用于测试私有方法,了解测试框架如JUnit...

    java基础笔试面试题目 Word版 经典

    Java 基础笔试面试题目通常涵盖了许多核心概念和技术,以下是对这些题目涉及知识点的详细解释: 1. **面向对象基本概念**:面向对象编程(OOP)是一种编程范式,基于类和对象,强调封装、继承和多态。封装是将数据...

Global site tag (gtag.js) - Google Analytics