String的构造方法
String(): 创建内容为空的字符串对象
String(byte[] bytes):将指定的字节数组转换为字符串对象
String(char[] chars):将指定的字符数组转换为字符串对象
String(String str):创建指定内容的字符串对象
public class Demo1 {
public static void main(String[] args) {
/*
使用构造方法创建字符串对象
*/
//创建空的字符串
String str = new String();
System.out.println(str.hashCode());
//修改字符串的值
str += "haha";
//打印字符串对象的hashCode值,根据打印结果我们猜测,String应该是重写了hashCode方法
System.out.println(str.hashCode());
System.out.println(str);
//创建指定内容的字符串对象
String str2 = new String("hello");
System.out.println(str2);
//将指定的字节数组转换为字符串
byte[] bytes = {97,98,99,100};
String str3 = new String(bytes);
System.out.println(str3);
//将指定的字符数组转换为字符串
char[] chars = {'我','爱','学','习'};
String str4 = new String(chars);
System.out.println(str4);
/*
直接使用字面量创建字符串对象
*/
String str5 = "helloworld";
System.out.println(str5);
}
}
两种创建字符串对象的方式的区别
根据这幅图可得:
如果用字面量的方式,最多只会在常量池创建一个对象
如果使用构造方法的方式,最少会在堆中单独创建一个String对象
那么:创建的String对象是通过什么属性来引用的字符串呢
通过查看String类的源码:找到了该变量
private final char value[];
说明了字符串的底层就是一个字符数组
字符串对+的优化
public class Demo3 {
public static void main(String[] args) {
/*
创建了多少个对象
*/
String s1 = "hello";
String s2 = "world";
//当+左右两边都是字面量时,java会将+直接优化掉
String s4 = "hello" + "world";
}
}
常见方法-获取字符串信息
char charAt(int index):获取指定索引处的字符
int indexOf(char ch):获取指定字符串在字符串中第一次出现的索引 如果没有该字符,返回-1
int indexOf(char ch,int fromIndex):从指定索引处开始查询指定的字符串第一次出现的索引
int lastIndexOf(char ch):查询指定的字符在字符串中最后出现的索引 如果没有该字符,返回-1
int hashCode():获取当前对象的hashCode值
int length():获取字符串的长度
public class Demo4 {
public static void main(String[] args) {
String str = "hell o ";
//charAt方法
System.out.println(str.charAt(3));//l
//length方法
System.out.println(str.length());//5
//遍历字符串中的每一个字符
for (int i = 0; i < str.length(); i++) {
System.out.print(str.charAt(i) + " ");
}
System.out.println();
//indexOf方法
System.out.println(str.indexOf('l'));//2
System.out.println(str.lastIndexOf('l'));//3
System.out.println(str.indexOf('l',3));//3
//hashCode方法
/*
String类重写了hashCode方法
该方法的返回值与字符串的内容相关
几乎可以认为:内容相同的字符串的的hashCode值相等
*/
System.out.println(str.hashCode());
}
}
String判断相关的方法
boolean contains(String str):判断当前字符串中是否包含指定字符串
boolean endsWith(String str):判断当前字符串的内容是否以指定内容结尾
boolean startsWith(String str):判断当前字符串的内容是否以指定内容开头
boolean equals(String str):判断当前字符串与指定字符串的内容是否一致
boolean equalsIgnoreCase(String str):判断当前字符串与指定字符串的内容在忽略大小写时是否一致
boolean isEmpty():判断是否是空字符串
举例说明:
public class Demo1 {
public static void main(String[] args) {
String str = "helloworld";
System.out.println(str.contains("w"));//true
System.out.println(str.endsWith("world"));//true
System.out.println(str.startsWith("he"));//true
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = new String("HeLLo");
System.out.println(str1 == str2);//false
System.out.println(str1.equals(str2));//true
System.out.println(str1.equals(str3));//false
System.out.println(str1.equalsIgnoreCase(str3));//true
String str4 = "";
System.out.println(str4.isEmpty());
}
}
String修改值的相关方法
String replace(String oldStr, String newStr):将当前字符串中的oldStr子串替换为指定的newStr
String subString(int index):从当前字符串的index索引处到最后截取子串
String subString(int beginIndex, int endIndex):从当前字符串索引为beginIndex到endIndex-1 处,截取子串
String toUpperCase():将当前字符串的内容全部转换为大写
String toLowerCase():将当前字符串的内容全部转换为小写
注意:String的值是不能修改的。所以上面的每一个方法其实都是新建了一个String对象作为返回值,调用该方法的String的内容是没有改变的。
转换相关的方法
/String replace(String oldStr, String newStr):将当前字符串中的oldStr子串替换为指定的newStr
String subString(int index):从当前字符串的index索引处到最后截取子串
String subString(int beginIndex, int endIndex):从当前字符串索引为beginIndex到endIndex-1 处,截取子串
注意:取前不取后 截取到endIndex-1索引处
String toUpperCase():将当前字符串的内容全部转换为大写
String toLowerCase():将当前字符串的内容全部转换为小写
public class Demo2 {
public static void main(String[] args) {
String str = "I hate study hahahaha";
//将str中hate改为love
str = str.replace("hate", "love");//注意一定要接收返回值
System.out.println(str);
//截取str中最后的hahahaha
int index = str.indexOf("hahahaha");//获取hahahaha 在str中第一次出现的索引
str = str.substring(index);
System.out.println(str);
str = "I hate study hahahaha";
//截取str中的study
index = str.indexOf("s");
str = str.substring(index, index + 6);
System.out.println(str);
str = "I hate study hahahaha";
//将str内容全部转换为大写
str = str.toUpperCase();
System.out.println(str);
//将str内容全部转换为小写
str = str.toLowerCase();
System.out.println(str);
}
}
字符串和字符数组之间的转换
static String valueOf(几乎可以是所有的其他类型):将指定的参数转换为字符串
byte[] getBytes():将当前字符串转换为字节数组
char[] toCharArray():将当前字符串转换为字符数组
new String(byte[] bytes):将指定的字节数组转换为字符串
new String(char[] chars):将指定的字符数组转换为字符串
public class Demo3 {
public static void main(String[] args) {
boolean boo = false;
String str = String.valueOf(boo);
System.out.println(str);
String s = "你好世界haha";
//将s转换为字符数组
char[] chars = s.toCharArray();
System.out.println(Arrays.toString(chars));
//将该字符数组转换回字符串
s = String.valueOf(chars);
System.out.println(s);
String s2 = "hello世界";
//将s2转换为字节数组
byte[] bytes = s2.getBytes();
System.out.println(Arrays.toString(bytes));
//将该字节数组转换回字符串
s2 = new String(bytes);
System.out.println(s2);
}
}
StringBuilder 与 StringBuffer
这两个类的功能几乎是一致的,但是StringBuffer是线程安全的
多个线程访问一个方法:
有可能出现a线程在操作某个属性值的时候 b线程也来操作这个属性值
这种情况就可能会发生线程安全问题
具体的例子:
卖票:
a窗口 b窗口
如果总共只剩一张票,但是有两个客户同时去a/b窗口买票,可能会出现两个客户都买到票
这就是线程安全问题
如何解决线程安全问题:排队
如果一个类是线程安全的,说明如果有多个线程访问它的方法,需要排队,所以效率较低
如果一个类不是线程安全的,说明多个线程可以同时访问它的方法,效率提高,但是有安全问题
StringBuilder
是一个可变的字符串:这个字符串的内容是可以修改的。
new StringBuilder():创建一个内容为空的可变字符串
new StringBuilder(String str):创建一个指定内容的可变字符串
如果要经常修改字符串的值,我们建议不要使用String
因为如果使用String,则每修改一次就会创建一个新的String的对象,浪费内存空间
这种情况建议使用StringBuilder....
常用方法
append(几乎所有的类型):将指定的数据添加到当前字符串的末尾
insert(int index, 任意类型的数据):将指定数据添加到当前字符串的指定位置
delete(int start, int end):删除指定范围索引之间的子串
deleteCharAt(int index):删除指定索引处的字符
reverse():将内容反转
toString():将当前可变字符串转换为String类型
public class Demo2 {
public static void main(String[] args) {
String str = "我爱世界";
StringBuilder sb = new StringBuilder(str);
//向字符串的末尾添加内容 因为StringBuilder是可变字符串
//所以本质上就是修改了自己的内容 不需要去接收
sb.append(666);
System.out.println(sb);
//在我 与 爱之间添加 "very"
sb.insert(1, "very");
System.out.println(sb);
//删除最后的 666
sb.delete(8,11);
System.out.println(sb);
//将内容反转
sb.reverse();
System.out.println(sb);
/*
实际开发中大多数情况需要的字符串都是String
但是如果要对内容进行频繁的修改建议将String先转换成StringBuilder进行操作
操作完成之后再转换回String
*/
str = sb.toString();
System.out.println(str);
}
}