一、String类介绍
String 类代表字符串。Java中所有的字符串字面值都作为String类的实例实现。
字符串:有多个字符组成的字符序列。
字符串也有索引,从0开始
字符串是常量,它们的值在创建之后不能改变。
String s = "hello";
s = "world" + "java";
System.out.println(s); //worldjava
/*我们在进行上述编码时Sring s在栈内存,而"hello"是一个常量,会被存入方法区的常量池中,其地址值假设为0x001,String s = "hello"是把"hello"的地址值0x001赋给s
s = "world" + "java"中我们在定义(输入)"world"时,程序会在常量池中寻找是否有已创建的"world"的常量,如果没有就会在常量池中重新创建"world"的常量,并赋予其地址值--我们假设为0x002;
"java"也是一样过程,常量池中没有就会重新创建"java"的常量,并赋予其地址值--我们假设为0x003
我们在用+将"world" 和 "java"拼成"worldjava"后,会再次进行判断,如果常量池中没有就会重新创建"worldjava"的常量,并赋予其地址值--我们假设为0x004,并将其地址值0x004再次赋给s,s的地址值不在是0x001。
所以我们在输出时得到的是worldjava
而方法区常量池中的"hello"、 "world"、"java"并未发生改变,只有s代表的地址值发生了改变。
*/
String s2 = "eee"+"ddd"+"ccc"+"aaa";
//常量池中有多少个常量? "eee"、"ddd"、"ccc"、"aaa"、"eeeddd"、"eeedddccc"、"eeedddcccaaa"六个
String s = new String("hello");
String s2 = "hello";
这两种定义方式有什么区别?
/*
使用new创建对象时,程序会在堆内存开辟一个空间其地址值假设为0x001,这个空间存放的是"hello"在方法区常量池中的地址值--假设为0x002,s代表的是堆内存空间的地址值0x001
而下一种定义方式因为常量池中已经有"hello"的常量,s2代表的是常量池中"hello"的地址值0x002
*/
System.out.println(s==s2); //false
//在比较s与s2代表的字符串是否相等时我们需要用equals()方法
System.out.println(s.equals(s2)); //true
//String类重写了父类object中的equals方法,不在比较两个字符串的地址值,二是比较其内容
[外链图片转存失败(img-gP56QTR2-1562549392768)(C:\Users\Administrator\Desktop\上课资料\正常进度上课班资料\20190629-JavaSE-课件\字符串内存图\字符串一旦被创建就不能被改变深入解析图解.bmp)]
[外链图片转存失败(img-fLsDSu7y-1562549392770)(C:\Users\Administrator\Desktop\上课资料\正常进度上课班资料\20190629-JavaSE-课件\字符串内存图\字符串创建对象的面试题图解.bmp)]
因为String对象是不可变的,所以可以共享。
例如:
String str = "abc";
char data[] = {'a','b','c'};
String str = new String(char);
"abc".substring(2,3);//"abc"就是String类的实例对象,可以使用String类的方法
Java语言支持字符串串联符号+以及将其他对象转换为字符串。
二、String类的构造方法
A.常见构造方法(把其他数据类型转为String类)
public String() //空参构造 使用new创建对象时使用
String str = new String();//初始化一个新建的String类对象,使其表示一个空字符序列
public String(byte[] bytes) //把字节数组转换成字符串
byte[] bytes = {97,98,99,100};
String s = new String(bytes);
System.out.println(s);//abcd 字节数组转为字符串
public String(byte[] bytes,int index,int length) //把字节数组一部分转换为字符串(index表示从第几个索引开始(包含该索引),length表示要转的长度)
public String(bytes,0,2) //ab
public String(char[] value) //把一个字符数组转成字符串
char[] chars = {'a','b',100,'你','好','吗'};
String s2 = new String(chars);
System.out.println(s2); //abd你好吗
public String(char[] value,int offset,int count) //从offset索引处开始,将count个字符转为字符串
String s3 = new String(chars,chars.length-3,3);
System.out.println(s3); //你好吗
public String(String original) //把字符串常量转化为字符串
B.常用判断方法
public boolean equals(Object obj) //比较字符串的内容是否相通,区分大小写
public boolean equalsIgnoreCase(String str) //比较字符串的内容是否相通,不区分大小写
public boolean contains(String str) //contains=>包含 判断字符串中是否包含传递进来的字符串
public boolean startsWith(String str) //判断字符转是否以传进来的字符串开头
public boolean endth(String str) //判断字符转是否以传进来的字符串结尾
public boolean isEmpty () //判断字符转是否为空串
C.常用获取方法
length() //获取字符串长度的方法
System.out.println("abcdef".length()); //6
indexOf() //获取字符串中指定int/char/String数据第一次出现的索引,未找到输出-1
System.out.println("abcdef".indexOf("c")); //2
System.out.println("abcdef".indexOf("h")); //-1
//indexOf(需要寻找的指定数据,从第几个索引(包含该索引)开始)
//lastIndexOf() 字符串中指定数据从后往前找,第一次出现的索引
//lastIndexOf(需要寻找的指定数据,从第几个索引(包含该索引)开始)
public String substring() //获取从指定索引字符处(包含该字符)截取到指定索引字符(不包含该字符)的字符串 单个参数则会截取到最后 返回类型为String类型
String str = "abcdefg".substring(2,5);
System.out.println(str); //cde
charAt(字符串索引) //从字符串的中截取指定索引处的字符 返回类型为字符
D.常用转换方法
public byte[] getBytes() //把字符串转换为字节数组
String str = "abcde";
byte[] b = str.getBytes();
System.out.println(Arrays.toString(b)); //abcde被转换为字节数组
public char[] toCharArray() //把字符串转化为字符数组
String str2 = "七月的风八月的雨";
char[] c = str2.toCharArray(); //返回的就是字符数组
public static String valueOf() //把基本数据类型转为字符串
//还有一种简单的方法将基本数据类型转为字符串
//创建一个空串String str = 其他数据类型+""; 使用+拼串
public static String valueOf(字符数组char[] chars,起始索引,转换长度)
public String concat(String str) //拼串 使用+拼串大量占用内存 concat则不会
String str = "ab".concat("cd").concat("ef").concat("gh");
System.out.println(str); //abcdefgh
E、其他方法
//toString()方法
返回该对象的字符串表示。
打印一个对象名时默认调用toString()。
未被调用时会输出该对象的地址值
String类重写了toString方法,获取的是字符串的内容
public String toLowerCase() //转小写
System.out.println("ABCD".toLowerCase()); //abcd
public String toUpperCase() //转大写
System.out.println("abcd".toUpperCase()); //ABCD
public String replace(char old,char new) //将指定字符进行互换
public String replace(String old,String new) //将指定字符串进行互换
System.out.println("去你妈".replace("妈","*")); //去你*
public String trim() //去除两端空格
String s = " asd ".trim;
System.out.println(s); //asd
三、StringBuffer和StringBuilder
A.StringBuffer
String 是一个长度固定的字符序列,一旦定义就不能改变。
StringBuffer是线程安全的一个可变序列。 是一个存储字符的容器,可以不断地追加数据,长度可变。
1.构造方法
StringBuffer() //空参构造 构造一个其中不带字符的字符串缓冲区,其初始容量为16个字符。超过了默认容量可以自动扩充
new StringBuffer("asd"); //有参构造 可以提前往里面放入字符串
StringBuffer sb = new StringBuffer();
2.常用方法
sb.capacity(); //获取容器的容量 默认是16
sb.length(); //获取长度,实际装了多少个字符 默认无字符时长度为0
sb.append(); //往容器中追加(几乎任何数据类型)内容(默认放到原来字符串的后面),返回的还是原来的容器
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = sb.append("abc");
System.out.println(sb2==sb); //true sb代表原容器的地址值,sb2代表装了"abc"后的地址值 还是同一个容器,其所代表的地址值也就未曾改变
sb.append("asd").append("we").append("qrtew");
sb.insert(offset: ,str:" ");
sb.insert(offset:0,str:"皮皮虾我们走"); //在指定位置(该索引前一位)插入数据
sb.delete(int start,int end)
sb.delete(2,5) //删除从指定起始索引(不包含该字符)开始到指定结束索引(不包含该字符)的那一段内容
sb.deleteCharAt(int index)
sb.deleteCharAt(0) //根据索引删除单个字符
sb.indexOf("都") //检索指定字符在容器中第一次出现的索引
sb.lastIndexOf("都") //检索指定字符在容器中最后一次出现的索引
sb.replace(起始索引,结束索引,替换内容) //将从起始索引开始到结束索引(不包含该字符)的那段内容替换为新的内容,返回的还是StringBuffer类型
sb.reverse(); //将容器中数据反转,返回的还是原来的类型
sb.substring(); //获取容器中的一段内容
sb.substring(2,4) //获取从指定开始索引(包含)开始到指定结束索引(不包含)的内容,返回String类型,原容器内容没有发生改变
3.String和StringBuffer的相互转换
//String==>StringBuffer
String str = "abc";
new StringBuffer().append(str);
new StringBuffer(str);
new StringBuffer().insert(0,str);
//StringBuffer==>String
StringBuffer sb = new StringBuffer("abc");
sb.toString();
sb.substring(0);
B.StringBuilder
StringBuffer的一个简易替换,在单线程情况下StringBuilder效率更高,优先使用;多线程时线程不安全。
StringBuilder与StringBuffer的方法一样