一、字符串的不变性:

    文章使用的源码是jdk1.8的。(下同)

    1.首先可以看到`String`是`final`类,说明该类不可继承,保证不会被子类改变语义

    2.String的值实际上就是一个字符数组对象,字符数组成员变量`value`使用`final`修饰,说明该引用地址不变(不可指向其他对象)但是该数组对象本身是可以改变的,同时`value`使用private 修饰,String中也没有提供可以让外部访问该属性的方法,所有返回类型为String的方法,都只是返回了新的String对象,例如如substring

以上的两点都是为了保证String的不变性,String类注释中有提到:

* Strings are constant; their values cannot be changed after they
* are created. String buffers support mutable strings.
* Because String objects are immutable they can be shared.

  意思是字符串是常量,一旦创建对象,他们的值就无法改变,这里提到String buffers(StringBuffer StringBuilder)支持可变字符串,由于不可变的特性,使得字符串对象可以被共享;

字符串被设计成不可变的原因(好处):

  1.首先就是就是类注释中有提到保证线程安全(不可被修改);是字符串常量池实现的前提,当代码中出现字面量形式(直接使用双引号)创建字符串对象时,JVM首先会对这个字面量进行检查,如果字符串常量池(编译时就确定)中存在相同内容的字符串对象的引用,则将这个引用返回,否则新的字符串对象被创建,这大大节省了内存空间

   2.安全性的考虑;基本上所有的类中有会使用到String,最典型的就是HashMap,其中的key类型最适合String(重写了hashcode和equals),假如一个HashMap中元素的key可以被改变,可想而知必然会出现问题

   3.还有一点就是其HashCode方法,对结果进行了保存,就是第一次计算hash值,以后就不用重新计算了,提高运行效率,这也是HashMap中为什么使用String的原因之一

二、字符串常量池

  首先我们知道创建字符串有两种方法:

    第一种直接使用字面量:String str = "hello";

    第二种就是使用new:String str = new String("hello");

1.class常量池和运行时String常量池:

  当我们使用字面量创建字符串对象的时候如:"hello",java文件被编译成class文件时,"hello"会先检查class常量池是否存在相等的字符串,不存在就放入到class常量池;jvm运行时class文件被加载到内存中,同时class中的字符串常量池会被加载到运行时String常量池,所以当运行String str = "hello"语句时,首先会在运行时String常量池查找是否存在和"hello"相等的字符串对象(使用equals方法比较),存在就返回该对象的地址,不存在就在堆中new一个String对象,并返回该引用;

2.intern方法:

  正常情况下运行时常量池是由class常量池决定的,换句话说在编译阶段就确定了运行时常量池的内容,不过String 提供了一个intern的本地方法,该方法可以在运行期间动态地在运行时常量池中添加String对象,当一个对象调用intern方法,首先会检查String常量池是否存在相等的String对象,存在则返回该对象,不存在则将该对象放入String常量池(jdk1.6 直接复制该对象到String常量池 1.7以后是加入该堆对象的引用) ,并返回该对象的引用。

测试代码:

String str1 = "计算机";
String str2 = "计算机";
System.out.println("str1==str2:" + (str1 == str2)); String str3 = new String("计算机");
System.out.println("str1==str3:" + (str1 == str3));
System.out.println("str1==str3.intern():" + (str1 == str3.intern()));
System.out.println("str2==str3.intern():" + (str2 == str3.intern())); String str4 = new String("计算机");
System.out.println("str3==str4:" + (str3 == str4));
System.out.println("str3.intern()==str4.intern():" + (str3.intern() == str4.intern())); String str5 = new StringBuilder("软件").append("工程").toString();
System.out.println("str5.intern() == str5:" + (str5.intern() == str5)); String str6 = new String(new StringBuilder("物联网").append("工程").toString());
System.out.println("str6.intern() == str6:" + (str6.intern() == str6)); String str7 = new String("物联网");
System.out.println("str7.intern() == str7:" + (str7.intern() == str7)); //JDK1.8输出结果如下: str1==str2:true
str1==str3:false
str1==str3.intern():true
str2==str3.intern():true
str3==str4:false
str3.intern()==str4.intern():true
str5.intern() == str5:true
str6.intern() == str6:true
str7.intern() == str7:false //JDK1.7结果如下 str1==str2:true
str1==str3:false
str1==str3.intern():true
str2==str3.intern():true
str3==str4:false
str3.intern()==str4.intern():true
str5.intern() == str5:true
str6.intern() == str6:true
str7.intern() == str7:false //JDK1.6结果 str1==str2:true
str1==str3:false
str1==str3.intern():true
str2==str3.intern():true
str3==str4:false
str3.intern()==str4.intern():true
str5.intern() == str5:false
str6.intern() == str6:false
str7.intern() == str7:false

看不懂,不理解的可以,欢迎评论哦!!!博主给你详细解答

  

JDK常用类解读--String的更多相关文章

  1. JDK常用类解读--StringBuffer、StringBuilder

    上一篇博客讲到String对象一旦被创建该内容就不能被修改了如: String s = "hello world"; s.substring(6); s.replace(" ...

  2. Java常用类:包装类,String,日期类,Math,File,枚举类

    Java常用类:包装类,String,日期类,Math,File,枚举类

  3. java常用类与包装类--常用类字符串String类、StringBuffer类、Stringbuilder类

    1.String类 1.1String类的概念和储存结构: (1)字符串是一个比较特殊的对象,可以使用new,也可以不使用new来创建字符串对象 String s1 = new String(&quo ...

  4. Java常用类之String类、Stringbuffer和Random类练习

    定义一个StringBuffer类对象, 1)使用append方法向对象中添加26个字母,并倒序遍历输入 2)删除前五个字符 package 第十一章常用类; /** * 定义一个StringBuff ...

  5. [趣学程序]java的常用类之String

    java基础之常用类 String类 String表示字符串,所谓字符串,就是一连串的字符,是java中最常用的类之一. String是不可变类,一旦String对象被创建,包含在对象中的字符序列(内 ...

  6. Java——常用类(String)

    [常用类]   <1>字符串相关类(String.StringBuffer)   <2>基本数据类型包装类   <3>Math类   <4>File类 ...

  7. java 面向对象编程 --第十二章 JDK常用类

    1.  系统类 java.lang包   System类 sys.out;sys.exit;sys.gc; sys.currentTimeMillis();----得到从1970-01-01到当前时间 ...

  8. Java常用类:String

    一.介绍 String:不可变的Unicode字符序列     例如:"Java"   就是4个Unicode字符J,a,v,a组成的 Java没有内置的字符串类型,而是在标准的J ...

  9. java常用类与包装类--常用类正则表达式 String正则方法+Matcher+Pattern

    0.java中的正则 java 中的正则总共涉及三个类(或者说1个String类和一个regex包) java.lang.String java.util. Matcher java.util.Pat ...

随机推荐

  1. 微信通过openID发送消息/后台post、get提交并接收数据 C# .NET 配置404,500等错误信息 连接字符串

    微信通过openID发送消息/后台post.get提交并接收数据   控制器:下面是post发送消息(微信不支持从前台发送数据,之前试过,报错,需要跨域,跨域的问题解决后还不行,最后发现之后后端提交 ...

  2. superCleanMaster

    https://github.com/eltld/superCleanMaster

  3. mysql 中 unix_timestamp和from_unixtime 时间戳函数

    1.unix_timestamp 将时间转化为时间戳.(date 类型数据转换成 timestamp 形式整数) 没传时间参数则取当前时间的时间戳 mysql> select unix_time ...

  4. 嵌入式开发之davinci---IPIPE、IPIPEIF and ISIF这三者有什么区别

    (1)缩写概念 (2)各自区别 (3)不同sensor 采集接口 (4)采集后的数据链路link (5)8127 中的iss和ipipe的区别 (1)缩写概念 http://www.ti.com.cn ...

  5. Java 文件路径的读取

    记得在操作系统中了解到文件读取有两种方式,当然这在各编程语言中也是通用的,所以java路径也分,相对和绝对路径. 绝对路径 绝对路径URI ,听着和URL非常相似.那我们就来看看吧. URI(Unif ...

  6. 【leetcode】Word Break(python)

    思路是这种.我们从第一个字符開始向后依次找,直到找到一个断句的地方,使得当前获得的子串在dict中,若找到最后都没找到.那么就是False了. 在找到第一个后,接下来找下一个断句处,当然是从第一个断句 ...

  7. linux下信息分屏显示

    在字符界面下,经常遇到ls之后信息太长,只能看到最后一页的信息,这时就需要分屏显示了. 常用: ls | less 这样就可以分屏显示了,并可以用PgUp和PgDn来上下翻页. 也可以用: ls | ...

  8. linear map (also called a linear mapping, linear transformation or, in some contexts, linear function

    Linear map - Wikipedia https://en.wikipedia.org/wiki/Linear_map

  9. HDU 5056 Boring count(不超过k个字符的子串个数)

    Boring count Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tot ...

  10. 《31天成为IT服务达人》--做事篇(第四章)之如何找目标

     前面介绍了什么是IT服务.以下几章将介绍IT服务该怎么做.在聊怎么做之前.想起几句流行的告白和准备入行IT服务事业的朋友共勉. 当你的才华 还撑不起你的野心时 就应该静下心来 学习 --- 当你 ...