字符串
字符串的特点
字符串String类型本身是final声明的,意味着我们不能继承String
字符串是不可变对象,一旦修改,就会产生新的对象
String对象内部是用字符数组进行保存的
- JDK1.9之前 char[] 数组
- JDK1.9之后 byte[] 数组
- “abc” 等价于 char[] data = {'a', 'b', 'c'}
char[] 数组也是final修饰的,这意味着这个数组不可变
通过字符串常量池来保存很多常量对象
JDK1.6及以前:方法区
JDK1.7:堆
JDK8:元空间
String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); // 内存中只有一个"abc"对象被创建,同时被s1和s2共享
字符串的拼接
原则
常量 + 常量:结果在常量池
常量 + 变量 或 变量 + 变量:结果在堆
concat方法拼接,哪怕是两个常量拼接,结果也是在堆
@Test public void test06(){ String s1 = "hello"; String s2 = "world"; String s3 = "helloworld"; String s4 = (s1 + "world").intern();//把拼接的结果放到常量池中 String s5 = (s1 + s2).intern(); System.out.println(s3 == s4);//true System.out.println(s3 == s5);//true } @Test public void test05(){ final String s1 = "hello"; final String s2 = "world"; String s3 = "helloworld"; String s4 = s1 + "world";//s4字符串内容也helloworld,s1是常量,"world"常量,常量+ 常量 结果在常量池中 String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是常量,常量+ 常量 结果在常量池中 String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果 System.out.println(s3 == s4);//true System.out.println(s3 == s5);//true System.out.println(s3 == s6);//true } @Test public void test04(){ String s1 = "hello"; String s2 = "world"; String s3 = "helloworld"; String s4 = s1 + "world";//s4字符串内容也helloworld,s1是变量,"world"常量,变量 + 常量的结果在堆中 String s5 = s1 + s2;//s5字符串内容也helloworld,s1和s2都是变量,变量 + 变量的结果在堆中 String s6 = "hello" + "world";//常量+ 常量 结果在常量池中,因为编译期间就可以确定结果 System.out.println(s3 == s4);//false System.out.println(s3 == s5);//false System.out.println(s3 == s6);//true }
public class TestString { public static void main(String[] args) { String str = "hello"; String str2 = "world"; String str3 ="helloworld"; String str4 = "hello".concat("world"); String str5 = "hello"+"world"; System.out.println(str3 == str4);//false System.out.println(str3 == str5);//true } }
equals 与 ==
- == 比较的是对象的地址
- equals比较的是对象的内容, 因为String类型重写了equals方法
字符串的常用方法
boolean isEmpty():字符串是否为空
int length():返回字符串的长度
String concat(xx):拼接,等价于+
boolean equals(Object obj):比较字符串是否相等,区分大小写
String trim():去掉字符串前后空白符
boolean contains(xx):是否包含xx
int indexOf(xx):从前往后找当前字符串中xx,即如果有返回第一次出现的下标,要是没有返回-1
int lastIndexOf(xx):从后往前找当前字符串中xx,即如果有返回最后一次出现的下标,要是没有返回-1
String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串
char charAt(index):返回[index]位置的字符
char[] toCharArray(): 将此字符串转换为一个新的字符数组返回
byte[] getBytes(字符编码方式):按照指定的编码方式进行编码
boolean startsWith(xx):是否以xx开头
boolean endsWith(xx):是否以xx结尾
boolean matchs(正则表达式):判断当前字符串是否匹配某个正则表达式
String replace(xx,xx):不支持正则
String replaceFirst(正则,value):替换第一个匹配部分
String repalceAll(正则, value):替换所有匹配部分
String[] split(正则):按照某种规则进行拆分
正则匹配
[abc]:`a`、`b` 或 `c`
[^abc]:任何字符,除了 `a`、`b` 或 `c`
[a-zA-Z]:`a` 到 `z` 或 `A` 到 `Z`
.: 任何字符
\d: 数字
\D: 非数字
\s:空白字符
\S:非空白字符
`\w`:单词字符
`\W`:非单词字符
`^`:行的开头
`$`:行的结尾
X?:一次或一次也没有
X*:零次或多次
X+:一次或多次
X{n}:恰好n次
X{n,}:至少n次
可变字符序列
StringBuffer 与 StringBuilder
- StringBuffer:老的,线程安全的(它的方法有synchronized修饰)
- StringBuilder:线程不安全的
常用API
@Test
public void test6(){
StringBuilder s = new StringBuilder("helloworld");
s.setLength(30);
System.out.println(s);
}
@Test
public void test5(){
StringBuilder s = new StringBuilder("helloworld");
s.setCharAt(2, 'a');
System.out.println(s);
}
@Test
public void test4(){
StringBuilder s = new StringBuilder("helloworld");
s.reverse();
System.out.println(s);
}
@Test
public void test3(){
StringBuilder s = new StringBuilder("helloworld");
s.delete(1, 3);
s.deleteCharAt(4);
System.out.println(s);
}
@Test
public void test2(){
StringBuilder s = new StringBuilder("helloworld");
s.insert(5, "java");
s.insert(5, "chailinyan");
System.out.println(s);
}
@Test
public void test1(){
StringBuilder s = new StringBuilder();
s.append("hello").append(true).append('a').append(12).append("atguigu");
System.out.println(s);
System.out.println(s.length());
}
日期时间API
@Test
public void test8(){
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒 E 是这一年的D天");
String str = df.format(now);
System.out.println(str);
}
@Test
public void test05(){
LocalDate lai = LocalDate.of(2019, 5, 13);
System.out.println(lai.getDayOfYear());
}
@Test
public void test04(){
LocalDate lai = LocalDate.of(2019, 5, 13);
System.out.println(lai);
}
@Test
public void test03(){
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
}
@Test
public void test02(){
LocalTime now = LocalTime.now();
System.out.println(now);
}
@Test
public void test01(){
LocalDate now = LocalDate.now();
System.out.println(now);
}