String、StringBuiler、StringBuffer的区别
一、三者的区别概述
1.可变与不可变:String底层使用final修饰的字符数组来存储字符串,它属于不可变类,对String对象的任何改变操作都不会改变原对象,而是生成一个新对象。StringBuilder和StringBuffer有一个共同的抽象父类AbstractStringBuiler,它们底层是一个不用final修饰的字符数组,因此它们是可变的。
2.是否线程安全:String由final修饰,因此必然是线程安全的。StringBuilder与StringBuffer的唯一区别就是StringBuffer的方法都加上了syncharnized,因此StringBuffer是线程安全的。
3.执行效率:StringBuilder > StringBuffer > String
二、对String的深入剖析
1.String str="hello world"和String str=new String("hello world")的区别
private static void test1() {
String str1 = "hello world";
String str2 = new String("hello world");
String str3 = "hello world";
String str4 = new String("hello world");
System.out.println(str1==str2);
System.out.println(str1==str3);
System.out.println(str2==str4);
}
运行结果:
false
true
false
在class文件中有一部分用来存储编译期生成的字面常量以及符号引用,这部分叫做class文件的常量池,在运行期间对应着方法区的运行时常量池。上面代码中str1,str2在编译期间都会生成字面常量和符号引用,运行时会将字面常量保存在方法区的运行时常量池,只保存一份,将引用和对象进行绑定时会检查常量池中是否存在相同的字面常量,有则直接绑定,没有则新建,因此可知str1,str2指向的是同一个字面常量,而new操作是在堆区新建对象,肯定是产生了新的对象。
2.
private static void test2() {
String a = "hello2";
String b = "hello" + 2;
System.out.println((a == b));
}
运行结果:true
在编译期"hello" + 2被优化为hello2,因此a,b指向的是同一个对象。
3.
private static void test3() {
String a = "hello2";
String b = "hello";
String c = b + 2;
System.out.println((a == c));
}
运行结果:false
由于存在符号引用,b+2并不会被编译器优化,只有处理字面常量时才会有优化。因此c,a是两个不同的对象。
4.
private static void test4() {
String a = "hello2";
final String b = "hello";
String c = b + 2;
System.out.println((a == c));
}
运行结果:true
由于b被final修饰,属于一个常量,编译器会进行优化,对final变量的访问在编译期间都会直接被替代为真实的值,因此c = "hello" + 2。
5.
public class Main {
public static void main(String[] args) {
String a = "hello2";
final String b = getHello();
String c = b + 2;
System.out.println((a == c));
}
public static String getHello() {
return "hello";
}
}
运行结果:false
b虽然被final修饰,但它的值只有在运行期间才能确定,因此编译器不会优化。a,c指向不同的对象。
6.
public class Main {
public static void main(String[] args) {
String a = "hello";
String b = new String("hello");
String c = new String("hello");
String d = b.intern();
System.out.println(a==b);
System.out.println(b==c);
System.out.println(b==d);
System.out.println(a==d);
}
}
运行结果:
false
false
false
true
在String类中,intern方法是一个本地方法,在JAVA SE6之前,intern方法会在运行时常量池中查找是否存在内容相同的字符串,如果存在则返回指向该字符串的引用,如果不存在,则会将该字符串入池,并返回一个指向该字符串的引用。因此,a和d指向的是同一个对象。
7.String str = new String("abc")创建了多少个对象?
创建了一个对象,涉及到两个对象。在类加载的过程中,在运行时常量池中创建了一个"abc"对象,而在代码执行过程中只创建了一个String对象。
8.
public class Main {
public static void main(String[] args) {
String str1 = "I";
//str1 += "love"+"java"; 1)
str1 = str1+"love"+"java"; //2)
}
}
1)的效率比2)的效率要高,1)中的"love"+"java"在编译期间会被优化成"lovejava",而2)中的不会被优化。
个人总结:编译器是否会在编译期优化取决于取决于这个"常量"在编译期是否是一个确定的值,以及它是否是一个字面常量,如果存在引用符号则不会优化。
参考链接:https://www.cnblogs.com/dolphin0520/p/3778589.html
https://www.cnblogs.com/xudong-bupt/p/3961159.html
https://blog.csdn.net/weixin_35235724/article/details/112080445
String、StringBuiler、StringBuffer的区别的更多相关文章
- JAVA中String与StringBuffer的区别
String和StringBuffer的区别,网上资料可以说是数不胜数,但是看到这篇文章,感觉里面做的小例子很有代表性,所以转一下,并自己做了一点总结. 在java中有3个类来负责字符的操作. 1.C ...
- String 和 StringBuffer的区别
String与StringBuffer的区别: 简单地说,就是一个常量和变量的关系.StringBuffer对象的内容可以修改:而String对象一旦产生后就不可以被修改,重新赋 ...
- boolean和Boolean, char和Character , byte和Byte, short和Short, int和Integer , long和Long , float和Float, double和Double的区别 , String和StringBuffer的区别
Java提供两种不同的类型:引用类型和原始类型(内置类型).Int是java的原始数据类型,Integer是java为int提供的封装类. Java为每个原始数据类型提供了封装类. 其中原始数据类型封 ...
- string 和 stringbuffer的区别?
string和stringbuffer的区别其实是变量和常亮的关系,string和stringbuffer内部实现的原理不同,在修改string对象时会产生另外的对象,也就是说在内存中会有两个存储区域 ...
- 【转载】String和StringBuffer的区别,以及StringBuffer的常用方法介绍
String与StringBuffer的区别简单地说,就是一个变量和常量的关系.StringBuffer对象的内容可以修改:而String对象一旦产生后就不可以被修改,重新赋值其实是两个对象.Stri ...
- String和StringBuffer的区别
1.选自http://szh-java.iteye.com/blog/1666630 String 1,Stirng是对象不是基本数据类型 2,String是final类,不能被继承.是不可变对象,一 ...
- String与StringBuffer的区别
首先,String和StringBuffer主要有2个区别: (1)String类对象为不可变对象,一旦你修改了String对象的值,隐性重新创建了一个新的对象,释放原String对象,StringB ...
- String和StringBuffer的区别;字符串的一些基本方法
String 和 StringBuffer区别 字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 需要注意的是,String的 ...
- Java语言基础(四) String和StringBuffer的区别
Java提供了两个字符串类:String和StringBuffer. String提供了数值不可变的字符串,而StringBuffer提供的字符串对象可以进行修改. 当知道字符数据要改变的时候就可以使 ...
- java中String和StringBuffer的区别
前言 String和StringBuffer本质上都是修饰字符串的只是含义不同 StringBuffer叫做字符串缓冲区 首先看下string类的例子 public class Work1 { pub ...
随机推荐
- [Java]程序运行时的内存分配
本文出处:<Thinking in JAVA> 寄存器这是最快的存储区,因为它位于不同于其他存储区的地方--处理器内部.但是寄存器的数量极其有限,所以寄存器根据需求进行分配.你不能直接控制 ...
- 配置IPv6地址跳变——网络测试仪实操
第一部分:什么是IPv6地址跳变? IPv6地址跳变是指IPv6地址进行一系列有规则的变化,Renix支持对IPv6地址进行递增.递减.列表和随机变化. 如当用户想要仿真大量的源IPv6地址变化的数据 ...
- strtok()出现segment fault的错误
在写一个简易的 shell 时,需要将命令行的命令通过空格分割成一个个字符串参数,这里我使用了 strtok() 函数,然后遇到了 segment fault 的错误. 出现问题的代码如下: 终于寻找 ...
- linux设置 自定义脚本开机启动
本文原创,转载请标明出处 https://blog.csdn.net/qq2531246791/article/details/89036084 一. 赋予可执行权限 chmod +x /etc/rc ...
- Java多线程编程核心技术---多线程技能
1.继承Thread /** * Copyright (C), 2018-2018, * FileName: MyThread * Author: 大象 * Date: 2018-06-08 22:3 ...
- 如何在 Spring Boot 优雅关闭加入一些自定义机制
个人创作公约:本人声明创作的所有文章皆为自己原创,如果有参考任何文章的地方,会标注出来,如果有疏漏,欢迎大家批判.如果大家发现网上有抄袭本文章的,欢迎举报,并且积极向这个 github 仓库 提交 i ...
- 从零开始Pytorch-YOLOv3【笔记】(一)配置文件解读
前言 这是github上的一个项目YOLO_v3_tutorial_from_scratch,它还有相应的blog对其详细的解读.机器之心翻译了他的tutorial:从零开始PyTorch项目:YOL ...
- Solon 1.6.30 发布,更现代感的应用开发框架
相对于 Spring Boot 和 Spring Cloud 的项目 启动快 5 - 10 倍 qps 高 2- 3 倍 运行时内存节省 1/3 ~ 1/2 打包可以缩小到 1/2 ~ 1/10(比如 ...
- 接口自动化测试框架(Java 实现)
目录 需求分析 开发设计 分层与抽象 技术选型 主要类设计 测试文件设计 工程目录设计 工程实现 github 地址 运行示例 需求分析 需求点 需求分析 通过 yaml 配置接口操作和用例 后续新增 ...
- L2Dwidget二次元前端添加人物插件
如果想要在博客园上添加这个插件,只需要在设置的"页首html代码"中添加下面的js就行 <!-- 右下角live2d效果 --> <script src=&quo ...