• 今天刷技术文章,遇到了一个问题,用 Java 反射机制去修改 String 变量的值,出于深入研究,就发现了一个问题,即,用初始值比较修改后的值,用 == or .equals() 方法,出现了相等的情况

文字描述看起来比较难受,我们直接看代码


//创建字符串"Hello World", 并赋给引用 s
String s = "Hello World";
System.out.println("s = " + s); //Hello World
//获取String类中的value字段
Field valueFieldOfString = String.class.getDeclaredField("value");
//改变value属性的访问权限
valueFieldOfString.setAccessible(true);
//获取s对象上的value属性的值
byte[] value = (byte[]) valueFieldOfString.get(s);
//改变value所引用的数组中的第5个字符
value[5] = '_';
System.out.println("s = " + s); //Hello_World
System.out.println("Hello World".toString());
System.out.println(s == "Hello World"); // true
System.out.println(s.equals("Hello World")); // true

如上方代码所示,我们定义了一个 String 变量 s ,并且赋值给它 "Hello World",然后通过 Java 的反射机制去修改第五个字符的值,在输出结果的时候,理所当然的结果是 "Hello_World",但是我在这个情况之上多了一手,把被修改后的值与初始值比较看看,会发生什么情况,结果一试就出现了问题,竟然与初始值相等且返回了 true .

于是,打算好好深究一下,我们知道 String 的变量是存放在 JVM 的常量池中的,同时指向 "Hello World" 的引用 s1 是 String 对象,存放在堆区,我们通过反射区修改的值并不是常量池中的 "Hello World" ,而是 堆区中的对象 s1 的值,所以我们输出 s1 的时候就是 "Hello_World" ,那么为什么初始值比较修改后的值的时候会出现 true 呢?

我们看看 System.out.println("Hello World".toString()); 这行代码,输出结果是 Hello_World,这是因为 "Hello World".toString() 的时候,会去常量池中去找 "Hello World"的引用,它的引用就是 s1 ,所以输出的是 s1 的值,即 "Hello_World",所以,到这里,我们就知道了,为什么 s == "Hello World" 和 s.equals("Hello World") 返回 true 了 .

[reference]

String类型的值能够被反射改变和常量池的理解

String字符串被创建的原理过程

Java内存图以及堆、栈、常量区、静态区、方法区的区别

Java中 类的加载概述和加载时机

String 类型的值能够被反射改变从而引发的意外事件的更多相关文章

  1. C#中string类型是值类型还是引用类型?

    .Net框架程序设计(修订版)中有这样一段描述:String类型直接继承自Object,这使得它成为一个引用类型,也就是说线程上的堆栈上不会驻留有任何字符串. string类型(引用类型) 名称 CT ...

  2. C#中string类型是值类型还是引用类型?(转)

    出处:https://www.cnblogs.com/dxxzst/p/8488567.html .Net框架程序设计(修订版)中有这样一段描述:String类型直接继承自Object,这使得它成为一 ...

  3. SpringMVC中使用@Value给非String类型注入值

    String类型的@Value注入方式 String类型的直接可以使用 @Value("陈婉清") private String name; 非String类型的@Value注入方 ...

  4. 为什么说Java String 类型的值是不可改变的?

    String对象是不可变的,它的内容是不能改变的.下列代码会改变字符串的内容吗? 1 2 String s = "Java"; s = "HTML"; 答案是不 ...

  5. Java - 尚学堂第八章常用类(将输入的string类型的值转为整数、浮点型、日期类型)

    import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; imp ...

  6. String 类型

    一.不可变 一个 String 类型的值是不可以改变的,比如,String china = "中国",“中国”这个字符串从它创建开始直到销毁都是不可改变的. 二.字符串常量池 字面 ...

  7. C#中特殊的string类型

                                                                                  string C#有string关键字,在翻 ...

  8. java对象转化成String类型

    在java项目的实际开发和应用中,常常需要用到将对象转为String这一基本功能.本文将对常用的转换方法进行一个总结.常用的方法有Object#toString(),(String)要转换的对象,St ...

  9. redis的数据类型(二)string类型

      下面讲解value,value包括String.List.Set.Sorted Set.Hash 一.String类型 1.string类型  String是最基本的类型,而且Stirng类型是二 ...

随机推荐

  1. java第七周动手动脑

    public class ParentChildTest { public static void main(String[] args) { Parent parent=new Parent(); ...

  2. list-列表练习

    #list列表取值更方便灵活 列表.数组说的都是1个东西#列表中每个字符都有一个编号,就是我们说的下标,从0开始#如果你输入的下标在列表中不存在,会报下标越界的错误 1.查询user表中下标为0的记录 ...

  3. Selenium Java环境配置

    Selenium Java环境配置 上次配置的是C#的环境,今天主要来配置一下Java环境. 首先,对于java环境配置最基础的JDK和JRE 先前我做过配置,这里就不重述了,网上的教程超级多.在基础 ...

  4. vue路由打开新窗口

    一. <router-link>标签实现新窗口打开: 官方文档中说 v-link 指令被 <router-link> 组件指令替代,且 <router-link> ...

  5. yuv rgb 互转 公式 及算法

    1 前言 自然界的颜色千变万化,为了给颜色一个量化的衡量标准,就需要建立色彩空间模型来描述各种各样的颜色,由于人对色彩的感知是一个复杂的生理和心理联合作用的过程,所以在不同的应用领域中为了更好更准确的 ...

  6. MAC 开启与关闭SIP

    1. 查看SIP状态 在终端中输入csrutil status,就可以看到是enabled还是disabled. 2. 关闭SIP S1  重启MAC,按住cmd+R直到屏幕上出现苹果的标志和进度条, ...

  7. solr集群构建的基本流程介绍

    先从第一台solr服务器说起:1. 它首先启动一个嵌入式的Zookeeper服务器,作为集群状态信息的管理者,2. 将自己这个节点注册到/node_states/目录下3. 同时将自己注册到/live ...

  8. 获得最近一天的提交,并使用winscp上传到服务器

    @echo off D:\dev\Git\bin\git.exe pull origin master D:\dev\Git\bin\git.exe add -A D:\dev\Git\bin\git ...

  9. TensorFlow迭代速度变慢的问题

    最近用TensorFlow实现遗传算法(Genetic Algorithms),发现迭代速度越来越慢,用time.time()观察以后,发现每次迭代都要比上一次慢0.5秒左右,但是每次迭代的计算量是差 ...

  10. [转]awsome-python

    原文链接 Python 资源大全中文版 我想很多程序员应该记得 GitHub 上有一个 Awesome - XXX 系列的资源整理.awesome-python 是 vinta 发起维护的 Pytho ...