String不可变性的一些思考_讲了string的底层实现,自己写一个不可变对象的策略_吴大大酱的博客-程序员秘密

技术标签: java基础  java  

1.什么是不可变类型

不可变对象是指一个对象的状态在对象被创建之后就不再变化。这里的不可变化是指不可以修改这个类的内容,这样的设计有很多的好处,不可变的对象可以复用,是共享的,同时还设计到了一个线程安全的问题,不可变类的不变性确保了多个线程在访问同一个对象的时候,是线程安全的。这里有兴趣的可以看一下《Effective Java》这本书,很经典的书,一般别人问我推荐什么java程序员必读的书,这本书是我第二推荐的书,当然,第一本还是《颈椎病康复指南》。

那么对于String对象来说,怎么解释String是不可变的呢,一句话,不能改变一个字符串的值。这句话在很多初学者看来非常的难以理解。我不是经常进行字符串拼接的吗,为什么说没有改变它的值呢?写个demo来看一下。



demo

首先创建了一个字符串“love”,然后进行拼接,显然第一次输出的是love,第二次输出的是loveyou。看上去似乎改变了str的内容,其实这只是表象,我们来进行debug一下。


debug

我们知道String的底层实现是一个数组(下面会讲),字符串为love时,str指向的是@434,进行了字符串凭借之后,指向了@437,并不是一样的,也就是说这里的str其实指向了另一个地址对象而已,也就是每次都生成了新的对象(这里的说法存在一些的问题,结合一下String的堆栈常量池相关的内容进行理解)那么之前指向的love在哪里,答案是在常量池里面。这部分内容以后抽时间写一篇说一下,其实概括一下就是,如果是编译期已经创建好(直接用双引号定义的)的就存储在常量池中进行维护。

2.Stirng如何实现不可变

直接看一下String的源码


jdk8中的String源码

可以看到,String底层是用一个不可变的数组进行存储,final修饰的字段创建以后是不可改变的。这时候思考一下,final修饰的意义,它表示这个数组的引用地址是不可改变的。但同时我们知道,地址虽然不可以改变,但是我们可以改变数组上的值啊---value[]的地址唯一,但是value[i]对应的的值我们是可以改变的。这里就是String不可变的关键,写源码的这些牛逼人物保证了这些数组的值不会对外暴露,private保证了其私有的属性,同时String整个类也是final的,防止继承之后进行修改。

3.为什么要设计成不可变的类型

首先我们应该思考的是,既然有不可变,那么有可变String类使用吗。牛逼的源码工程师肯定考虑到了,StringBuffer和StringBuild这两个类是对本身字符串进行修改操作,至于这两个的区别,这里暂时不做讨论。

关于设计成不可变类的好处有很多的方面,我考虑的主要是常量池维护以及安全。首先String是维护在常量池里面的,所以不同的client都可以共享这里的数据,共享这种行为本身就是非常不安全的,所以我们必须保证这里面的数据不能够被随意的更改,因为更改了其中的一个数据,必然会对其他引用数据的客户端造成不可预估的危害。另一个方面,对于hashmap的影响,我们在使用hashmap的时候,有时候key值的类型是String类型的,我们知道hashmap是严格控制key值不唯一的,这里的string若是可变,同样会引发不可预估的错误,例如对应的value值丢失。(感谢国外code Javin Paul的文章,原文地址http://javarevisited.blogspot.hk/2010/10/why-string-is-immutable-or-final-in-java.html,英文需翻墙)

其实好处是很多方面的,相信造轮子的这些人也是考虑了方方面面,有其他的一些思考可以在底下留言讨论,文章中若有错误的地方,希望指出,我会修改以免造成误导。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_29724155/article/details/79253391

智能推荐

MBG(MyBatis Generator)使用_mbg使用_做一件事就好的博客-程序员秘密

MyBatis的generator用法Maven插件方式1、定义配置文件:generatorConfig.xml<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><!--suppre

谐振功率放大器的工作原理_谐振放大电路原理_鹅毛在路上了的博客-程序员秘密

晶体管的功率放大作用三极管(或场效应管),利用输入到基极(栅极)的信号,来控制集电极(或阳极)的直流电源所供给的直流功率,使之转变为交流信号功率输出去,这是晶体管功率放大器工作的基本原理,不同的连接方式,得到的功率放大效果也不同。低频功率放大器和高频功率放大器的共同特点是输出功率(p0p_0p0​)大,效率(ηηη)高;不同点在于两者的工作频率和相对频宽不同,因此负载网络与工作状态也不同...

openssl密码套件详解_openssl ciphers_富甲一方张三的博客-程序员秘密

说起加密套件(CipherSuite)这个词可能会比较陌生,但是说起ssl/tls可能就是一个众所周知的词汇了,我们知道ssl/tls是经常被用在http协议上以使http协议升级为安全的https协议,ssl协议呢也有自己的握手协商的过程,而这个握手协商的过程呢。就会使用到很多的加密算法,MAC算法,认证算法等等,而加密套件呢就可以理解为是这一些列密码算法的打包形式,其实密码算法的实现有很多,但是目前最主流的实现还是openssl,该文是以openssl来讲解的,有兴趣的可以了解一下其他的实现。先说用法

Spring AOP:静态代理、动态代理和几种常见的aop配置_spring.aop.auto_Coder-Qian的博客-程序员秘密

本文主要对Spring AOP的相关概念和简单的静态代理、动态代理以及常见的几种AOP配置方式做总结学习。真诚希望大家给予批评和指导。 本文以自己写的一个简单Code为例,主要逻辑结构及说明信息依code中的注释内容为说明,所以可能出现 many codes little explianations.AOP的常见概念静态代理jdk动态代理Aspectj and Aspectjweaver

Mybatis学习日记(二)--mybatis-generator_brianyeye的博客-程序员秘密

使用MyBatis-generator自动生成MyBatis映射代码下载mybatis-generator.1.3.1.jar   点击打开链接(包含英文api)还需要ant-1.6.5.jar主要说下如何使用配置文件生成,建立 config.xml<!DOCTYPE generatorConfiguration PUBLIC "-//myba

SpringBoot+mybatis Generator_SSPo的博客-程序员秘密

SpringBoot已经帮我们集成了mybatis,我们只需用mybatis的generator代码生成器来生成bean,dao,以及mapper.xml映射文件运行环境:JDK1.8SpringBoot2.1.4Maven3.5.41.创建好项目文件夹选中web模块选中SQL模块的JDBC,Mybatis,Mysql创建好项目文件夹2.引入myba...

随便推点

unity_NGUI系统学习(十四)_游戏界面滑动切换的效果实现(无代码实现)_unity+卡牌滑动效果_MaximilianLiu的博客-程序员秘密

unity_NGUI系统学习(十四)_游戏界面滑动切换的效果实现(无代码实现)主要是给Panel添加动画效果然后取消激活,使用Button按钮来实现效果平滑效果:(直接上图解释)效果演示:

kettle 技术调研_leaders_forerver的博客-程序员秘密

适用场景1.ETL(抽取,转换,加载)2.BI(商务智能)3.DW(数据仓库)基本理论,核心概念Etl三个最主要步骤:“抽取”:将数据从各种原始的业务系统中读取出来,这是所有工作的前提。csv,table,json,xml“转换”:按照预先设计好的规则将抽取的数据进行转换,使本来异构的数据格式能统一起来。“装载”:将...

andriid:通知的简单记录(11)_weixin_34265814的博客-程序员秘密

2019独角兽企业重金招聘Python工程师标准&gt;&gt;&gt; ...

聊聊让开发头疼的一句话需求那些事_LaoYuanPython的博客-程序员秘密

本文以聊天系统的一句话需求为蓝本,从开发的角度简单分析了需求的功能性和非功能性方面需要澄清的内容。当然限于时间和个人经验,上述分析肯定不全,大家可以留言帮忙补充。在实际工作中,站在产品经理的角度提出的一句话需求或类似简单需求大家一定遇到不少。能说说你遇到的最奇葩需求是什么吗?

【漏洞复现】Vmware vcenter未授权任意文件RCE_Adminxe的博客-程序员秘密

0x00 Vmware vcenter信息vSphere是VMware推出的虚拟化平台套件,包含ESXi、vCenter Server等一系列的软件。其中vCenter Server为ESXi的控制中心,可从单一控制点统一管理数据中心的所有vSphere主机和虚拟机,使得IT管理员能够提高控制能力,简化入场任务,并降低IT环境的管理复杂性与成本。vSphere Client(HTML5)在vCenter Server插件中存在一个远程执行代码漏洞。未授权的攻击者可以通过开放443端口的服务器向...

error: dereferencing pointer to incomplete type 'RSA {aka struct rsa_st}'_rainforest_c的博客-程序员秘密

编译OpenWRT 15.05(Chaos Calmer)的模块 tools/mkimage(u-boot-2014.10) 的时候碰到了下面的错误信息:u-boot-2014.10/lib/rsa/rsa-sign.c:279:21: error: dereferencing pointer to incomplete type 'RSA {aka struct rsa_st}' if ...

推荐文章

热门文章

相关标签