博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java反射学习总结二(用反射调用对象的私有属性和方法)
阅读量:5108 次
发布时间:2019-06-13

本文共 2754 字,大约阅读时间需要 9 分钟。

大家都知道正常的调用是不可以访问对象的private修饰的属性和方法的,这也是的封装性原则。

但是有没有方法可以强制去访问对象的private修饰的属性和方法呢?那就是用反射!(这个可能在面试题中被问到哦)

接下来就来看看是如何实现的:

我们先去jdk里看一下描述属性的类Field,和方法的类Method:

java.lang.reflect

Class Field

      • java.lang.reflect.Field
java.lang.reflect

Class Method

      • java.lang.reflect.Method

可以看到这两个类有个共通的特点,就是他们都继承自java.lang.reflect.AccessibleObject这个类,我们好好看看这个类的描述

java.lang.reflect

Class AccessibleObject

    • java.lang.reflect.AccessibleObject
  • All Implemented Interfaces:
    Direct Known Subclasses:
    ,  , 

    public class AccessibleObjectextends implements
    The AccessibleObject class is the base class for Field, Method and Constructor objects. It provides the ability to flag a reflected object as suppressing default Java language access control checks when it is used. The access checks--for public, default (package) access, protected, and private members--are performed when Fields, Methods or Constructors are used to set or get fields, to invoke methods, or to create and initialize new instances of classes, respectively.

大致意思就是:

这个AccessibleObject类是Field, Method and Constructor对象的一个父类,他可以让一个反射对象去禁止Java语言的访问控制检测。控制检测有public, default (package) access, protected, and private。。。blah blah blah。。。

这里我贴出控制访问控制检测的这个方法:(这个类里还有一些相关的方法,有兴趣的大家可以自己去看看)

 

setAccessible

public void setAccessible(boolean flag)                   throws
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 
falseindicates that the reflected object should enforce Java language access checks.

大致意思:

设置标志去指示对象的boolean值,如果是true则禁止java访问控制检查,如果是false则强制反射对象使用java访问控制检查

知道了这个方法就可以做一个小例子一下啦。

下面这个例子很简单,就是定义一个dog类,里面有个private的属性dogName,和private的方法say。

main函数里用反射先去修改dogName,然后在调用say方法打印出来:

[java]
  1. public class Test2 {  
  2.   
  3.     public static void main(String[] args) throws Exception {  
  4.         //获得Dog类的Class对象  
  5.         Class<?> classType = Class.forName("Dog");  
  6.         //生成对象的实例  
  7.         Object obj = classType.newInstance();  
  8.           
  9.         //取得dogName属性  
  10.         Field dogName = classType.getDeclaredField("dogName");  
  11.         //禁止Field的访问控制检查  
  12.         dogName.setAccessible(true);  
  13.         //将Field的值设为“Xiao Qiang”  
  14.         dogName.set(obj, "Xiao Qiang");  
  15.           
  16.         //取得say()方法  
  17.         Method say = classType.getDeclaredMethod("say", new Class[]{});  
  18.         //禁止say方法的访问控制检查  
  19.         say.setAccessible(true);  
  20.         //调用say方法  
  21.         say.invoke(obj, new Object[]{});  
  22.     }  
  23.   
  24. }  
  25.   
  26.  class Dog {  
  27.     //私有的属性  
  28.     private String dogName = "Wang Cai";  
  29.     //私有的方法  
  30.     private void say() {  
  31.         System.out.println(dogName + ": Wang Wang");  
  32.     }  
  33. }  

输出结果:Xiao Qiang: Wang Wang

这里需要特别注意一个地方:

如果想用反射修改访问控制检查的话,获取Method和Field对象的时候一定要用getDeclaredField和getDeclaredMethod。不要用getField和getMethod。

虽然这两个方法的参数都是相同的,但不同点在于getMethod和getField只能获得public修饰的属性和方法。而getDeclared可以获取任何类型的属性和方法,因为这个例子要调用私有的属性和方法,所以要用getDeclaredXX。

转载于:https://www.cnblogs.com/Free-Thinker/p/6397401.html

你可能感兴趣的文章
Regular Experssion
查看>>
python中的字符编码
查看>>
图论例题1——NOIP2015信息传递
查看>>
uCOS-II中的任务切换-图解多种任务调度时机与问题
查看>>
CocoaPods的安装和使用那些事(Xcode 7.2,iOS 9.2,Swift)
查看>>
Android 官方新手指导教程
查看>>
幸运转盘v1.0 【附视频】我的Android原创处女作,请支持!
查看>>
UseIIS
查看>>
为什么int型最大的数是2147483647
查看>>
数据库连接的三层架构
查看>>
集合体系
查看>>
vi命令提示:Terminal too wide
查看>>
nyoj 5 Binary String Matching(string)
查看>>
引用 移植Linux到s3c2410上
查看>>
BizTalk 2010 单机安装
查看>>
人与人之间的差距是从大学开始的
查看>>
vue 开发过程中遇到的问题
查看>>
[Swift]LeetCode341. 压平嵌套链表迭代器 | Flatten Nested List Iterator
查看>>
MySQL5.7开多实例指导
查看>>
hdu 1029 Ignatius ans the Princess IV
查看>>