一、String、StringBuilder和StringBuffer的区别

1. String是字符串常量,StringBuilder和StringBuffer是字符串变量

String对象创建完成之后,如果对其更改,都是重新创建一个字符串对象,让引用变量重新指向其引用地址,而StringBuilder和StringBuffer都是可变的;

2. StringBuilder是线程不安全的,StringBuffer是线程安全的

StringBuffer相关方法添加了线程同步关键字synchronize关键字,故线程安全的,但效率低比StringBuilder低。

二、String为什么设计成不可变(immutable)

1. 字符串常量池的优化需要

字符串常量池针对String字符串使用的一种优化策略,创建字符串对象前,先检查字符串常量是否已经有该字符串(obj1.equal(obj2)),有直接返回字符串在字符串常量池的引用,如果String为可变的,这种优化策略则无效;

2. 允许String对象缓存HashCode

字符串的不变性保证了hashcode唯一性,不可变的hashcode可以被缓存而不用重新计算,提升了像使用String作为键值的hashmap的效率,这也侧面反映了hashmap为什么多数使用String作为键值的原因了;

3. 多线程使用安全性

字符串不可变,所以在多线程可以共享一个字符串实例,而不需要做额外的线程同步;

4. 类加载器需要

类加载器用到字符串,不可变性提供了安全性,以便类的正确加载;例如在加载java.sql.Connection类,如果这个值被改成myhacked.Connection,则会对数据库造成不可知的破坏;

5. 安全性

如果字符串是不可变的,则会引起很严重的安全问题;例如数据库的用户名和密码都是以字符串形式传入获得数据库的连接,socket编程中,主机名等都是以字符串形式传入,如果字符串可变,黑客可以很容易改变字符串对象的值,造成安全漏洞。

三、String直接创建对象(String s="abc")和intern()方法的区别

两者在创建字符串对象先去字符串常量池查找,如果有,直接返回该字符串的引用,没有则在字符串常量池创建并返回引用,看上去两者无差别,但是这样那么intern存在的意义为何?

测试代码 Test.java

String s1 = "ab";
String s2 = "c";
String s3 = "abc"; System.out.println(s3=="ab"+"c"); //true
System.out.println(s3==s1+s2); //false
System.out.println(s3==(s1+s2).intern()); //true

编译代码 Test.class

String s1 = "ab";
String s2 = "c";
String s3 = "abc";
System.out.println(s3 == "abc");
System.out.println(s3 == s1 + s2);
System.out.println(s3 == (s1 + s2).intern());

"ab"+"c";字符串拼接在编译期可以确定其值,进而可以在编译阶段确定该字符串是否存在于字符串常量池;但是s1+s2;字符串引用拼接需要在运行期才能得到结果,指望不上编译器的字符串常量池优化策略了,这时候intern方法作用便体现了,在运行期确定常量池是否有需要创建的字符串对象,如果有,返回其字符串常量池的引用。故得出的结论:String直接赋值和intern方法在字符串常量池的优化策略上,一个体现在编译期,一个则在运行期。

四、StringBuilder和"+"号的区别?

1. 拼接字符串常量

测试类

6 String s1 = "a" + "b" + "c";
7 String s2 = new StringBuilder().append("a").append("b").append("c").toString();

编译class

String s1 = "abc";
String s2 = "a" + "b" + "c";

字节件ByteCode

L0
LINENUMBER 6 L0
LDC "abc"
ASTORE 1
L1
LINENUMBER 7 L1
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
LDC "a"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC "b"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC "c"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 2

使用“+”进行字符串常量的拼接在编译时就已经完成,而使用 StringBuilder 进行字符串拼接需要在运行时完成。所以单纯的字符串常量拼接“+”的效率 应该高于 StringBuilder

2. 拼接字符串和引用

测试类

6 String s1 = "a";
7 String s2 = new StringBuilder().append(s1).append("b").append("c").toString();
8 String s3 = s1 + "b" + "c";

编译class

String s1 = "a";
String s2 = s1 + "b" + "c";
String s3 = s1 + "bc";

字节码ByteCode

L0
LINENUMBER 6 L0
LDC "a"
ASTORE 1
L1
LINENUMBER 7 L1
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC "b"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC "c"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 2
L2
LINENUMBER 8 L2
NEW java/lang/StringBuilder
DUP
INVOKESPECIAL java/lang/StringBuilder.<init> ()V
ALOAD 1
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
LDC "bc"
INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;
INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;
ASTORE 3

从字节码可以看出“+”拼接的字符串引用底层还是使用StringBuilder

参考链接

Java中的String,StringBuilder,StringBuffer三者的区别?

java中String类为什么不可变?

java String中的intern和String a="abc"的区别是什么?

String不得不说的那些事的更多相关文章

  1. 【原创】关于DNS不得不说的一些事

    引言 今天我们来聊聊DNS. 所谓域名系统(Domain Name System缩写DNS,Domain Name被译为域名)是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据 ...

  2. String类基础的那些事!

    第三阶段 JAVA常见对象的学习 第一章 常见对象--String类 (一) String 类的概述及其构造方法 (1) 概述 多个字符组成的一串数据,例如 "abc" 也可以看成 ...

  3. 【转】关于DNS不得不说的一些事

    转自:https://www.cnblogs.com/rjzheng/p/11395695.html 引言 今天我们来聊聊DNS.所谓域名系统(Domain Name System缩写DNS,Doma ...

  4. 我和ip_conntrack不得不说的一些事

    面对让人无语的ip_conntrack,我有一种说不出的感觉!自从接触它到现在,已经两年多了,其间我受到过它的恩惠,也被它蹂躏过,被它玩过,但是又不忍心舍弃它,因为我找不到更好的替代.工作中,学习中, ...

  5. Session与Cookie间不得不说的一些事

    在很久很久以前,刚有浏览器和网页的时候,web开发者发现了一个问题,我必须要在客户端这边保存一些东西才能实现某些功能,比如大家喜闻乐见的购物车.用户登录.自动登陆等.但是客户端只有一个浏览器,怎么在用 ...

  6. 镜像仓库管理:与Portus不得不说的那些事

    背景: 目前在做一个云计算相关的项目,其中有这样一个需求:每个平台用户都有自己的docker镜像仓库(docker registry),用户可以对自己的镜像仓库的push/pull权限进行管理,也就是 ...

  7. 《java入门第一季》之类(String类常见方法小叙)

    String类下面的构造方法和一些常见的方法: /* * 字符串:就是由多个字符组成的一串数据.也可以看成是一个字符数组. * 通过查看API,可以知道 * A:字符串字面值"abc&quo ...

  8. Java 枚举那点事

    目录 最近有需求,想存自定义的枚举值,比如 HOTLINE("Hotline") 我想存 Hotline 于是研究了一下Java的枚举问题 如下数据库的Entity (贫血模型哈) ...

  9. 关于javaScript事件委托的那些事

    今天是第一次写稿,还是有那么一丢丢小鸡冻...回归正题啦... 关于javaScript事件委托不得不说的那些事,为什么要使用事件委托? 我们可以这么说,假设老板要分配一项任务,首先要秘书叫A君来到办 ...

随机推荐

  1. 2018.10.26 NOIP模拟 性感手枪(搜索)

    传送门 vis[x][y]vis[x][y]vis[x][y]记录这个点是否在之前被搜过,且被搜过的坐标是什么. 然后搜索的时候记录一个循环的下标和不循环的下标就行了. 代码

  2. Javascript、Jquery获取浏览器和屏幕各种高度宽度(单位都为px)

    Javascript.Jquery获取浏览器和屏幕各种高度宽度 另外参见    http://www.cnblogs.com/top5/archive/2009/05/07/1452135.html ...

  3. python模块:pickle

    """Create portable serialized representations of Python objects. See module copyreg f ...

  4. 3-具体学习git--reset回到过去的版本(commit间穿梭),checkout单个文件穿梭

    git log --oneline 命令可以在一块儿显示做过的改动. 我在change 2时忘了一条,想在change 1后再添加一个语句或一个操作,然后这个状态再提交仍作为change 2.将这个s ...

  5. 第19章:MongoDB-聚合操作--聚合管道--$limit+$skip

    ①$limit “$limit”:负责数据的取出个数: “$skip”:数据的跨过个数. ②范例:使用“$limit”设置取出的个数

  6. load data妙用

    load变量和用户变量的巧妙结合,实现灵活导入字段列(NO.1) LOAD DATA INFILE 'file.csv' INTO TABLE dados_meteo (@var1, @var2) S ...

  7. 【慕课网实战】Spark Streaming实时流处理项目实战笔记三之铭文升级版

    铭文一级: Flume概述Flume is a distributed, reliable, and available service for efficiently collecting(收集), ...

  8. javaweb项目中的文件上传下载功能的实现

    框架是基于spring+myBatis的. 前台页面的部分代码: <form action="${ctx}/file/upLoadFile.do"method="p ...

  9. volatile 实现 单例模式

    单例模式的一种实现方式,但很多人会忽略volatile关键字,因为没有该关键字,程序也可以很好的运行,只不过代码的稳定性总不是100%,说不定在未来的某个时刻,隐藏的bug就出来了. 双重校验锁 cl ...

  10. spring之hello(简单环境配置)

    导入java包 配置springmvc.xml文件 <?xml version="1.0" encoding="UTF-8"?> <beans ...