java.lang.String

本文为 Java 源码阅读中的一节,重要程度为 1

NONGFAH 写于 2019-04-30

本文基于java8
String 类的源码极其简单,本质上是对内部数组的操作,但内部重载方法比较多,建议自己直接阅读源码。

类定义

String 类被设计为 final ,这意味着它不能被继承。

接口

该类实现了三个接口:

  • java.io.Serializable :不含任何方法,标识该类可以进行序列化
  • Comparable : 包含 compareTo(T o) ;用于对象比较
  • CharSequence :包含 length() , charAt(int) , subSequence(int,int),toString() ;表示char值的一个可读序列

方法

String类包括用于检查序列的各个字符的方法:

  • 比较字符串
  • 搜索字符串
  • 提取子字符串
  • 创建将所有字符翻译为大写或小写的字符串的副本

存储结构

该类的存储结构是一个不可变的 char 数组,String 类的对象创建后就不能进行修改。 JDK 提供了两个类用于构造可变的字符串: StringBuilder(线程不安全)、StringBuffer(线程安全)。

属性

private final char[] value;

用于存储 String 的实际内容,定义为 final,不可修改。

private int hash;

hashCode() 的缓存。对象求 hashCode 时,会通过该属性判断是否进行过 hashCode 操作,如果有缓存直接返回,否则计算 hashCode 后将其存储到该属性中。

public static final Comparator CASE_INSENSITIVE_ORDER

指向静态内部类,用于忽略大小写比较字符串。

构造器

前面说过,String 的存储结构是一个 Char 数组,基于此,String 类的所有构造方法本质上都是对该数组赋值。 其构造参数主要接受 byte[] 、 char[] 、 int[] 、 String 、StringBuffer 、StringBuilder 六种类型参数。

byte[]使用字节构造字符串

参数:

  • byte[]

可选参数

  • 起始位置,复制个数 (int ,int)
  • 编码 Charset 或 String
char[]使用字符构造字符串

参数:

  • char[]

可选参数

  • 起始位置,复制个数 ( int , int)
int[]使用码点构造字符串

参数:

  • 码点 int[]
  • 起始位置,复制个数 ( int , int )
String等

初始化新创建的String对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。

方法

接口方法

Comparable 接口

compareTo(String other) 方法

依次比较两个字符串中的字符,遇到字符不同时返回 对象在该字符位置与other的差值,所有字符相同,返回长度差值。 返回 0 为两个字符相同

CharSequence 接口

charAt(int index)

返回指定位置的字符

length()

返回字符串长度

subSequence(int beginIndex, int endIndex)

返回指定范围的字符串子串

toString()

因为String类内部方法大多是重载方法,逻辑大致相同参数不同,故将逻辑功能相同的方法统一分析

其他方法

codePoint*

代码点方法:用于返回指定位置、指定位置之前的代码点及两个位置之间代码点个数

compareTo*

字符串比较方法(可忽略大小写):依次比较两个字符串中的字符,遇到字符不同时返回 对象在该字符位置与other的差值,所有字符相同,返回长度差值。 返回 0 为两个字符相同

contentEquals、nonSyncContentEquals

判断两个字符串内容是否相等(可忽略大小写);多线程环境必须使用contentEquals

indexOf、lastIndexOf

字符串搜索方法:返回指定字符第一次或最后一次出现的索引

字符串编辑方法

format()

使用转换符(类似C语言的 %d )等对字符串进行格式化,非常不常用。

trim()

去除字符串两端的空格

concat(String other)

将other拼接到当前字符换后边;相当于 str1 + str2

replace*

将字符串中第一个字符、字符串、所有字符串替换为指定字符、字符串

toLowerCase、toUpperCase

返回当前字符串的大写小写格式(可指定编码)

substring

返回字符串截取出的字串

判断字符串

contains(String other)

判断字符串时候包含指定字符串

startWith,endsWith

判断字符串是否以指定字符串开始、结束(判断前缀时可指定判断起始位置)

matches

判断字符串是否匹配正则

get* 、toCharArray

将该对象的 char[] 复制到 byte[](可指定编码) 、 char[] 中,或返回字符数组。

join (CharSequence delimiter, CharSequence… elements)

使用指定字符串 delimiter 对 多个 elements 进行连接

split

将字符串以指定规则分割为字符数组,可指定分割次数

intern()

本地方法,一般面试中会有题目 用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后 返回引用。 字符串有两种情况进入常量池:

  • 使用”“包裹的字符串会进入常量池
  • 在字符串上调用 intern()

copyValueOf、 valueOf

返回使用基本数据类型构造的字符串

hashCode 方法

该方法使用属性 hash 字段对 hashCode 进行了缓存,提高了效率。

equals*

判断两个 String类的实例 内容是否相同


资料

Java– String源码分析
为什么 String hashCode 方法选择数字31作为乘子
忽略大小写比较器 CaseInsensitiveComparator 为什么比较大写还要比较小写