关于String相关内容的学习,历来都是Java学习必不可少的一个经历。

以前一直想要好好总结一下String的相关的知识点,苦于没有时间,终于在今天有一个闲暇的时间来好好总结一下,也希望这文章能够加深我对于String相关内容的理解(ps:在我看来,学习某些知识点的时候把学到的想到的都记录下一方面能够加深自己学习印象,二者能够锻炼锻炼我的文笔

首先JVM中存在着一个字符串池String pool,其中保存着很多String对象,这些String对象可以被共享使用,因此这个pool的存在在很多方面提高Java一些String操作的效率。 而这一些都是基于String类是final的,它的值一经创建就不可改变。String pool由String类维护,所以我们可以调用intern()方法来访问字符串池。

接下里我们来看第一个例子:

String s1 = "abc";
String s2 = "abc";
System.out.println("s1 == s2 : "+(s1==s2)); //true
System.out.println("s1.equals(s2) : " + (s1.equals(s2))); //true

在这个例子中,虚拟机进行了哪些操作呢?首先,因为在此s1我是直接使用了”abc”,那么系统会在String pool中创建了一个String对象,他的值就是”abc”,s2进行创建的时候,系统先搜索String pool中是否已经存在了”abc”,由于String pool中已经存在了一个”abc”的String对象,很好,系统直接将s2指向了String pool中的那个”abc”地址。所以下面两个输出都是true。

上面都是使用””来创建String对象的,第二个例子我们使用new来创建:

String s3 = new String("abc");
String s4 = new String("abc");
System.out.println("s3 == s4 : "+(s3==s4)); //false
System.out.println("s3.equals(s4) : "+(s3.equals(s4))); //true
System.out.println("s1 == s3 : "+(s1==s3)); //false
System.out.println("s1.equals(s3) : "+(s1.equals(s3))); //true

在这里,应当要提一点。对于new String来说,该构造函数的对象接收一个String字符串对象。其实这里进行了两件事情:

步骤一:系统首先会创建一个String对象”abc”,通过String temp = “abc”来创建的(temp只是我自己取得名字,至于到底叫什么,我们是不用关心的),这个创建过程和第一个例子是一样的道理,他会在String pool去寻找'”abc”,然后根据有没有来判断是额外的创建还是直接用String pool中的那个”abc”。

步骤二:new String接受了刚刚的temp参数以后,在堆上去创建一个对象,把刚刚的temp的值”abc”赋给这个在堆中的String对象的值。

步骤三:把s3指向刚刚在堆中的这个String对象。

通过以上的几步我们可以知道,使用new String完全没有直接使用=””来的快。

s4的创建是同样的道理,所以s3、s4最终都各自指向了内容相同,地址不同的,在堆中的String对象。所以又由于==在对于对象的比较的时候是直接比较的引用的地址。所以第一、三个输出是false。但是equals对于String比较的是内容的是否相等,所以第二、四个输出true。

接下来是第三种例子,String中 + 的重载:

由于我们知道,常量的值在编译的时候就已经进行了优化了。所以这一行代码:

String str1 = "ab" + "cd";

在编译的时候就等价于优化过的

String str1 = "abcd";

所以执行下面这几行代码的时候,根据常量编译优化,加上我对于第一个例子的讲解,我们可以知道输出是true:

String str1 = "ab" + "cd";  //1个对象
String str2 = "abcd";
System.out.println("str1 = str2 : "+ (str1 == str2)); //输出为true

接下来就是第四种情形了,这种情况依然是String + 的重载,但是比起第三种是有本质的不同的。首先看代码:

String str2 = "ab";
String str3 = "cd";
String str4 = str2 + str3;
String str5 = "abcd";
System.out.println("str4 = str5 : " + (str4 == str5));

解读这一段代码,str2、str3就是情况一,我们不再讨论。此刻str4比起第三种的 + 两端都是String常量而言,这里是对于编译器来说是两个变量。这一个部分,系统会干什么呢?首先,系统会new 一个StringBuilder对象,然后调用该对象的append函数,把str2、str3按顺序连接起来。连接好以后,调用StringBuilder的toString方法,该方法内部new 一个String对象,并把它return。得到str2 + str3的结果,接着str4指向堆中的这个String对象。

注意:对于StringBuilder的创建还有其他的情况。比如假设此处的String str4 = “ab” + “c” + str2 那么,编译器首先会进行一个优化,也就是第三种情况所说的他会优化为String str4 = “abc” + str2 然后,new StringBuilder(“abc”),然后append(str2)。也就是说,从=号右边开始前部分,他首先会在编译过程判断能否进行优化,可以优化,由优化为最大的常量子串,然后new一个以该最大子串的为初始值的StringBuilder对象,然后再append。

所以,在以上的这四条String创建语句中,创建了str2、str3、str5三个在String pool中的字符串常量,以及在系统内部进行append的StringBuilder,以及toString函数return的在堆中创建的String对象,一共五个对象。

那么最终输出结果当然是false,前者是指向堆中的String对象的地址,而后者是S指向tring pool中String对象的地址。

但是,还有一种变量情况是不一样的:

final String str1 = "b";
String str2 = "a" + str1;
String str3 = "ab";
System.out.println("str2 = str3 : "+ (str2 == str3)); //true

这里按照情况四中注意部分来说,输出本来应该是false,但是为什么是true呢?注意看str1前面的修饰符,这里使用了final修饰符,final修饰的变量表示是一个常量,在创建额时候就需要初始化,并且不可修改。在final关键字的修饰下,编译器会在编译过程中就进行优化,其实这里的道理就和例子三是一样的了。这也是为什么这里输出的是true。

Java String的探讨的更多相关文章

  1. 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念

    转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...

  2. Java String.split()小点

    java String.split(); 别的不说,单说其中一个问题,这个函数去切分空字符串时,得到的结果: public static void main(String[] args) {// St ...

  3. Java总结篇系列:Java String

    String作为Java中最常用的引用类型,相对来说基本上都比较熟悉,无论在平时的编码过程中还是在笔试面试中,String都很受到青睐,然而,在使用String过程中,又有较多需要注意的细节之处. 1 ...

  4. java String.split()函数的用法分析

    java String.split()函数的用法分析 栏目:Java基础 作者:admin 日期:2015-04-06 评论:0 点击: 3,195 次 在java.lang包中有String.spl ...

  5. java string类型的初始化

    以下基本上是java string类型最常用的三种方法 new string()就不介绍了  基本等同于第三种 String a;  申明一个string类型的 a,即没有在申请内存地址,更没有在内存 ...

  6. Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0

    课程概要 String 字符串 String字符串常用方法 StringBuffer StringBuilder String字符串: 1.实例化String对象 直接赋值  String str=& ...

  7. Java String类详解

    Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...

  8. java string,需要进行首字母大写改写

    java string,需要进行首字母大写改写,网上大家的思路基本一致,就是将首字母截取,转化成大写然后再串上后面的,类似如下代码 //首字母大写     public static String c ...

  9. Java String Class Example--reference

    reference:http://examples.javacodegeeks.com/core-java/lang/string/java-string-class-example/ 1. Intr ...

随机推荐

  1. springmvc框架(Spring SpringMVC, Hibernate整合)

    直接干货 model 考虑给用户展示什么.关注支撑业务的信息构成.构建成模型. control 调用业务逻辑产生合适的数据以及传递数据给视图用于呈献: view怎样对数据进行布局,以一种优美的方式展示 ...

  2. TCP请求连接与断开

    TCP连接的三次握手:

  3. 未解决的html页面banner对不齐

    莫名其妙的问题,记录等待解决: 怎么讲呢?就是可能真的没有理解这句话,浏览器是否是需要这句话的,思考! <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML ...

  4. Spring Boot +Vue 项目实战笔记(二):前后端结合测试(登录页面开发)

    前言:关于开发环境 每位 Coder 都有自己偏好的开发工具,从大的方面划分主要有文本编辑器流和 IDE 流两种,我有一段时间也喜欢用编辑器(Sublime Text.Vim),但对我来说开发效率确实 ...

  5. 【曹工杂谈】Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗

    Maven和Tomcat能有啥联系呢,都穿打补丁的衣服吗 前奏 我们上篇文章,跟大家说了下,怎么调试maven插件的代码,注意,是插件的代码.插件,是要让主框架来执行的,主框架是谁呢,就是maven ...

  6. C#新版本风格(NetCore)项目文件

    在VisualStudio中创建NetCore以上版本的项目,使用的都是新版本风格的项目文件. 和旧版本.NetFramework版本的项目文件区别: 双击项目可直接打开csproj文件进行编辑配置 ...

  7. RT-Thread 4.0 + STM32F407 学习笔记1

    RT Thread 4.0提供了新的BSP框架 新 BSP 框架的主要特性如下: 提供多系列 BSP 模板,大大降低新 BSP 的添加难度: 每个 BSP 都配有齐全的驱动文件,开发者可以方便地使用所 ...

  8. Linux常用命令 - rm命令详解

    21篇测试必备的Linux常用命令,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1672457.html 删除/ ...

  9. jQuery判断多种数据类型

    1.判断是否为数组类型 var obj=[0]; alert((typeof obj=='object')&&obj.constructor==Array)   2. 判断是否为字符串 ...

  10. ysoserial CommonsColletions6分析

    CC6的话是一条比较通用的链,在JAVA7和8版本都可以使用,而触发点也是通过LazyMap的get方法. TiedMapEntry#hashCode 在CC5中,通过的是TiedMapEntry的t ...