今天分析一下String,String有很多实用的特性,比如说“不可变性”,是工程师精心设计的艺术品。用final就是拒绝继承,防止内部属性或方法被破坏。

一,什么是不可变?

String不可变很简单,如图,给一个已有字符串“abcd”,第二次赋值为“abcde”,不是在原内存地址上修改数据,而是重新指向一个新对象,新地址。

二,String为什么不可变?

翻看IDK源码,String类前几行是这样写的:

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[]; /** Cache the hash code for the string */
private int hash; // Default to 0

首先String是被final修饰,这说明String不可被继承。下面String的主要字段value是个char[]数组,并且被final修饰。final修饰的字段创建后就不可改变。但是value是引用类型,用final修饰,只能说明value的引用地址不可变,但是挡不住char[]数组本身可变的事实。注意黑体的这段话,正如分析final关键字时所说,对于基本类型,final使数值恒定不变;而用于对象引用,final使引用恒定不变。一旦引用被初始化指向一个对象,就无法再把它改为指向另一个对象。然而,对象其自身却是可以被修改的。

final int[] value={2,3,4};
value[2]=100; //这时候数组里已经是{2,3,100}

所以String不可变,关键是因为SUN公司的工程师,在后面所有String的方法里很小心的没有去动Array里的元素,没有暴露内部成员字段。private final char value[]这一句里,private的私有访问权限的作用比final都大。而且工程师还很小心地把整个String类设成final禁止继承,避免被其他人继承后破坏。所以String不可变的关键在底层的实现,而不是一个final。

三,不可变的好处

  1,字符串常量池的需要。

  字符串常量池在方法区是一块特殊的存储区域。当字符串已经在常量池中,此时创造字符串时,直接返回已存在字符串的引用,而不是重新创造一个String对象。

String string1 = "abcd";
String string2 = "abcd";

  2,快速获取哈希码。

  String的哈希码在java中经常被使用。例如,在HashMap或者HashSet中。不可变确保了哈希码总是相同的。那就意味着每次在使用时不需要重新计算哈希码,这样更高效。

private int hash;

  3,不可变对象是线程安全的。

  因为不可变对象并不能被改变,因此它们能放心地在多线程中使用,这就使得不必另外做同步。

四,比较(String),toString()和String.valueOf()的区别

  1,(String),这是标准的类型转换,将其他类型转成String类型。使用这种方法时,需要注意的是类型必须能转成String类型,因此最好用instanceof做个类型检查,以判断是否可以转换。否则容易抛出CalssCastException异常。

  2,toString(),在这种使用方法中,因为java.lang.Object类里已有public方法.toString(),所以对任何严格意义上的java对象都可以调用此方法。但在使用时要注意,必须保证object不是null值,否则将抛出NullPointerException异常,也可以在子类中重写toString()方法。

  3,String.valueOf(),此方法不会报空指针异常,弥补了toString()的不足。但是需要注意,null返回的是字符串“null”。

    public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}

参考:https://www.zhihu.com/question/31345592

String不可变性的更多相关文章

  1. java基础解析系列(九)---String不可变性分析

    java基础解析系列(九)---String不可变性分析 目录 java基础解析系列(一)---String.StringBuffer.StringBuilder java基础解析系列(二)---In ...

  2. 记一次愚蠢的经历--String不可变性

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 记录一次在写代码时愚蠢的操作,本文涉及到的知识点:S ...

  3. 浅析String不可变性

    在所有编程语言领域,我想字符串应该是地球上最常用的表达手段了吧. 在java的世界里,String是作为类出现的,核心的一个域就是一个char数组,内部就是通过维护一个不可变的char数组,来向外部输 ...

  4. 一、图解Java中String不可变性

    这里有一堆例子来说明Java的String的不可变性. 1.声明一个String String s = "abcd"; s 变量保存string对象的引用,下面的箭头解释成保存了哪 ...

  5. Java基础:String不可变性和final修饰

    转载请注明出处: jiq•钦's technical Blog - 季义钦 String的不可变性 Java规定String是不可变的(immutable).事实上这个不可变具备两层含义: 1 内容不 ...

  6. Java中String类型的不可变性和驻留池

    一 基本概念 可变类和不可变类(Mutable and Immutable Objects)的初步定义: 可变类:当获得这个类的一个实例引用时,可以改变这个实例的内容. 不可变类:不可变类的实例一但创 ...

  7. 【JDK源码分析】String的存储区与不可变性(转)

    // ... literals are interned by the compiler // and thus refer to the same object String s1 = " ...

  8. 图解String类型的不可变性及其原因

    1.String的不可变性 String s="abcd": 上面的语句定义了一个字符串变量s.该变量指向字符串"abcd",当初始化变量s时,会在堆中为s非配 ...

  9. String、StringBuilder和StringBuffer

    1.string不可变性 java的docs有这样一句话:Strings are constant; their values cannot be changed after they are cre ...

随机推荐

  1. 【python】random

    1.random 和其他语言一样,返回大于等于0.小于1的浮点数 2.uniform(a,b) 返回大于等于a.小于等于b的浮点数 3.randint(a,b) 这个很好理解,返回一个介于a和b之间的 ...

  2. Assembly之Instruction之Byte and Word

    Byte and word issues The MSP430 is byte-addressed, and little-endian. Word operands must be located ...

  3. C++ Rand()各种实现

    参考链接:http://www.cplusplus.com/reference/cstdlib/rand/ 使用实例: v1 = rand() % 100; // v1 in the range 0 ...

  4. [Advanced Algorithm] - Inventory Update

    题目 依照一个存着新进货物的二维数组,更新存着现有库存(在 arr1 中)的二维数组. 如果货物已存在则更新数量 . 如果没有对应货物则把其加入到数组中,更新最新的数量. 返回当前的库存数组,且按货物 ...

  5. 【sqli-labs】 less27a GET- Blind based -All you Union&Select Belong to us -Double Quotes(GET型基于盲注的去除了Union和Select的双引号注入)

    和less 27一样,单引号换双引号 http://192.168.136.128/sqli-labs-master/Less-27a/?id=0"%a0uNion%a0sElect%a01 ...

  6. webpack学习(二)

    时下很火的react项目多用到webpack+ES6,本文只实践webpack的打包功能,不涉及react. 1.新建项目 新建的项目,命令模式下切换到项目根路径,用npm init命令生成packa ...

  7. 通过JDBC取Oracle数据库的时间字段时,时间丢失,只剩日期

    通过JDBC连接Oracle数据库,在查询的时候发现时间字段取出来值后只剩下了日期,时间消失了.查资料发现跟Oracle jdbc驱动版本有关,这里先贴出解决方案: 修改数据库的连接方式: try { ...

  8. PL\SQL(day05)

    PLSQL 1.常用的访问数据库的相关技术 1) plsql 过程化的sql 2) proc/c++ 在c/c++语言中访问oracle数据库的技术 3) ado/odbc vc中访问数据库的技术 4 ...

  9. webpack 配置 Vue 多页应用 —— 从入门到放弃

    webpack 配置 Vue 多页应用 -- 从入门到放弃 一直以来,前端享有无需配置,一个浏览器足矣的优势,直到一大堆构建工具的出现,其中 webpack 就是其中最复杂的一个,因此出现了一个新兴职 ...

  10. python爬虫09 | 上来,自己动 !这就是 selenium 的牛逼之处

    作为一个男人 在最高光的时刻 就是说出那句 之后 还不会被人打 ... 虽然在现实生活中你无法这样 但是在这里 就让你体验一番 那种呼风唤雨的感觉 我们之前在爬取某些网站的时候 使用到了一些 pyth ...