目录
String字符串
基本的存储空间概念
栈:基础的数据类型变量以及对象的引用
堆:存放new出来的对象
常量池:字符串常量
字符串常量不可变
底层原码中使用final修饰 char[] value来存储字符串的值。字符串常量是存在常量池
中,一旦声明,就不可以改变,同时常量池中不会存储相同内容的字符串,即s1与s2是相等的。
String s1 = "aaa";
s1 = "bbb";
System.out.println(s1);//bbb
String s1 = "123";
String s2 = "123";
System.out.println(s1==s2);//true
输出的s1的值是bbb,不是改变了么?注意这里的s1是引用对象,因此s1存在栈空间中,也就是s1与aaa并不存在同一内存空间中,只是中间连接了一条绳子将aaa指向了s1,现在这条绳子由bbb指向了s1,但是aaa其实还留在了常量池中,所以说字符串常量是不可改变的。
除此之外,String还实现了Serializable接口,表示字符串可以被序列化,还实现了Comparable接口表示字符串可以比较大小
null," "的区别
String s1 = null
String s2 = ""
- null代表的是
空对象
,并不是字符串,可以赋给任何对象,字符串中表示只是一个引用,还没有内存空间的分配 - “ ”表示引用已经指向了 一块内存空间了,是一个实际的东西,可以进行操作了,表示一个长度为0的字符串
数组转成字符串(String的构造)
-
String():构造一个空的字符串
-
String(byte[] arr): 将字节数组变为一个字符串
-
String(byte[] arr, int offset, int lengh): 将字节数组部分变为字符串
-
String(char[] arr): 将char字节数组变为字符串
-
String(char[] arr, int offset, int length): 将char字节数组部分变为字符串
-
String(String original): 字符串常量构建字符串
byte[]===>String
- 全部转换:转换所有byte数据
byte[] b = {97,98,99,100};
String str = new String(b);
System.out.println(str);//abcd
- 部分转换: 截取转换,超出索引,报出
StringIndexOutOfBoundsException
异常,通常Java中数组索引区间左开右闭的
byte[] b = {97,98,99,100};
String str = new String(b,1,3);
System.out.println(str);//bc
char[]转String等等一些数组转String的方式都和上述大同小异,这些都是对String方法使得构造
==与equals()的比较字符串是否相等
- == 比较的地址和内容都相等才相等
- equals()内容相等即是相等
理解上面两句:
String s1 = "123";①
String s2 = "123";②
String s3 = new String("123");③
System.out.println(s1==s2);//正确
System.out.println(s1==s3);//错误
只要明白了内存分布,判断不成问题。对于①,②来说,上面已经解释过了都在栈内存中,对于③来说,s3是对象存在Java堆中,s1,s2都是存在Java栈中,所以s1==s3是错误的!!!对于equals()就不一样了三者内容都是相等的。
练习一:
String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1==s2);//F
System.out.println(s1.equals(s2));//T
String s3 = new String("hello");
String s4 = "hello";
System.out.println(s3==s4);//F
System.out.println(s3.equals(s4));//T
String s5 = "hello";
String s6 = "hello";
System.out.println(s5==s6);//T
System.out.println(s5.equals(s6));//T
字符串的拼接
- 常量与常量的拼接还在常量池中
- 常量池不可有相同的常量
- 拼接的时候,只要存在变量都会存到堆中
- 调用intern()方法返回常量池里面的常量
String s1 = "hello";
String s2 = "world";
String s3 = "helloworld";
System.out.println(s3==(s1+s2));//F 变量的连接存在堆中不相等
System.out.println(s3==(s1+s2).intern());//T 获取的是值相等
System.out.println(s3.equals(s1+s2));//T 获取内容相等
System.out.println(s3=="hello" + "world");//T 常量与常量连接还在常量池中
System.out.println(s3.equals("hello"+"world"));//T 内容相等
字符串操作,常用方法
- equals方法比较两个字符串内容是否相等
- equalsIgnorecase忽略大小写比较两个对象是否相等
- contains是否包含字符串
- startsWith()是否以指定的字符串开头
- endsWIth()是否以指定的字符串结尾
- isEmpty()是否为空
String s1 = "abcde";
String s2 = "AbCde";
String s3 = "abcde";
//equals
System.out.println(s1.equals(s2));//t
System.out.println(s1.equals(s3));//f
//equalsIgnorecase
System.out.println(s1.equalsIgnoreCase(s2));//t
System.out.println(s1.equalsIgnoreCase(s3));//t
//是否包含指定字符串
System.out.println(s1.contains("bd"));//f
//是否以指定字符串开头
System.out.println(s1.startsWith("ab"));//t
System.out.println(s1.startsWith("cde",2));//
//是否以字符串结尾
System.out.println(s1.endsWith(s3));//t
//是否为空
System.out.println(s1.isEmpty());//false
获取的方法
-
length() : 获取长度
String str = "abcdeabca"; //长度 System.out.println(str.length());//9
-
charAt(int index) : 获取指定下标的字符
//获取第二个元素值 System.out.println(str.charAt(1));//b
-
indexOf(int ch) : 获取指定字符第一次出现的下标
//获取'a'第一次的索引值 System.out.println(str.indexOf('a'));//0
-
indexOf(int ch, int fromIndex) : 获取从指定下标开始,指定字符第一次出现的位置
//从第二个索引值开始,’a'出现的位置 System.out.println(str.indexOf('a',2));//5
-
indexOf(String str) : 获取指定字符串第一次出现的下标
//获取“bc”第一次出现的索引值 System.out.println(str.indexOf("bc"));//1
-
indexOf(String str,int fromIndex) : 获取指定下标开始,第一次获取指定字符串的下标
//从2开始索引“ab“第一次出现的索引值 System.out.println(str.indexOf("ab",2));//5
-
lastIndex(int ch) : 获取指定字符最后一次出现的下标
//获取‘a'最后一次存储的索引值 System.out.println(str.lastIndexOf('a'));//8
-
lastIndex(String str,int fromIndex) : 获取从指定下标开始,指定字符最后一次出现的下标
//获取'bc'最后一次出现的索引值 System.out.println(str.lastIndexOf("bc"));//6
-
substring(int start) : 从指定下标开始一直截取到末尾
//从索引1截取到末尾 String s1=str.substring(1); System.out.println(s1);//bcdeabca
-
substring(int start,int end) : 截取[start,end-1]范围
//"abcdeabca"---->"deab" String s2=str.substring(3,7); System.out.println(s2);//deab
注意:如果都找不到的话,返回-1
转换方法
-
byte[] getBytes() : 将字符串转换为字节数组
String string="小林学java"; //以默认编码进行编码(当前工具默认的是UTF-8) byte[] bys1=string.getBytes(); //[-27, -80, -113, -26, -98, -105, -27, -83, -90, 106, 97, 118, 97] System.out.println(Arrays.toString(bys1));
-
byte[] getBytes(String charset) : 通过指定的字符集,将字符串转换为字节数组
byte[] bys2=string.getBytes("gbk"); //[-48, -95, -63, -42, -47, -89, 106, 97, 118, 97] System.out.println(Arrays.toString(bys2));
-
char[] toCharArray() : 将字符串转换为字符数组
char[] cs=string.toCharArray();//[小, 林, 学, j, a, v, a] System.out.println(Arrays.toString(cs));
-
static valueOf(char[] chs) : 将字符数组转换成字符串
char[] b={'a','b','c'}; //abc System.err.println(String.valueOf(b));
-
static valueOf(int num) : 将int数据转换成字符串
//100 System.out.println(String.valueOf(100));
-
static valueOf(Object obj) : 将任意引用类型转换成字符串
-
toLowerCase() : 转成小写
String i="ASDF"; System.out.println(i.toLowerCase());
-
toUpperCase() : 转成大写
String x="adgg"; System.out.println(x.toUpperCase());
-
concat(String str) : 字符串连接
//小林学javaadgg System.out.println(string.concat(x));
-
trim() : 去除两边空格
//jjjj bbbb String ss=" jjjj bbbb "; System.out.println(ss.trim());
比较和替换
-
replace(char old,char new) : 将old替换成new字符
String s="abc中国abc"; //b替换成B String s1=s.replace('b', 'B'); System.out.println(s1);//aBc中国aBc
-
replace(String old,String new) : 将old替换成new字符串
//“中国“替换成”CHINA“ String s2=s.replace("中国", "CHINA"); System.out.println(s2);//abcCHINAabc
-
String replace(CharSequence target, CharSequence replacement) : 替换指定的字符序列
-
int compareTo(String str) : 字典比较
这里的比较可看的是开头的字符,如果相等则往后推,不相等就用前者的值减去后者的值。
如果后者包含前者,则结果即为后者多出来的字符个数的负数。
String str1="abc"; String str2="cbc"; String str3="abcde"; System.out.println(str1.compareTo(str2));//-2 System.out.println(str1.compareTo(str3));//-2
-
int compareToIgnoreCase(String str) : 忽略大小写比较
正则表达式的方法
-
boolean matches(String regex) : 字符串是否匹配指定的正则表达式
//校验手机号 String regex="1[3568]\\d{9}"; return s.matches(regex);
-
String[] split(String regex) : 通过正则表达式将字符串分割成字符串数组
String s="ab1cd23ef456g"; String[] strs=s.split("\\d+"); System.out.println(Arrays.toString(strs));//[ab, cd, ef, g]
-
String[] split(String regex,int limit) : 分割,但不超过limit个,超出不分割
String s2="a bc de fg"; String[] strs2=s2.split("\\s+",3); System.out.println(Arrays.toString(strs2));//[a, bc, de fg]
-
String replaceAll(String regex,String replacement) : 将符合规则的字符串替换成指定的字符串
String s="ab1cd23ef456g";//每一组数字替换为NUM"abNUMcdNUMefNUMg" String s2=s.replaceAll("\\d+", "NUM"); System.out.println(s2);//abNUMcdNUMefNUMg
-
String replaceFirst(String regex, String replacement):将符合规则的第一个字符串替换成指定的字符串
String s3=s.replaceFirst("\\d+", "NUM"); System.out.println(s3);//abNUMcd23ef456g
StringBuilder
-
构造方法
- StringBuilder() : 以默认容量(16)创建空的字符串缓冲区对象
- StringBuilder(int capacity) : 已指定容量创建空StringBuilder对象
- StringBuilder(String str) : 以指定字符串创建StringBuilder对象
-
成员方法
-
添加 :StringBuilder append(int value) : 追加。追加任意类型数据
insert(int offset,String str) : 在指定位置插入指定数据
-
删除 :deleteCharAt(int index) : 在指定位置处删除对应的元素
delete(int start,int end) : 删除start~end-1范围内的元素
-
修改 :setCharAt(int n,char ch) : 指定下标位置的元素设置为指定的值
replace(int start,int end,String str) : 将指定范围的元素替换成指定的字符串
-
查询 :charAt(int n) :获取指定下标的元素
-
int capacity() :获取容量capacity()
int length() :获取长度
-
反转:reverse() : 反转元素
-
截取:String substring(int start) : 截取指定位置到末尾
String substring(int start,int end) : 截取[start,end-1]范围
-
string、StringBuffer、StringBuilder的对比
String:不可变的字符序列
StringBuffer:可变的字符序列;线程安全,效率低
StringBuilder:可变的字符序列;线程不安全,效率高
注意:三者的底层都使用char[]存储