- String类:代表字符串。用"xxx"来表示。
- String是final类,不可被继承。
- 实现了Serializable接口,表示字符串可被序列化;实现Comparable:可比较大小。
- 字符串的数据存储在内部定义的*private final char value[]*数组中。
- String不可变性:对字符串重新赋值、连接、替换(replace)时,不能在原有的value赋值,需要重新指定内存区域
关于String的不可变性
public class StringTest {
//5.不可变性
@Test
public void test1(){
String s1 = "abc";//不用new,直接赋值的方式:字面量的定义方式
String s2 = "abc";
System.out.println(s1 == s2);//比较s1和s2的地址值,结果是true
/*
这里是栈中的s1和s2都指向字符串常量池中,是存储”abc“的同一个地址
相同内容(”abc“)不会重复存储
*/
s1 = "hello";
//5.1:此时s1的地址已经和s2不同,说明重新指定了内存区域
System.out.println(s1);//hello
System.out.println(s2);//abc
//5.2:说明s3在拼接前后地址变了
String s3 = "abc";
System.out.println(s2 == s3);//true
s3 += "def";//s3 == "abcdef"
System.out.println(s2 == s3);//false
System.out.println("*************");
//5.3:replace
String s4 = "abc";
System.out.println(s2 == s4);//true
String s5 = s4.replace("a", "d");
System.out.println(s2 == s5);//fasle
System.out.println("s4:" + s4 + ", s5: " + s5);//s4:abc, s5: dbc
}
}
通过字面量的方式给字符串赋值,此时字符串值声明在字符串常量池中。
字符串常量池中不会存储相同内容的字符串。
关于String的实例化方式
public class StringTest {
@Test
public void test2(){
//实例化方式1:字面量的方式
String s1 = "JAVAEE";
String s2 = "JAVAEE";
//方式2:new + 构造器
String s3 = new String("JAVAEE");
String s4 = new String("JAVAEE");
System.out.println(s1 == s2);//常量池中的同一个地址值:true
System.out.println(s1 == s3);//s3是new出来的结构,在堆中,地址肯定和常量池中的s1不一样:false
System.out.println(s3 == s4);//s3和s4都是new出来的,分别在堆中的不同地址:false
//但是此时s3、s4的char型数组value的地址与常量池中的"JAVAEE"地址相同
System.out.println("**********");
Person p1 = new Person(10, "wkm");
Person p2 = new Person(10, "wkm");
System.out.println(p1.name == p2.name);//true:这里是字面量的实例化方式,
//p1的name和p2的name都存储的是字符串常量池中“wkm”的地址
}
public class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
String的拼接
public class StringTest {
/*
字符串的拼接:
如果拼接的都是常量,返回值是常量池中的地址;
只要拼接的成员存在变量,相当于new出来的结构,返回的是堆空间地址;
拼接的字符串调用intern()方法,返回值是常量池中的地址
*/
@Test
public void test(){
String s1 = "hello";
String s2 = "world";
String s3 = "hello" + "world";
String s4 = s1 + "world";
String s5 = "hello" + s2;
String s6 = s1 + s2;
String s7 = (s1 + s2).intern();
System.out.println(s3 == s4);//false
System.out.println(s3 == s5);//false
System.out.println(s3 == s6);//false
System.out.println(s3 == s7);//true
}
JDK1.8:字符串常量池在方法区(具体实现:元空间)
String常用方法
常用方法1:
public void test1(){
String s1 = "abcdasfsa";
//1.String.length:返回字符串的长度(return的是value的length)
System.out.println(s1.length());//9
//2.String.charAt(int index):返回字符串中index的字符
System.out.println(s1.charAt(5));//s
//3.String.isEmpty():判断String是否为空字符串
System.out.println(s1.isEmpty());//false
System.out.println("".isEmpty());//true
//4.String.toLowerCase()和toUpperCase():将String所有字母转换为小写/大写
System.out.println(s1.toLowerCase());//abcdasfsa
System.out.println(s1.toUpperCase());//ABCDASFSA
//5.trim():返回字符串的副本,忽略前导空白和尾部空白
System.out.println(s1 == s1.trim());
System.out.println(" d dadsfasfdsa fd f ".trim());//d dadsfasfdsa fd f
//6.equals():比较字符串的内容是否相同
String s2 = "abc";
String s3 = new String("abc");
String s4 = "abc";
System.out.println(s2.equals(s3));//true
System.out.println(s2.equals(s4));//true
//7.equalsIgnoreCase():比较内容相同,忽略大小写
String s5 = "AbC";
System.out.println(s2.equalsIgnoreCase(s5));//true
//8.concat(String str):将str连接到调用此方法的字符串结尾
System.out.println(s5.concat(s2));//AbCabc
//9.compareTo(String str):比较两个字符串大小(返回ascii的差值/长度的差值)
System.out.println(s5.compareTo(s1));//-32
System.out.println(s2.compareTo(s4));//0,大小相同
/*
10.subString(int beginIndex):返回一个从此字符串的beginIndex开始截取的字符串
subString(int beginIndex, int endIndex):截取字符串的[beginIndex, endIndex)返回
*/
String s6 = "ABCDefgh";
System.out.println(s6.substring(3));//Defgh
System.out.println(s6.substring(2,4));//CD
}
常用方法2:
public void test2(){
//1.boolean endsWith(String suffix):判断字符串是否以suffix结尾
String s = "abcdef..";
System.out.println(s.endsWith(".."));//true
//2.boolean startsWith(String prefix):判断字符串是否以suffix开头
System.out.println(s.startsWith("abc"));//true
//3.boolean startsWith(String prefix, int toffset):判断该字符串从toffset起始的字串是否以指定的前缀prefix开始
System.out.println(s.startsWith("cdef..", 2));//true
//4.boolean contains(CharSequence s):判断字符串是否包含串s
System.out.println(s.contains("def"));//true
//5.int indexOf(String str):返回字符串中第一次出现str的索引(不存在就返回-1)
String s1 = "abcfgsdafger";
System.out.println(s1.indexOf("fg"));//3
//6.int indexOf(String str, int fromIndex):返回字符串中从fromIndex开始第一次出现str的索引
System.out.println(s1.indexOf("fg", 5));//8
//7.int lastIndexOf(String str):倒序搜索此字符串中首次出现str的索引
String s2 = "asdgkoapsgkpklxz";
System.out.println(s2.lastIndexOf("gk"));//9
//8.int lastIndexOf(String str, int fromIndex):从fromIndex开始,倒序搜索此字符串中首次出现str的索引
System.out.println(s2.lastIndexOf("gk", 8));//3
}
常用方法3:
public void test3() {
/*
1.String replace(char oldChar, char newChar)
将字符串中的oldChar字符替换为newChar
*/
String s1 = "abcabc";
System.out.println(s1.replace('a', 'e'));//ebcebc
/*
2.String replace(CharSequence target, CharSequence replacement)
将字符串中的target替换为replacement
*/
String s2 = "aaabbbcccddd";
System.out.println(s2.replace("aaa", "dddd"));//ddddbbbcccddd
/*
3.String replaceAll(String regex, String replacement)
用replacement替换字符串中用regex匹配到的子字符串*/
String str = "12hello34world5java7891mysql456";
String str1 = str.replaceAll("\\d+", ",");
System.out.println(str1);//,hello,world,java,mysql,
/*
4.String replaceFirst(String regex, String replacement)
替换首个匹配到的
*/
String s3 = "123adfs456bcx26sadfa5sadg";
System.out.println(s3.replaceAll("\\d+", ","));//,adfs,bcx,sadfa,sadg
System.out.println(s3.replaceFirst("\\d+", ","));//,adfs456bcx26sadfa5sadg
/*
5.boolean matches(String regex):判断字符串是否匹配regex
*/
String s4 = "123456";
System.out.println(s4.matches("\\d+"));//true
/*
6.切片:
String[] split(String regex)
将字符串按照regex切片,返会若干子字符串
String[] split(String regex, int limit)
拆分的结果不超过limit个,超过limit的就全部在最后一个元素中
*/
String s5 = "hello|world|wkm|abc";
String[] temp = s5.split("\\|");//以|切片
for(int i = 0; i < temp.length; i++)
System.out.println(temp[i]);//换行打印hello、world、wkm、abc
String[] temp1 = s5.split("\\|", 2);
for(int i = 0; i < temp1.length; i++)
System.out.println(temp1[i]);//换行打印hello、world|wkm|abc
}
String与其他类型的转换
1.基本数据类型、包装类
String --> 基本数据类型、包装类:parseXxx(str)
基本数据类型、包装类–> String :ValueOf(xxx)
2.与char[]
public void func2(){
//String与char[]转换
//1.String --> char[]:调用toCharArray()方法
String str = "123abc";
char[] charlist = str.toCharArray();
for(int i = 0;i < charlist.length;i++){
System.out.println(charlist[i]);
}//遍历charlist的每一个成员:1、2、3、a、b、c
//2.调用String构造器
char[] charlist2 = new char[]{'h', 'e', 'l', 'l', 'o'};
String str2 = new String(charlist2);
System.out.println(str2);//hello
}
与byte[]
public void func3(){
//String与byte[]转换
//1.String --> byte[]:调用getBytes()方法
String str1 = "abc564";
byte[] bytes = str1.getBytes();//使用默认的编码规则
System.out.println(Arrays.toString(bytes));
//[97, 98, 99, 53, 54, 52]
//2.byte[] --> String:构造器
String str2 = new String(bytes);
System.out.println(str2);//abc564
}
StringBuffer、StringBuilder
/*
String StringBuffer StringBuilder区别:
String:不可变性
StringBuffer:可变的字符序列、线程安全、效率低
StringBuilder:可变、线程不安全、效率高(jdk5.0新增)
*/
public void test1(){
StringBuffer strb1 = new StringBuffer(); // 此时底层创建的数组:char[] value = new char[16];
strb1.append("abc"); //通过append方法添加字符
System.out.println(strb1);
StringBuffer strb2 = new StringBuffer("123"); //底层char[]数组长度:"123".length + 16
System.out.println(strb2.length());//注意1:此时strb2的length值是3,不是16
/*
注意2:
如果append的字符大于16,就要对数组进行扩容:
查看StringBuffer的父类AbstractStringBuilder中的append方法源码
默认情况扩容至原数组容量的2倍+2,同时将原数组内容复制到新数组中
*/
}
开发过程中,使用指定参数的构造器避免再扩容:StringBuffer(int capacity)、StringBuilder(int capacity)
三者的执行效率:StringBuilder > StringBuffer >> String
StringBuffer方法
StringBuilder方法类似
/*
1.StringBuffer append(xxx):添加xxx,类型自选
2.StringBuffer delete(start, end):删除[start, end)的字符
3.StringBuffer replace(start, end, String xxx):用xxx替换[start, end)
4.StringBuffer insert(int index, xxx):将xxx向index处插入,xxx类型自选
5.StringBuffer reverse():逆向StringBuffer
6.public int indexOf(String str): 搜索首次出现str的索引
7.public String substring(int start, int end):返回[start, end)的字符串
8.public int length():长度
9.public char charAt(int n): 查找n处的char值
10.public void setCharAt(int index, char ch): 修改index处为ch
*/
public void test2(){
StringBuffer strb1 = new StringBuffer("abc");
strb1.append(1);
strb1.append('1');
System.out.println(strb1);//abc11
//strb1.delete(2, 4);//ab1
//strb1.replace(2,4, "hello");//abhello1
//strb1.insert(2, 22.9);//ab22.9c11
//strb1.reverse();
System.out.println(strb1);//11cba
int i = strb1.indexOf("11");
System.out.println(i);// 3
String temp = strb1.substring(2, 5);
System.out.println(temp);// c11
System.out.println(strb1.charAt(3)); // 1
strb1.setCharAt(4, '2');
System.out.println(strb1);// abc12
}