Java String的探讨
关于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的探讨的更多相关文章
- 从Java String实例来理解ANSI、Unicode、BMP、UTF等编码概念
转(http://www.codeceo.com/article/java-string-ansi-unicode-bmp-utf.html#0-tsina-1-10971-397232819ff9a ...
- Java String.split()小点
java String.split(); 别的不说,单说其中一个问题,这个函数去切分空字符串时,得到的结果: public static void main(String[] args) {// St ...
- Java总结篇系列:Java String
String作为Java中最常用的引用类型,相对来说基本上都比较熟悉,无论在平时的编码过程中还是在笔试面试中,String都很受到青睐,然而,在使用String过程中,又有较多需要注意的细节之处. 1 ...
- java String.split()函数的用法分析
java String.split()函数的用法分析 栏目:Java基础 作者:admin 日期:2015-04-06 评论:0 点击: 3,195 次 在java.lang包中有String.spl ...
- java string类型的初始化
以下基本上是java string类型最常用的三种方法 new string()就不介绍了 基本等同于第三种 String a; 申明一个string类型的 a,即没有在申请内存地址,更没有在内存 ...
- Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0
课程概要 String 字符串 String字符串常用方法 StringBuffer StringBuilder String字符串: 1.实例化String对象 直接赋值 String str=& ...
- Java String类详解
Java String类详解 Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生. 类结构: public final ...
- java string,需要进行首字母大写改写
java string,需要进行首字母大写改写,网上大家的思路基本一致,就是将首字母截取,转化成大写然后再串上后面的,类似如下代码 //首字母大写 public static String c ...
- Java String Class Example--reference
reference:http://examples.javacodegeeks.com/core-java/lang/string/java-string-class-example/ 1. Intr ...
随机推荐
- OVN入门
参考链接 如何借助 OVN 来提高 OVS 在云计算环境中的性能 OVN简介 Open vSwitch Documentation OVSDB介绍及在OpenDaylight中的调用 OpenDayl ...
- 第一章 Net 5.0 快速开发框架 YC.Boilerplate--框架介绍
YC.Boilerplate 框架介绍 YC.Boilerplate 是一套快速开发框架,采用当下流行的前后端分离开发模式,前端 采用VUE.后端采用Net 5.0:框架实现了 多租户.动态webAp ...
- 删除mysql数据库后django重建数据库
问题:由于表的结构设计的不太合理,后来要添加列,但是在django中使用makemigrations一直失败. 解决:索性就把mysql中对于django的数据库删了(其实也不用删除),在django ...
- Red Hat Enterprise Linux 7.2修改主机名(hostname)
Red Hat Enterprise Linux 7.2在安装的时候,会默认生成主机名:localhost. 那么如何修改成自己想要的自己名? //格式为:用户名@主机名 比如: [root@loca ...
- MySQL读写IO的操作过程解析
数据库作为存储系统,所有业务访问数据的操作都会转化为底层数据库系统的IO行为(缓存系统也可以当做是key-value的数据库),本文主要介绍访问MySQL数据库的IO流程以及IO相关的参数. 一.My ...
- JavaScript——数组——数组长度
JavaScript--数组--数组长度 JavaScript中的数组长度是可变的,可用赋值运算符改变数组大小,如果改变之后的数组的长度比原数组大,则新数组会在末尾补充相应数量的空位,空位上的数组元素 ...
- vue ele table表格 设置只能勾选一个
table 更改属性设置: <el-table ref="multipleTable" :data="tableData" tooltip-effect= ...
- 机器学习之支持向量机(python)
参考链接:https://blog.csdn.net/weixin_33514582/article/details/113321749.https://blog.csdn.net/weixin_44 ...
- 记录一下Vray5中文汉化版本中导出EXR或vrimg多通道文件的那些坑和解决方法
最近在给一个培训机构代课,学生英语基础差,就安装了Vray5的中文版,噩梦从此开始. 做过合成的都知道,需要输出多通道到NUKE或者AE中进行合成,通常情况下把多个pass分成不同的文件对硬盘反复读写 ...
- Abp Vnext3 vue-admin-template(一用户登录)
Git地址https://github.com/PanJiaChen/vue-admin-template/blob/master/README-zh.md 官方文档https://panjiache ...