大家都知道使用java反射可以在运行时动态改变对象的行为,甚至是private final的成员变量,但并不是所有情况下,都可以修改成员变量。今天就举几个小例子说明。

基本数据类型

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionUsage {private final int age=18;

public int getAge(){

return age;

}

}

测试代码:

import java.lang.reflect.Field;

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionTest {

public static void main(String[] args){

try {

Class reflectionUsage = Class.forName("practise.practise.ReflectionUsage");

ReflectionUsage o = (ReflectionUsage)reflectionUsage.newInstance();

Field age = reflectionUsage.getDeclaredField("age");

age.setAccessible(true);

age.set(o,68);

age.setAccessible(false);

System.out.println(o.getAge());

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

}catch (IllegalAccessException | InstantiationException e){

}

}

}

运行结果:18

此时无法修改成员变量age.

如果将初始化age放到构造函数中会如何呢:

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionUsage {private final int age;

public ReflectionUsage(){

this.age=18;

}

public int getAge(){

return age;

}

}

再执行RefectionTest会发生什么呢?会发现结果变成了68。

为什么会发生这种情形呢?看一下这两个情况下生成的class文件有什么不同:

直接初始化:

public class ReflectionUsage {

private final int age = 18;

public ReflectionUsage() {

}

public int getAge() {

return 18;

}

}

构造函数中初始化:

public class ReflectionUsage {

private final int age = 18;

public ReflectionUsage() {

}

public int getAge() {

return this.age;

}

}

可以看出如果直接初始化时,经过编译后getAge方法直接返回常量值,而在构造函数中初始化时,返回的是this.age变量的值。

String类型

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionUsage {

private final String reflectionString="reflectionString";

public String getReflectionString(){

return reflectionString;

}

}

测试代码:

import java.lang.reflect.Field;

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionTest {

public static void main(String[] args){

try {

Class reflectionUsage = Class.forName("practise.practise.ReflectionUsage");

ReflectionUsage o = (ReflectionUsage)reflectionUsage.newInstance();

Field reflectionString = reflectionUsage.getDeclaredField("reflectionString");

reflectionString.setAccessible(true);

reflectionString.set(o,"newReflectionString");

reflectionString.setAccessible(false);

System.out.println(o.getReflectionString());

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

}catch (IllegalAccessException | InstantiationException e){

}

}

}

运行结果:reflectionString

如果将初始化reflectionString放到构造函数中又如何呢?

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionUsage {

private final String reflectionString;

public ReflectionUsage(){

this.reflectionString="reflectionString";

}

public String getReflectionString(){

return reflectionString;

}

}

运行结果:newReflectionString

为什么运行结果不同呢,来看下class文件:

直接初始化:

public class ReflectionUsage {

private final String reflectionString = "reflectionString";

public ReflectionUsage() {

}

public String getReflectionString() {

return "reflectionString";

}

}

构造函数中初始化:

public class ReflectionUsage {

private final String reflectionString = "reflectionString";

public ReflectionUsage() {

}

public String getReflectionString() {

return this.reflectionString;

}

}

可以看出跟基本类型相似,直接初始化时,编译器会将reflectionString出现的地方,替换成常量值,而构造函数中初始化不替换。

Integer类型

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionUsage {

private final Integer age=18;

public Integer getAge(){

return age;

}

}

测试代码:

import java.lang.reflect.Field;

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionTest {

public static void main(String[] args){

try {

Class reflectionUsage = Class.forName("practise.practise.ReflectionUsage");

ReflectionUsage o = (ReflectionUsage)reflectionUsage.newInstance();

Field reflectionString = reflectionUsage.getDeclaredField("age");

reflectionString.setAccessible(true);

reflectionString.set(o,68);

reflectionString.setAccessible(false);

System.out.println(o.getAge());

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (NoSuchFieldException e) {

e.printStackTrace();

}catch (IllegalAccessException | InstantiationException e){

}

}

}

运行结果:68

可以看出直接初始化private final Integer age变量后,不像基本类型和String类型一样不能修改,原因是什么呢,看下class文件。

public class ReflectionUsage {

private final Integer age = Integer.valueOf(18);

public ReflectionUsage() {

}

public Integer getAge() {

return this.age;

}

}

可以看到编译器并未将getAge中变量替换成常量。

看到对Integer赋值时,编译器进行了自动装箱,那如果初始化String变量时,使用String.value()方式时,能否被修改呢,来看一下。

/**

* @author Cool-Coding 2018/5/15

*/

public class ReflectionUsage {

private final String reflectionString = String.valueOf("reflectionString");

public ReflectionUsage() {

}

public String getReflectionString() {

return this.reflectionString;

}

}

运行结果:newReflectionString

可以看出,reflectionString的值被修改了,看下class文件:

package practise.practise;

public class ReflectionUsage {

private final String reflectionString = String.valueOf("reflectionString");

public ReflectionUsage() {

}

public String getReflectionString() {

return this.reflectionString;

}

}

可见编译器并未替换getReflectionString方法中的变量。

如果在构造函数中初始化Integer类型变量呢?

public class ReflectionUsage {

private final Integer age;

public ReflectionUsage() {

this.age=18;

}

public Integer getAge() {

return this.age;

}

}

运行结果:68

age值也被改变了,看下class文件:

public class ReflectionUsage {

private final Integer age = Integer.valueOf(18);

public ReflectionUsage() {

}

public Integer getAge() {

return this.age;

}

}

生成的class文件与直接初始化是一样的。

总结:

final可以修改类,变量,方法,表示不可继承,不可修改,不可覆盖(override),这里讨论了使用反射修改private final修饰的成员变量情况,当private final修改直接初始化的基本类型或String(注意不能使用String.valueOf()初始化)时,使用反射无法修改变量值,其它情况下可以修改。这也告诉我们在平时开发时,如果想定义常量请在基本类型int或String类型前加private final修饰,这样编译器会在编译时将这些变量出现的地方替换成常量,以免被恶意修改。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

java反射成员变量的值_Java反射如何修改private final成员变量值相关推荐

  1. python输出变量的值使用_Python捕获任何异常,并使用变量值打印或记录回溯

    当我用sys.excepthook捕获意外错误时 import sys import traceback def handleException(excType,excValue,trace): pr ...

  2. java 反射 成员变量_java使用反射访问成员变量的值示例

    本文实例讲述了java使用反射访问成员变量的值.分享给大家供大家参考,具体如下: 一 代码 import java.lang.reflect.*; class Person { private Str ...

  3. java 反射私有变量赋值_通过反射,操作私有成员变量(取/赋值),调用私有方法...

    Java的反射工具很强大,有句著名的话:No reflection ,no frameworks. 工作中直到涉及到UT,才体会到它的重要性,现归纳整理一个小例子: 反射工具类:import java ...

  4. 反射练习- 改变private成员变量的值

    package com.zj.reflect;import java.lang.reflect.Field;/*** 使用反射改变private成员变量的值* @author zhengjiong* ...

  5. Java逆向基础之AspectJ的获取成员变量的值

    注意:由于JVM优化的原因,方法里面的局部变量是不能通过AspectJ拦截并获取其中的值的,但是成员变量可以 在逆向中,我们经常要跟踪某些类的成员变量的值,这里以获取ZKM9中的qs类的成员变量g为例 ...

  6. C++如何在const函数修改成员变量的值

    C++如何在const函数修改成员变量的值 在C++,总所周知,c++不允许在const函数直接修改成员变量的值,想要达到此目的,有两种方式: 使用mutable关键字 造一个假的this去操作成员变 ...

  7. C++57个入门知识点_17 类的访问权限及C语言模拟类的封装(类的私有权限突破方法:编译期进行权限检查,运行期通过指针修改类的私有成员变量;利用函数指针对结构体中成员变量进行修改;CPU大小尾排列)

    接上篇:C++57个入门知识点_16 类的标准写法(类名.成员变量.成员函数及对象命名规则:成员变量一般为私有,成员函数为公有并暴露给外部使用成员变量:防止类过大,声明写在.h,实现写在.cpp,调用 ...

  8. 类的成员变量 猜数字游戏一个类A有一个成员变量v有一个初值100。 * 定义一个类对A类的成员变量v进行猜。 * 如果大了则提示大了小了则提示小了。等于则提示猜测成功。

    /** 类的成员变量 猜数字游戏一个类A有一个成员变量v有一个初值100.* 定义一个类对A类的成员变量v进行猜.* 如果大了则提示大了小了则提示小了.等于则提示猜测成功.*/ import java ...

  9. java反射设置属性值_Java反射如何有效的修改final属性值详解

    前言 以前写过一篇 Java 反射修改 final 属性值,本文将在这里重新温习一下Java反射如何有效的修改final属性值,下面话不多说了,来一起看看详细的介绍: 假设有个类 class Pers ...

最新文章

  1. win8无线网服务器,Win8连接wifi受限
  2. Github拉取远端的时候提示“ssh: connect to host github.com port 22: Connection timed out”错误...
  3. 纯JSP实现简单登录跳转
  4. ZOJ 3597 Hit the Target! (线段树扫描线 -- 矩形所能覆盖的最多的点数)
  5. ZOJ3261并查集逆向处理
  6. redis php 守护进程,PHP守护进程利用Redis队列实现业务
  7. 添加chorme插件时出现“程序包无效”
  8. 阿里云喻义:十年牧码,从码农走向工程师的进化之路
  9. android 9图片报错,Android2.1加载9Patch图片运行后报错
  10. java 像素级碰撞检测,» 像素级碰撞检测类
  11. ACM——2的n次方
  12. 音视频之——FFmpeg教程(二)——Windows10下搭建nginx-rtmp流媒体服务器
  13. 一说起丁克,我们普遍的认知就是,不生孩子
  14. 【OGG】OGG简单配置双向复制(三)
  15. 针对Android智能电视研发的,论Android智能电视盒子必装应用之一ES
  16. ABB伺服驱动调试(二)
  17. IT 如何把骨干留住
  18. 湖北民院OJ 计算球体体积
  19. vue 微信公众号 二维码 ios系统长按没有反应,识别不了二维码
  20. 转:AIX菜鸟成长日志

热门文章

  1. 华为软件开发云试用手记(一) 建立项目
  2. Android侧滑返回手机工具,Vivo侧滑返回手势工具app-Vivo手机侧滑手势工具下载v9.2.0.0 安卓版-西西软件下载...
  3. 叛乱沙漠风暴服务器配置教程 叛乱沙漠风暴怎么开服
  4. uniapp蓝牙模块demo
  5. ch06-物理系统与碰撞——Arrowshooting射箭小游戏
  6. R语言突变点检测Mann-Kendall(MK)、滑动平均差等方法
  7. 电脑公司Windows7 Ghost 2010新年版
  8. 弹载计算机标准,弹载计算机
  9. 【Wifi】adb命令打开/关闭蓝牙、NFC(bluetooth)开关
  10. H3C防火墙授权相关问题