java中字符串“不可变性”的破坏,使用反射破坏final属性。以及涉及到字符串常量池的问题。
大家都清楚java中String类是不可变的,它的定义中包含final关键字。一旦被创建,值就不能被改变(引用是可以改变的)。
但这种“不可变性”不是完全可靠的,可以通过反射机制破坏。参考一下代码:
String str = "abc";
System.out.println(str); Field field = String.class.getDeclaredField("value");
field.setAccessible(true); char[] value = (char[])field.get(str);
value[0] = '1';
value[1] = '2';
value[2] = '3'; System.out.println(str);
这段程序会输出:
abc
123
此处没有给str赋上新的引用值,说明字符串对象确实被改变了。但如果创建新的String对象,用来进行比对的话,会发现一个有趣的现象。先看代码及注释中的运行结果:
String str = "abc";
System.out.println(str); //打印abc Field field = String.class.getDeclaredField("value");
field.setAccessible(true); char[] value = (char[])field.get(str);
value[0] = '1';
value[1] = '2';
value[2] = '3';
System.out.println(str); //打印123 String str1 = "123";
String str2 = "abc"; System.out.println(str1 == str); //打印false
System.out.println(str2 == str); //打印true System.out.println(str1.equals(str)); //打印true
System.out.println(str2.equals(str)); //打印true
System.out.println(str2.equals(str1)); //打印true System.out.println(str); //打印123
System.out.println(str1); //打印123
System.out.println(str2); //打印123
前两个打印仍然是原先的值就不说,后面几个输出信息就很有意思了。仔细想想其出现的原因,应该是因为有字符串常量池的存在。常量池相关的知识网上和各种java基础的书上有很多介绍,这里只简单说下:
jvm在用户创建字符串的时候,会检查字符串常量池中该字符串(字面量,而不是引用)是否存在,若不存在,则将字符串放入常量池中,如果存在则直接返回该字符串的内存地址给String对象。
现在问题就清楚了,str1和str2创建的时候,JVM没有在常量池中找到123这个字面量,找到了abc这个字面量(之前创建过),所以给str1分配了新的内存,而直接将abc的内存地址(虽然现在已经不是存储的abc这个字面量了),即str指向的地址直接返回给了str2。
所以当用==比较的时候,str和str1指向不同的内存地址,返回了false,而str和str2则会返回true。
后面的equals比较,只要清楚一点就能搞清楚原因了:为什么str2的值会是123呢?因为如上所诉,JVM在创建str2的时候,直接将abc这个内存的地址给到了str2,而这个内存块中现在存储的值已经被我们通过反射强行改成了123。
java中字符串“不可变性”的破坏,使用反射破坏final属性。以及涉及到字符串常量池的问题。的更多相关文章
- Java中对不变的 data和object reference 使用 final
Java中对不变的 data和object reference 使用 final 许多语言都提供常量数据的概念,用来表示那些既不会改变也不能改变的数据,java关键词final用来表示常量数据.例如: ...
- Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值
Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值 说到循环遍历,最常见的遍历数组/列表.Map等.但是,在开发过程中,有时需要循环遍历一个对象的所有属性.遍历对象的属性该如何遍历呢?查了 ...
- JAVA中内部类(匿名内部类)访问的局部变量为什么要用final修饰?
本文主要记录:在JAVA中,(局部)内部类访问某个局部变量,为什么这个局部变量一定需要用final 关键字修饰? 首先,什么是局部变量?这里的局部是:在方法里面定义的变量. 因此,内部类能够访问某局部 ...
- java中的成员变量、类变量,成员方法、类方法 属性和方法区别
成员变量:包括实例变量和类变量,用static修饰的是类变量,不用static修饰的是实例变量,所有类的成员变量可以通过this来引用. 类变量:静态域,静态字段,或叫静态变量,它属于该类所有实例共有 ...
- 一、图解Java中String不可变性
这里有一堆例子来说明Java的String的不可变性. 1.声明一个String String s = "abcd"; s 变量保存string对象的引用,下面的箭头解释成保存了哪 ...
- 认识Java中的字符串
Java 中 String 类的常用方法 Ⅰ String 类提供了许多用来处理字符串的方法,例如,获取字符串长度.对字符串进行截取.将字符串转换为大写或小写.字符串分割等,下面我们就来领略它的强大之 ...
- java中字符串的存储
在java中,不同的字符串赋值方法,其所在的地址可能不同也就导致,两个字符串的值看似相等可是在s1==s2操作时,其结果返回的却是false 例: String s1 = "Programm ...
- 详解Java中的字符串
字符串常量池详解 在深入学习字符串类之前, 我们先搞懂JVM是怎样处理新生字符串的. 当你知道字符串的初始化细节后, 再去写String s = "hello"或String s ...
- Java中的字符串操作(比较String,StringBuiler和StringBuffer)
一.前言 刚开始学习Java时,作为只会C语言的小白,就为其中的字符串操作而感到震撼.相比之下,C语言在字节数组中保存一个结尾的\0去表示字符串,想实现字符串拼接,还需要调用strcpy库函数或者自己 ...
- 深入理解Java中的String
一.String类 想要了解一个类,最好的办法就是看这个类的实现源代码,来看一下String类的源码: public final class String implements java.io.Ser ...
随机推荐
- 【转】EDID的简介和解析
转自:https://www.cnblogs.com/beyond-rxl/p/9266997.html 一.EDID简介 EDID: Extended Display Identification ...
- 使用http服务提供yum源
1.安装httpd yum -y install httpd systemctl start httpd systemctl enable httpd 2.镜像资源目录拷贝至http的网站根目录 /v ...
- cron定时任务
1.确认系统安装了cron rpm -aq | grep crontabs 2.认识cron时间格式 3.生成定时任务 crontab -e #进入任务命令编辑模式 30 7,12,20 * * * ...
- 【PHP函数】PHP 去掉字符串中的转义符号
PHP字符串中的转义符号 string stripslashes ( string $str ) //去掉字符串中的反斜线字符.若是连续二个反斜线,则去掉一个,留下一个.若只有一个反斜线,就直接去掉.
- 20165309 《网络对抗技术》 Kali安装
20165309 <网络对抗技术> Kali安装 1. 目的要求 下载 安装 网络 共享 软件源 2. 主要步骤 下载系统镜像文件 进入Kali官网下载,我选择的是64位版本: 虚拟机设置 ...
- javascript高级程序设计第3版——第6章 面向对象的程序设计
第六章——面向对象的程序设计 这一章主要讲述了:面向对象的语言由于没有类/接口情况下工作的几种模式以及面向对象语言的继承: 模式:工厂模式,构造函数模式,原型模式 继承:原型式继承,寄生式继承,以及寄 ...
- IntelliJ IDEA激活
以前一直使用eclipse,直到后来发现了IntelliJ IDEA,就爱上了它. 不过可惜的是,community版本虽然是免费的,不过功能相对较少,而ultimate版本的又需要花钱.但是我穷啊, ...
- maven加载springboot project
maven加载springboot project 1● 下载项目 2● 构建project mvn install mvn package 3● idea加载 4● run启动 ==== ...
- 转载:dos批处理中路径获取
在DOS的批处理中,有时候需要知道当前的路径. 在DOS中,有两个环境变量可以跟当前路径有关,一个是%cd%, 一个是%~dp0. 这两个变量的用法和代表的内容是不同的. 1. %cd% ...
- PHP:第一章——PHP中的变量002
预定义变量.变量的有效范围.可变变量.静态变量.php之外的变量 <?php /*****************************************************/ // ...