String

String 被声明为 final,因此不能被继承。(Integer 等包装类也不能被继承)

在 java8 中,String 内部使用 char 数组 来存储数据

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}

在 java9 中,String 内部使用 byte 数组存储字符串,同时使用 coder 来标识使用了哪种编码

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final byte[] value; /** The identifier of the encoding used to encode the bytes in {@code value}. */
private final byte coder;
}

value 数组被声明 final,因此 value 数组初始化之后就不能再引用其他数组。并且 String 内部没有改变 value 数组的方法,因此可以保证 String 不可变

String 不可变的好处

1. 可以缓存 hash 值

因为 String 的 hash 值经常被使用,例如 String 用做 HashMap 的 key。不可变的特性可以使得 hash 值也不可变,因此只需要进行一次计算。

2. String pool

如果一个 String 对象已经被创建过,那么就会从常量池中取的引用,只有 String 是不可变的,才能使用 String pool

3. 安全性

String 经常作为参数,String 不可变可以保证参数不可变,例如在作为网络连接参数的情况下如果 String 是可变的,那么在网络连接过程中,String 被改变,改变 String 的那一方以为现在连接的是其它主机,而实际情况却不一定是。

4. 线程安全

因为字符串是不可变的,所以是多线程安全的,同一个字符串实例可以被多个线程共享。这样便不用因为线程安全问题而使用同步。字符串自己便是线程安全的。

String, StringBuffer and StringBuilder

1. 可变性

String 不可变(String 类中使用 final 关键字修饰字符数组来保存字符串,所以 String 对象是不可变的。)

StringBuilder 与 StringBuffer是可变的(都继承AbstractStringBuilder,也是使用 char 数组保存数据,但是没有使用 final 修饰符)

AbstractStringBuilder:

abstract class AbstractStringBuilder implements Appendable, CharSequence {
/**
* The value is used for character storage.
*/
char[] value; /**
* The count is the number of characters used.
*/
int count; /**
* This no-arg constructor is necessary for serialization of subclasses.
*/
AbstractStringBuilder() {
}
}

2. 线程安全性

  1. String 不可变,线程安全(操作少量的数据使用)
  2. StringBuilder 线程不安全(单线程操作字符串缓冲区下操作大量数据)
  3. StringBuffer 线程安全,内部使用 synchronized 进行同步(多线程操作字符串缓冲区下操作大量数据)

String pool

字符串常量池(String Pool)保存着所有字符串字面量(literal strings), 这些字面量在编译时期就确定。不仅如此, 还可以使用 String 的 intern() 方法在运行过程将字符串添加到 String Pool 中。

当一个字符串调用 intern() 方法时,如果 String Pool 中已经存在一个字符串和该字符串值相等(使用 equals() 方法进行确定),那么就会返回 String Pool 中字符串的引用;否则,就会在 String Pool 中添加一个新的字符串, 并返回这个新字符串的引用。

下面示例中,s1 和 s2 采用 new String() 的方式新建了两个不同字符串,而 s3 和 s4 是通过 s1.intern() 方法取得同一个字符串引用。intern() 首先把 s1 引用的字符串放到 String Pool 中, 然后返回这个字符串引用。因此 s3 和 s4 引用的是同一个字符串。

String s1 = new String("aaa");  //堆内存中 s1为一个引用
String s2 = new String("aaa"); //堆内存中 s2为另一个引用
System.out.println(s1 == s2); // false
String s3 = s1.intern(); //s3为s1的引用
String s4 = s1.intern(); //s4为s1的引用
System.out.println(s3 == s4); // true

如果是采用 "bbb" 这种字面量的形式创建字符串,会自动地将字符串放入 String Pool 中。

String s5 = "bbb";              //放在常量池中
String s6 = "bbb"; //从常量池中查找
System.out.println(s5 == s6); // true

在 Java 7 之前,String Pool 被放在运行时常量池中,它属于永久代。而在 Java 7,String Pool 被移到堆中。这是因为永久代的空间有限,在大量使用字符串的场景下会导致 OutOfMemoryError 错误。

new String("abc")

使用这种方式会创建两个字符串对象,前提是常量池中还没有 “abc” 字符串对象

  • “abc” 属于字符串字面量,因此编译时期会在 String Pool 中创建一个字符串对象,指向这个 “abc” 字符串字面量;
  • 使用 new 的方式会在堆中创建一个字符串对象

    ------------恢复内容结束------------

Java 基础之 String 类的更多相关文章

  1. Java基础笔记-String类

    String 类(被final修饰) 字符串是一种特殊的对象,一旦字符串被初始化就不可以被改变了.(内容不变) 例如: String  s = “abc”; String  s1 = new Stri ...

  2. Java基础之String类

    String类 字符串是不可变的,对其做的任何改变,会生成一个对象,不会改变有原有对象. ==和equals() String s1 = "good"; String s2 = & ...

  3. Java基础教程——String类

    String类 Java程序中的所有字符串字面值(如 "abc" )都是String的实例 字符串是常量(因为 String 对象是不可变的,所以可以共享) 字符串的本质是字符数组 ...

  4. Java基础笔记-String类2

    StringBuffer 特点: 是字符串缓冲区. 是一个容器,其长度可变,可以操作添加多个数据类型. 最后通过toString方法变成字符串. 被final锁修饰,因此不能被继承. 存储: 方法1: ...

  5. Java入门 - 语言基础 - 14.String类

    原文地址:http://www.work100.net/training/java-string.html 更多教程:光束云 - 免费课程 String类 序号 文内章节 视频 1 概述 2 创建字符 ...

  6. Java基础-DButils工具类(QueryRunner)详解

    Java基础-DButils工具类(QueryRunner)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC ...

  7. Java基础之File类的使用

    Java基础之File类的使用 1.File类的构造方法和常用方法 2.对File中listFile(FileNameFilter name)学习 3.与File文件类相关的实现 File类的构造方法 ...

  8. Java基础之String、StringBuffer、StringBuilder浅析

    Java基础之String.StringBuffer.StringBuilder浅析 一.前言: 位于java.lang包下的String.StringBuilder.StringBuffer一般都是 ...

  9. Java基础-常用工具类(一)

    object类 Object 类是所有类的的父类,如果一个类没有明确使用EXPENTS关键字明确标识继承另外一个类,那么这个类默认继承object类,oject类中的方法适合所有子类 1)toStri ...

随机推荐

  1. 凯撒密码(Java)

    事实上就是把每个字母偏移一下而已,并且字符不限于a-zA-z,可以是别的,那就很显而易见了,代码如下:定义一个Caesar密码类,成员变量只有密钥,也就是偏移量key 代码如下: public cla ...

  2. 7、Python语法之与用户交互、运算符

    一 .程序与用户交互 1.1.什么是与用户交互 用户交互就是人往计算机中input/输入数据,计算机print/输出结果. 1.2.为什么要与用户交互 为了让计算机能够像人一样与用户沟通交流. 比如, ...

  3. <摘自>飞:jxl简析[ http://www.emlog.net/fei ]

    <摘自>飞:jxl简析:http://www.emlog.net/fei 最近,完成了一个网上报表系统,刚巧用到了一个 JAVA 操作 excel 表格的 API .闲来无事,就将其大概的 ...

  4. tcp syn-synack-ack 服务端 接收 SYN tcp_v4_do_rcv分析

    rcv 分析: /* The socket must have it's spinlock held when we get * here, unless it is a TCP_LISTEN soc ...

  5. GC 的认识(转) https://github.com/qcrao/Go-Questions/blob/master/GC/GC.md#1-什么是-gc有什么作用

    1. 什么是 GC,有什么作用? GC,全称 Garbage Collection,即垃圾回收,是一种自动内存管理的机制. 当程序向操作系统申请的内存不再需要时,垃圾回收主动将其回收并供其他代码进行内 ...

  6. 基于 Nebula Operator 的 K8s 自动化部署运维

    摘要:Nebula Operator 是 Nebula Graph 在 Kubernetes 系统上的自动化部署运维插件.在本文,你将了解到 Nebula Operator 的特性及它的工作原理. 从 ...

  7. 腾讯云容器服务 TKE 推出新一代零损耗容器网络

    随着容器技术的发展成熟,越来越多的组件迁移到容器,在技术迁移过程中,数据库,游戏,AI 这些组件对容器网络性能(时延,吞吐,稳定性)提出了更高的要求.为了得到更优的时延和吞吐表现,各大云厂商都在致力于 ...

  8. CSS 常用列表样式

    CSS 常用列表样式 CSS没学扎实,复习记录一下.下面是一些常用的属性 list-style-image 指定一个图片作为列表项的标记 默认值none,可设置为图片的url list-style-i ...

  9. mybatis 多数据源动态切换

    笔者主要从事c#开发,近期因为项目需要,搭建了一套spring-cloud微服务框架,集成了eureka服务注册中心. gateway网关过滤.admin服务监控.auth授权体系验证,集成了redi ...

  10. Spring接口

    FactoryBean接口 Spring中有两种类型的Bean:一种是普通的JavaBean:另一种就是工厂Bean(FactoryBean),这两种Bean都受Spring的IoC容器管理. Fac ...