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 ...
随机推荐
- 前端调用后台接口下载word文档的两种方法
1传统的ajax虽然能提交到后台,但是返回的数据被解析成json,html,text等字符串,无法响应浏览器下载.就算使用bob模拟下载,数据量大时也不方便 废话不多说:上代码(此处是Layui监听提 ...
- canvas——动画实例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Seq2Seq sequence-to-sequence模型 简介
Sequence-to-sequence (seq2seq) 模型. 突破了传统的固定大小输入问题框架 开创了将DNN运用于翻译.聊天(问答)这类序列型任务的先河 并且在各主流语言之间的相互翻译,和语 ...
- D3之svg transform 与 css3 transform 区别与联系
D3就不用多介绍了,在数据可视化界属于大佬级别的js库.在这里主要想记录一下在写程序期间遇到的一个问题. 如下图所示,想完成主视图在小地图上的映射,小地图的白色矩形框用来代表当前主视图可见区域,主视图 ...
- QT学习日记篇01(1)-QT界面初探- *.pro文件详解
一: 项目管理文件(.pro文件) 项目管理文件用于记录项目的一些设置,以及项目包含文件的组织管理 后缀为".pro"的 文件是项目的管理文件,文件名就是项目的名称,如Demo.p ...
- SSH无法正常连接服务器
远程权限没有打开 #允许root登录 PermitRootLogin yes #不允许空密码登录 PermitEmptyPasswords no 远端的ssh信息有变化,本地保存的那个需要删掉 Use ...
- kubeadm方式搭建K8S集群
一.kubeadm介绍 二.安装要求 三.集群规划 四.环境初始化(在每个服务器节点操作) 1.关闭防火墙 2.关闭selinux 3.关闭swap 4.根据规划设置主机名 5.在Master添加ho ...
- [考试总结]noip模拟47
感觉自己放弃题目还是过于容易. 其实第一题不是很难,但是自己拿了一个暴力就走人了.. 然后其实简单优化一下子就有不少分数. 然后第二题的本质不同的子序列个数的方程没有推出来,如果推出来就会直接有 \( ...
- Intel® QAT 加速卡之IPSec示例
Intel QAT 加速卡之IPSec示例 文章目录 Intel QAT 加速卡之IPSec示例 1. QAT处理IPSec入站报文 2. QAT处理IPSec出站报文 3. 组织架构 4. 示例源码 ...
- Springcloud轻松上手
Springcloud技术分享 Spring Cloud 是一套完整的微服务解决方案,基于 Spring Boot 框架,准确的说,它不是一个框架,而是一个大的容器,它将市面上较好的微服务框架集成进来 ...