一、三者的区别概述

  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的区别的更多相关文章

  1. JAVA中String与StringBuffer的区别

    String和StringBuffer的区别,网上资料可以说是数不胜数,但是看到这篇文章,感觉里面做的小例子很有代表性,所以转一下,并自己做了一点总结. 在java中有3个类来负责字符的操作. 1.C ...

  2. String 和 StringBuffer的区别

    String与StringBuffer的区别:            简单地说,就是一个常量和变量的关系.StringBuffer对象的内容可以修改:而String对象一旦产生后就不可以被修改,重新赋 ...

  3. 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为每个原始数据类型提供了封装类. 其中原始数据类型封 ...

  4. string 和 stringbuffer的区别?

    string和stringbuffer的区别其实是变量和常亮的关系,string和stringbuffer内部实现的原理不同,在修改string对象时会产生另外的对象,也就是说在内存中会有两个存储区域 ...

  5. 【转载】String和StringBuffer的区别,以及StringBuffer的常用方法介绍

    String与StringBuffer的区别简单地说,就是一个变量和常量的关系.StringBuffer对象的内容可以修改:而String对象一旦产生后就不可以被修改,重新赋值其实是两个对象.Stri ...

  6. String和StringBuffer的区别

    1.选自http://szh-java.iteye.com/blog/1666630 String 1,Stirng是对象不是基本数据类型 2,String是final类,不能被继承.是不可变对象,一 ...

  7. String与StringBuffer的区别

    首先,String和StringBuffer主要有2个区别: (1)String类对象为不可变对象,一旦你修改了String对象的值,隐性重新创建了一个新的对象,释放原String对象,StringB ...

  8. String和StringBuffer的区别;字符串的一些基本方法

    String 和 StringBuffer区别 字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 需要注意的是,String的 ...

  9. Java语言基础(四) String和StringBuffer的区别

    Java提供了两个字符串类:String和StringBuffer. String提供了数值不可变的字符串,而StringBuffer提供的字符串对象可以进行修改. 当知道字符数据要改变的时候就可以使 ...

  10. java中String和StringBuffer的区别

    前言 String和StringBuffer本质上都是修饰字符串的只是含义不同 StringBuffer叫做字符串缓冲区 首先看下string类的例子 public class Work1 { pub ...

随机推荐

  1. 打破刻板印象,了解真正的商业智能BI

    ​在技术飞速发展的过程中,人们越来越怀疑传统的数据分析方法.可以通过对商业智能的各种误解来解释这一点,如今,这种误解正在作为有效的真理传播.例如,数据仓库已达到其目标.而数据质量似乎也正在失去其相关性 ...

  2. 这款智能又高效的自助式BI工具,你应该了解一下

    如今,企业的经营面临越来越激烈的竞争,如何将数据的价值发挥到最大化,成为众多企业急需解决的问题.如果部署数据分析平台还像以前那样要经历漫长实施过程的话,那么数据化运营将成为空谈.在市场需求的催化下,& ...

  3. 企业环境下用脚本设置ubuntu防火墙

    ubuntu防火墙设置 初始状态下直接设置即可,尽量不要尝试 重装 iptables 以及ufw,很容易导致 防火墙崩掉,最后可能只能重装系统. 配置脚本 firewall.sh #/bin/bash ...

  4. 3D打印第二弹:狗牌

    给朋友做一个狗牌(误,给朋友的狗狗做一个狗牌 1. 设计 没有设计功底,看看别人是如何做的,搜到一个狗牌: 照着这个做一个,正面是上图这种的:狗狗名字+狗爪子:另一面是手机号加联系说明文字. 2. 建 ...

  5. c# 表格控件SourceGrid使用总结

    网上SourceGrid相关的资料很少,使用过程中做了下记录,以便日后查用 1:初始化 this.grid = new SourceGrid.Grid(); this.grid.Size = new ...

  6. ConvertHelper

    DataTable 转Json using Newtonsoft.Json; public static string DataTableToJson(DataTable dt) { varJsonS ...

  7. matplotlib补充知识及数据清理方法

    今日内容概要 数据操作 数据清洗理论 数据清洗实操 数据操作 read_csv read_excel read_hdf read_html read_json read_msgpack read_sq ...

  8. Python 学习路线(2022)

    原文链接: Python 学习路线(2022) 前几天整理了一份 Go 学习路线(2022),广受好评.那么趁火打劫,不是,是趁热打铁,又整理了一份 Python 学习路线. 内容依然是从入门到进阶, ...

  9. .NET 6: New DateOnly and TimeOnly strcuts

    Background and Motivation .NET 目前有用于处理日期和时间的DateTime和DateTimeOffset.但在许多情况下,用户需要处理日期而根本不关心时间部分,也存在需要 ...

  10. Control Flow in Tensorflow TF中的控制流解析

    写在前面 本文翻译自Tensorflow团队的文章Tensorflow Control Flow Implementation,部分内容加入了笔者自己的理解,如有不妥之处还望各位指教. 目录 概览 控 ...