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

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

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

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

java.lang.reflect

Class Field

java.lang.reflect

Class Method


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

java.lang.reflect

Class AccessibleObject

  • All Implemented Interfaces:
    AnnotatedElement
    Direct Known Subclasses:
    ConstructorFieldMethod

    public class AccessibleObject
    extends Object
    implements AnnotatedElement
    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 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 falseindicates that the reflected object should enforce Java language access checks.

大致意思:

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

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

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

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

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

输出结果:Xiao Qiang: Wang Wang

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

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

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

Java反射学习总结二(用反射调用对象的私有属性和方法)的更多相关文章

  1. Java反射机制(三):调用对象的私有属性和方法

    一. 通过反射调用类中的方法 在正常情况下,得到类的对象后,我们就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚地知道要调用的方法是什么,之后通过Class类中的getMethod方法,可 ...

  2. 【Java语言特性学习之二】反射

    一.概念java加载class文件分两种情况:(1)类型是编译器已知的,这种文件的.class文件在编译的时候,编译器会把.class文件打开(不加载)检查,称为Run- Time Type Iden ...

  3. Java多线程学习(二)synchronized关键字(2)

    转载请备注地址:https://blog.csdn.net/qq_34337272/article/details/79670775 系列文章传送门: Java多线程学习(一)Java多线程入门 Ja ...

  4. Java多线程学习(二)synchronized关键字(1)

    转载请备注地址: https://blog.csdn.net/qq_34337272/article/details/79655194 Java多线程学习(二)将分为两篇文章介绍synchronize ...

  5. Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer

    作者:Grey 原文地址:Java IO学习笔记二:DirectByteBuffer与HeapByteBuffer ByteBuffer.allocate()与ByteBuffer.allocateD ...

  6. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  7. 2019/3/4 java集合学习(二)

    java集合学习(二) 在学完ArrayList 和 LinkedList之后,基本已经掌握了最基本的java常用数据结构,但是为了提高程序的效率,还有很多种特点各异的数据结构等着我们去运用,类如可以 ...

  8. python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码

    python3.4学习笔记(二十三) Python调用淘宝IP库获取IP归属地返回省市运营商实例代码 淘宝IP地址库 http://ip.taobao.com/目前提供的服务包括:1. 根据用户提供的 ...

  9. Java基础学习笔记(二) - 面向对象基础

    面向对象 一.面向对象概述 面向对象思想就是在计算机程序设计过程中,参照现实事物,将事物的属性特征.行为特征抽象出来,描述成计算机时间的设计思想.面向对象思想区别于面向过程思想,强调的是通过调用对象的 ...

随机推荐

  1. Elasticsearch之marvel(集群管理、监控)插件安装之后的浏览详解

    前提 Elasticsearch之插件介绍及安装 https://i.cnblogs.com/posts?categoryid=950999&page=2  (强烈建议,从头开始看) 比如,我 ...

  2. Kinect 开发 —— WaveHand

    基本注释都写了,就不废话了 <Window x:Class="KinectBasicHandTrackingFrameworkTest.MainWindow" xmlns=& ...

  3. 原生JS实现页面内定位

    需求:点击跳转到页面指定位置 <div id="test">点击跳转到此处</div> [法一]: 利用a标签的锚点跳转 <a href=" ...

  4. logout命令用于退出当前登录的Shell

    logout命令用于退出当前登录的Shell

  5. Python day2 知识回顾

    标准库一般放在lib,site-packages放自己下载的:起的py文件名称不要和模块名字相同:import sys#print(sys.path)#打印去哪里寻找这些模块的路径#print(sys ...

  6. 初识Django框架——环境搭建前你需要了解的几点

    Django是一个开放源代码的Web应用框架,由Python写成. 采用了MVC的框架模式,即模型M,视图V和控制器C. 它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,即是C ...

  7. Eclipse怎样把文件系统形式的项目作为工程直接导入?

    导入的时候,选择已经存在的工程,如果选择文件系统,可能会提示没有项目可以导入.这个时候,可以从其它Eclipse项目下,copy一份.project文件过来,修改源文件中的工程名字.如果需要,也可以c ...

  8. 【hihocoder 1378】网络流二·最大流最小割定理

    [Link]:http://hihocoder.com/problemset/problem/1378 [Description] [Solution] 在求完最小割(最大流)之后; 可以在剩余网络中 ...

  9. Spring 实现数据库读写分离(转)

    现在大型的电子商务系统,在数据库层面大都采用读写分离技术,就是一个Master数据库,多个Slave数据库.Master库负责数据更新和实时数据查询,Slave库当然负责非实时数据查询.因为在实际的应 ...

  10. P1145 约瑟夫

    P1145 约瑟夫 题目描述 n个人站成一圈,从某个人开始数数,每次数到m的人就被杀掉,然后下一个人重新开始数,直到最后只剩一个人.现在有一圈人,k个好人站在一起,k个坏人站在一起.从第一个好人开始数 ...