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 ...
随机推荐
- ceph-deploy离线部署ceph集群及报错解决FAQ
ceph-deploy部署ceph集群 环境介绍 主机名 ip地址 操作系统 角色 备注 ceph-node1 10.153.204.13 Centos7.6 mon.osd.mds.mgr.rgw. ...
- Google发布跨云Serverless管理平台Knative
企业只要使用由Google与Pivotal.IBM.红帽和SAP等企业共同开发的跨云Serverless管理平台Knative,就能在支持Kubernetes的云平台上自由的迁移工作负载,无论是跨私有 ...
- Django ORM 多表操作
目录 Django ORM 多表操作 表模型 表关系 创建模型 逆向到表模型 插入数据 ORM 添加数据(添加外键) 一对多(外键 ForeignKey) 一对一 (OneToOneFeild) 多对 ...
- 《Java编程思想》学习笔记(详细)
目录 01 对象导论 02 一切都是对象 03 操作符 04 控制执行流程 05 初始化与清理 06 访问权限控制 07 复用类(继承) 08 多态 09 接口 10 内部类 11 持有对象 12 通 ...
- JZ-070-数字序列中的某一位数字
数字序列中的某一位数字 题目描述 数字以 0123456789101112131415... 的格式序列化到一个字符串中,求这个字符串的第 index 位. 题目链接: 数字序列中的某一位数字 代码 ...
- LeetCode-011-盛最多水的容器
盛最多水的容器 题目描述:给你 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, ...
- VirtualBox虚拟机--桥接模式
问题概述:VirtualBox虚拟机设置桥接模式,与宿主机互相ping通. 注:如果按照以下方式设置了还是ping不通,查看虚拟机防火墙是否已关. 公司电脑拿去维修了,在自己家里电脑上部署项目开发环境 ...
- docker学习(一) - docker简介
(一)Docker是什么? Docker 是一个开源的应用容器引擎,你可以将其理解为一个轻量级的虚拟机,开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上 ...
- Laravel 报错: Dotenv values containing spaces must be surrounded by quotes.
报错信息如下: 原因: .env文件配置中欧冠包含空格的配置信息,用双引号""引起来即可
- java控制流学习
java流程控制学习 Scanner对象 概念 1.通过Scanner类实现程序和人的交互,通过它获取到用户的输入.java.util.Scanner是java5的特征. 我们可以通过Scanner类 ...