字符序列
多个字符按照一定的顺序组成的列表就叫作字符序列
-
String
字符串 -
StringBuffer
字符串缓冲区,是线程安全的 -
StringBuilder
字符串构造器,非线程安全的 -
CharBuffer
字符缓冲区
String
多个字符按照一定的顺序组成字符序列,默认值是null
(字符串不可变特性)字符串的内容是不会发生改变的,它的对象在创建后不能被更改
原因:字符串内容存储的元素是final修饰的,不可变
-
字符串常量池不存重复的值。
jdk 1.8及之前版本:
private final char value[]; // 用于存放内容,字符串底层其实就是一个字符数组 private int hash; // 用来存放hash值
jdk1.9及以后版本:
private final byte value[]; // 用于存放内容,1.9之后使用字节数组存储 private int hash; // 用来存放hash值 private byte coder; // 编码方式,0 -LATIN1, 1 - UTF-16
> jdk 1.8之前字符串用char储存,jdk 1.9之后字符串用byte储存,为什么要这么改呢?
主要是为了节约
String
占用的内存,占用内存少引发另外一个好处就是减少GC
次数。
众所周知,在大多数 Java
程序的堆里, String
占用的空间最大,并且绝大多数 String
只有 Latin-1
字符,这些 Latin-1
字符只需要1个字节
就够了。 JDK9
之前, JVM
因为 String
使用 char
数组存储,每个 char
占2个字节
,所以即使字符串只需要1字节/字符,它也要按照2字节/字符进行分配,浪费了一半的内存空间。 JDK9
是怎么解决这个问题的呢?一个字符串出来的时候判断,它是不是只有 Latin-1
字符,如果是,就按照1字节/字符
的规格进行分配内存,如果不是,就按照2字节/字符
的规格进行分配( UTF-16 编码
),提高了内存使用率。 为什么用 UTF-16 而不用 UTF-8 呢,这就要从这两个字符集的设计说起了. UTF-8
实际上是对空间利用效率最高的编码集,它是不定长的,可以最大限度利用内存和 网络。但是这种编码集只能用于传输和存储,并不适合拿来做 String
的底层实现。因为 String
有随机访问的方法
,所谓随机访问,就是 charAt
、 subString
这种方法。如果字符串中的每个字符占用的内存是不定长的,那么进行随机访问的时候,就需要从头开始数每个字符的长度,才能找到你想要的字符。 使用 UTF-16
编码将它们表示并存储为每个字符2个字节。
字符串的声明
//字面量 String 变量名 = "初始值"; //构造创建对象 String 变量名 = new String ("初始值");
例:
//字符串数组 char[] c ={'a', 'b' ,'c'}; String s4 = new String(c); System.out.println(s4); //字节数组 byte[] bytes ={97,98,99,100}; String s5 = new String(bytes); System.out.println(s5);
字符串在内存中的创建
1.当使用双引号直接赋值时,系统会检查该字符串在字符串常量池(串池)中是否存在。不存在,创建新的,存在,复用
2.new
对象时在堆里面,字符串不会复用
常见方法
1.比较
-
==
-
比较基本数据类型,比较的是数据值
-
比较引用数据类型,比较的是地址值
String s1 = "abc"; String s2 = "abc"; System.out.println(s1==s2);//true String s1 = new String("abc");//堆里面的地址 String s2 = "abc";//串池地址值 System.out.println(s1==s2);//false
-
-
equals/
equalsIgnoreCase
String s1 = new String("abc"); String s2 = "abc"; System.out.println(s1==s2);//false //比较字符串内容 boolean result = s1.equals(s2); System.out.println(result);//true String s3 = "Abc"; boolean result1 = s1.equals(s3); System.out.println(result1);//false //忽略大小写 boolean result2 = s2.equalsIgnoreCase(s3); System.out.println(result1);//true Scanner sc =new Scanner(System.in); System.out.println("请输入一个字符串abc"); String str = sc.next(); System.out.println(str == s2);//false
2.构造方法
在声明字符串时,使用字符串对象的方式来声明时使用的方法。
方法名 | 描述 |
---|---|
String( ) | 初始化新创建的 String 对象,使其表示空字符序列 |
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组来构造新的 String |
*String(byte[] bytes, Charset charset)* | 构造一个新的 String 用指定的字节的数组解码 ``charset |
*String(byte[] bytes, String charsetName)* | 构造一个新的 String 用指定的字节的数组解码 charsetName |
String(char[] value) | 构造一个新的 String 由指定的字符的数组构成 |
String(String original) | 初始化新创建的 String 对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本 |
String(StringBuffer buffer) | 分配一个新的字符串,其中包含当前包含在字符串缓冲区参数中的字符序列 |
String(StringBuilder builder) | 分配一个新的字符串,其中包含当前包含在字符串构建器参数中的字符序列 |
3.实例方法
方法名 | 返回值类型 | 描述 |
---|---|---|
charAt(int index) | char | 返回指定索引处的字符 |
subSequence(int beginIndex, int endIndex) | String | 返回作为该序列的子序列的字符序列。(从某一位置到某一位置,[ )包含左,不包含右。) |
subSequence(int beginIndex) | String | 返回一个字符串,该字符串是该字符串的子字符串。(从某一位置开始, [ ) ) |
equals(Object obj) | 将此字符串与指定对象进行比较。 | |
equalsIgnoreCase(String anotherString) | String | 将此字符串与另一个字符串进行比较,忽略大小写。 |
compareT0(String anotherString) | int | 按字典顺序比较两个字符串。( > string 大 , < 0 anotherString 大 , = 0 一样大) |
compareToIgnoreCase(String str) | int | 按字典顺序比较两个字符串,忽略大小写差异。 |
length() | int | 返回当前字符串的长度 |
isBlank() | boolean | 如果字符串为空或仅包含空格代码点,则返回 true,否则返回 false。 |
isEmpty() | boolean | 当且仅当 length() 为 0 时返回 true。 |
toString() | String | 这个对象(已经是一个字符串了!) |
toCharArray() | char[] | 将此字符串转换为新的字符数组。 |
trim() | String | 返回一个新字符串,去除当前字符串的前导和尾部空格 |
strip() | String | 返回一个字符串,其值为该字符串,并删除所有前导和尾随空格。 |
stripIndent() | String | 返回一个字符串,其值为该字符串,并从每行的开头和结尾删除了附带的空格。(去除缩进) |
stripLeading() | String | 返回一个字符串,其值为该字符串,并删除所有前导空格 |
stripTrailing() | String | 返回一个字符串,其值为该字符串,并删除所有结尾空格。 |
concat(String str) | String | 将指定字符串连接到该字符串的末尾 |
contains(CharSequence s) | Boolean | 当且仅当此字符串包含指定的 char 值序列时返回 true。 |
startsWith(String prefix) | boolean | 判断当前字符串是否以指定的前缀开头 |
startsWith(String prefix,int toffs) | boolean | 测试此字符串中从指定索引开始的子字符串是否以指定前缀开头。 |
endsWith(String suffix) | boolean | 判断当前字符串是否以指定的后缀结尾 |
indexOf(String str) | int | 返回第一次出现指定字符串的索引位置,从头开始搜索 |
indexOf(String str,int fromIndex) | int | 返回此字符串中指定子字符串第一次出现的索引,从指定索引开始。 |
lastIndexOf(String str) | int | 返回最后一次出现指定字符串的索引位置,从末尾开始搜索 |
indent(int n) | int | 根据n的值调整该字符串每行的缩进,并标准化行终止符。 |
split(String regex) | String[] | 根据指定的正则表达式将当前字符串拆分为子字符串数组 |
split(String regex,int limit) | String[] | 围绕给定正则表达式的匹配项拆分此字符串。(limit 最多分割几个) |
join(CharSequence delimiter, CharSequence... elements) | String | (static)使用指定的分隔符将多个元素连接为一个字符串 |
repeat(int count) | String | 返回一个字符串,其值是该字符串重复 count 次的串联。 |
replace(char oldChar, char newChar) | String | 返回用 newChar 替换该字符串中所有出现的 oldChar 所得到的字符串。 |
replace(CharSequence target,CharSequence relacement) | String | 将此字符串中与文字目标序列匹配的每个子字符串替换为指定的文字替换序列。 |
replaceAll(String regex,String relacement) | String | 将此字符串中与给定正则表达式匹配的每个子字符串替换为给定替换。 |
replaceFirst(String regex,String relacement) | String | 将此字符串中与给定正则表达式匹配的每个子字符串替换为给定替换。 |
format(String format,Object ....args) | static String | (static)使用指定的格式字符串和参数返回格式化字符串。 |
format(Local l,String format,Object ....args) | static String | 使用指定的区域设置、格式字符串和参数返回格式化字符串 |
formatted(String format) | String | 使用此字符串作为格式字符串和提供的参数进行格式化 |
intern() | String | 如果字符串在常量池中有就返回常量池的对象,如果没有就将对象放回常量池中。 |
codePointAt(int index) | int | 返回指定索引处的Unicode代码点 |
codePointCount(int beginIndex, int endIndex) | int | 返回指定范围内的Unicode代码点数量 |
toLowerCase() | String | 返回一个新字符串,将所有字符转换为小写字母 |
toUpperCase() | String | 返回一个新字符串,将所有字符转换为大写字母 |
matches(String regex) | boolean | 判断当前字符串是否与指定的正则表达式匹配 |