字符串API
String是不可变对象
- java.lang.String使用了final修饰,不能被继承
- 字符串底层封装了字符数组及针对字符数组的操作算法
- 字符串一旦创建,对象永远无法改变,但字符串引用可以重新赋值
- java字符串中任何一个字符对应16位的定长Unicode编码
String常量池
Java为了提高性能,静态字符串在常量池中创建,并尽量使用同一个对象,重用静态字符串
/**
* 字符串常量池是JVM在堆内存中专门为了字符串提供的一段空间,用于缓存所有使用字面量形式
* 创建的字符串对象,当再次使用相同的字面量创建字符串时会直接重用常量池中的对象而不会再次
* 创建对象减少内存开销。
*/
public class StringDemo {
public static void main(String[] args) {
String s1 = "123abc";
System.out.println("s1:"+s1);
//s2字面量与s1相同,因此重用了上面s1创建的字符串对象
String s2 = "123abc";
System.out.println("s2:"+s2);
System.out.println(s1==s2);//s1==s2为true,说明保存的地址一样,使用同一个对象
String s3 = new String("123abc");
System.out.println("s3"+s3);
System.out.println(s2==s3);//为false,new很强制,一定创建新对象
System.out.println(s2.equals(s3));//true,equals仅比较内容是否相同
s1 = s1 + "!";//由于字符串是不变对象,修改内容就会创建新的对象
System.out.println("s1:"+s1);
System.out.println(s1==s2);//false
/*
编译器有一个特性:
当编译器在编译一段代码时发现一个计算表达式可以在编译期间确定结果时就会进行计算,并将结果编译到class文件中。
这样一来虚拟机运行该程序时就不必每次都进行计算了。
下面的代码会被编译器改为:
String s4 = "123abc";
*/
String s4 = "123"+"abc";
System.out.println("s4:"+s4);
System.out.println(s4==s2);//true
String s = "123";
String s5 = s + "abc";
System.out.println("s5:"+s5);
System.out.println(s5==s2);//false
}
}
/**
* int length()
* 获取当前字符串的长度(字符的个数)
*/
public class LengthDemo {
public static void main(String[] args) {
String str = "我爱java!";
int len = str.length();
System.out.println("len:"+len);
}
}
/**
* int indexOf(String str)
* 返回给定字符串在当前字符串的位置,如果当前字符串不包含给定内容则返回值为-1
*/
public class IndexOfDemo {
public static void main(String[] args) {
// 0123456789012345
String str = "thinking in java";
int index = str.indexOf("in");//检索str中第一次出现in的位置
System.out.println(index);//2
//重载的indexOf方法可以从指定位置开始检索第一次出现指定字符串的位置
index = str.indexOf("in",2);//从下标2处开始寻找第一次出现in的位置
System.out.println(index);//2
index = str.indexOf("in",3);//从下标3处开始寻找第一次出现in的位置
System.out.println(index);//5
//检索最后一次出现给定字符串的位置
index = str.lastIndexOf("in");
System.out.println(index);//9
}
}
/**
* String substring(int start,int end)
* 截取指定范围内的字符串。两个参数分别是范围对应的下标。
* 注:在JAVA API中通常使用两个数字表示范围时都是"含头不含尾"的。
*/
public class SubstringDemo {
public static void main(String[] args) {
// 01234567890
String host = "www.tedu.cn";
String sub = host.substring(4,8);
System.out.println(sub);
//重载的substring传入一个参数为从指定位置截取到字符串末尾
String sub1 = host.substring(4);
System.out.println(sub1);
}
}
public class Test {
public static void main(String[] args) {
String s1 = getHostName("www.tedu.cn");
String s2 = getHostName("http://www.tarena.com");
String s3 = getHostName("doc.canglaoshi.com.cn");
System.out.println("s1:"+s1);//s1:tedu
System.out.println("s2:"+s2);//s2:tarena
System.out.println("s3:"+s3);//s3:canglaoshi
}
/**
* 获取给定的网址中的域名(地址中第一个"."到第二个"."之间的内容)
*/
public static String getHostName(String address){
//地址中第一个"."之后第一个字符的位置
int start = address.indexOf(".")+1;
//地址中第二个"."的位置
int end = address.indexOf(".",start);
return address.substring(start,end);
}
}
/**
* String trim()
* 去除字符串两边的空白字符
*/
public class TrimDemo {
public static void main(String[] args) {
// 左侧三个空格,右侧三个tab
String str = " Hello ";
System.out.println(str);// Hello
String trim = str.trim();
System.out.println(trim);//Hello
}
}
/**
* char charAt(int index)
* 获取指定位置上的字符
*/
public class charAtDemo {
public static void main(String[] args) {
// 0123456789012345
String str = "thinking in java";
char c = str.charAt(4);
System.out.println(c);//k
}
}
/**
* boolean startsWith(String str)
*判断字符串是否是以给定的字符串开始的
* boolean endsWith(String str)
* 判断字符串是否是以给定的字符串结尾的
*/
public class StartsWithDemo {
public static void main(String[] args) {
String str = "www.tedu.cn";
//判断str是否是以"wwww"开始的
boolean starts = str.startsWith("www");
System.out.println(starts);
//判断str是否是以"cn"结尾的
boolean ends = str.endsWith("cn");
System.out.println(ends);
}
}
/**
* String toLowerCase()
* 将当前字符串的英文部分转换为全小写
*
* String toUpperCase()
* 将当前字符串的英文部分转换为全大写
*/
public class ToUpperCaseDemo {
public static void main(String[] args) {
String str = "我爱Java";
System.out.println(str);
String upper = str.toUpperCase();
System.out.println(upper);//我爱JAVA
String lower = str.toLowerCase();
System.out.println(lower);/我爱java
}
}
public static void main(String[] args) {
String str = "好好学习java";
//基于给定的字符串内容进行修改
StringBuilder builder = new StringBuilder(str);
/*
好好学习java
好好学习java,就是为了找个好工作!
append:将给定内容追加到字符串末尾
*/
builder.append(",就是为了找个好工作!");
str = builder.toString();
System.out.println(str);
/*
好好学习java,就是为了找个好工作!
好好学习java,就是为了改变世界!
replace:替换当前字符串中的部分内容为指定的内容
*/
builder.replace(13,18,"改变世界");
System.out.println(builder.toString());
/*
好好学习java,就是为了找个好工作!
,就是为了改变世界!
delete:删除当前字符串中的部分内容
*/
builder.delete(0,8);
System.out.println(builder.toString());
/*
,就是为了改变世界!
活着,就是为了改变世界!
insert:将给定内容插入到指定位置
*/
builder.insert(0,"活着");
System.out.println(builder.toString());
/*
翻转字符串内容
*/
builder.reverse();
System.out.println(builder);//builder和builder.toString()一样
}
}
/**
* StringBuilder修改字符串性能很好
*/
public class StringBuilderDemo02 {
public static void main(String[] args) {
StringBuilder builder = new StringBuilder("a");
for (int i = 0; i <1000000 ; i++) {
builder.append("a");
}
System.out.println("执行完毕!");
}
}
注:StringBuilder和StringBuffer效果是一样的
- StringBuilder是非线程安全的,并发处理,性能稍快
- StringBuffer是线程安全的,同步处理的,性能稍慢