一、String类:
字符串,使用一对“”引起来;
1.String 声明为final 不可被继承;
2.实现了
- Seriablizable:表示字符串是支持序列化的;
- Compareble :可比较大小
- CharSequence接口:提供对多种不同类型的统一只读访问序列。
3.String内部声明了final char[] value数组,用于存储char 数组;
4.String:代表不可变的字符序列;简称:不可变性;
- 体现1:当对字符串重新赋值时,需要重新制定内存区域赋值,不能使用原有的value进行赋值
- 体现2:当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值
- 体现3.当调用replace方法时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值
说明:
1 @Test
2 public void test1() {
3 String s1 = "abc";// 自面量方式创建
4 String s2 = s1;
5 System.out.println(s1 == s2);
6 s1 = "hello";
7 System.out.println(s1 == s2);
8 System.out.println(s1);
9 System.out.println(s2);
19
这里 第一个 System.out.println(s1 == s2);这里是true;
s1 = "hello";
System.out.println(s1 == s2);
这里是false,因为s1就是hello,s2还是abc,这里区别于其他引用类型对象的赋值;也就是当对字符串重新赋值时,需要重新制定内存区域赋值,不能使用原有的value进行赋值
1 @Test
2 public void test4() {
3 String s1 = "abcdef";
4 String s2 = "abc";
5 s2 += "def";// abcdef
6 System.out.println("s1:" + s1);
7 System.out.println("s2:" + s2);
8 System.out.println(s1 == s2);
9
s1:abcdef;
s2:abcdef;
s1== s2的结果是false
体现了当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值;
1 @Test
2 public void test4() {
3 String s4 = "abc";
4 String s5 = s4.replace("a", "m");
5 System.out.println("s4:" + s4);
6 System.out.println("s5:" + s5);
7
s4:abc
s5:mbc
体现了当调用replace方法时,也需要重新指定内存区域赋值,不能使用原有的value值进行赋值
二、String 创建的方式
1.通过new+构造器的方式
说明:
给一个字符串赋值,此时的字符串声明在方法区的字符串常量池中;
问:String s = new String("abc");方式创建对象,在内存中创建了几个对象
答:一个是堆空间的new 对象,另一个 char 数组 对应常量池中的数据
1 String s = new String("0");
2 for(int i=0;i<=5;i++){
3 s+=i;
4 }
5
内存解析:
再看一个例子:
@Test
public void test2() {
String s1 = "ABC";// 在方法区 中的 字符串常量池中
String s2 = "ABC";// 在方法区 中的 字符串常量池中
String s3 = new String("ABC");// 在 堆空间中
String s4 = new String("ABC");// 在 堆空间中
System.out.println(s1 == s2);// true
System.out.println(s3 == s4);// false;
System.out.println(s1 == s4);// false;
Person p1 = new Person("Tom",1);
Person p2 = new Person("Tom",1);
System.out.println(p1.getName() == p2.getName());
System.out.println(p1.getAge() == p2.getAge());
}
1 class Person {
2 private String name;
3 private int age;
4
5 public String getName() {
6 return name;
7 }
8
9 public void setName(String name) {
10 this.name = name;
11 }
12
13 public int getAge() {
14 return age;
15 }
16
17 public void setAge(int age) {
18 this.age = age;
19 }
20
21 public Person(String name, int age) {
22 super();
23 this.name = name;
24 this.age = age;
25 }
26
27
View Code
2.通过字面量方式(区别于new)
说明:
通过字面量方式给一个字符串赋值,此时的字符串声明在方法区的字符串常量池中;
注意:字符串常量池中不保存相同内容的字符串;也就是String的不可变性;
1 String s = "0";
2 for(int i=0;i<=5;i++){
3 s+=i;
4 }
5
三、字符串的特性:
常量与常量的拼接结果在常量池;而且常量池中不会存在相同内容的常量;
字符串拼接:只要其中一个是变量,结果就在堆中;如果拼接的结果调用 intern(),返回值就在常量池中
1 @Test
2 public void test3() {
3 String s1 = "javaEE";
4 String s2 = "hadoop";
5 String s3 = "javaEEhadoop";
6 String s4 = "javaEE"+"hadoop";
7 String s5 = s1 +"hadoop";
8 String s6 = "javaEE"+s2;
9 String s7 = s1+s2;
10 String s8 = s7.intern();
11 System.out.println(s3 == s4);
12 System.out.println(s3 == s5);
13 System.out.println(s3 == s6);
14 System.out.println(s5 == s6);
15 System.out.println(s3 == s8);
16 final String s9 = "hadoop";
17 String s10 = "javaEE"+s9;
18 System.out.println(s3 == s10);//这里 s9是常量
19
20
21
22
s3 == s4:结果是true
s3 == s5:结果是false;
s3 == s6:结果是false;
s5 == s6:结果是false;
s3 == s8:结果是true
s3 == s10这里也是true
原因就是我们这里的特性;
五、String的常用方法:
- int length():返回字符串长度;(从1开始数的,如 Helloworld,那么length 就是10)
- char charAt(int index):返回某索引处的字符串 return value[index]; (index 从0开始)
- boolean isEmpty():判断空字符串 return value.length == 0;
- String toLowerCase():使用默认语言环境,将String中的所有字符串转化为小写
- String toUpperCase():使用默认语言环境,将String中的所有字符串转化为大写
- String trim():去除字符串 首尾的空格;
- boolean equals(Object obj)比较字符串内容是否相同
- boolean equalsIgnoreCase(String anOtherString)与equals方法类似,忽略大小写比较字符串内容是否相同
- String Concat(String str):将指定字符串连接到此字符串的结尾,等价于 “+”
- int compareTo(String anotherString),比较两个字符串的大小;
- String subString(int beginIndex):返回一个新的字符串,他是此字符串的重beginindex 开始截取
- String subString(int beginIndex,int endIndex):返回一个新的字符串,他是此字符串的重beginindex 开始截取 endIndex结束的[beginIndex,endIndex) beginIndex从0开始算的
- boolean endsWith(String suffix):测试字符串是否以指定的后缀结束
- boolean startWith(String prefix):测试此字符串是否以指定的前缀开始;
- boolean startWith(string prefix,int toffset)测试此字符串从指定索引开始的子字符串是否以指定的前缀开始
- boolean contains(charSequence s):当且仅当此字符串包含指定的char值序列时,返回true;
- int indexOf(String str):返回指定子字符串在此字符串中第一次出现的索引,如果存在,则从0开始的,如果不存在,则是-1;
- int indexOf(String str,int fromIndex);返回指定字符串在此字符串中第一次出现的索引
- int lastIndexOf(String str,int fromIndex);返回指定字符串在此字符串中最右边出现的索引
- int lastIndexOf(String str,int fromIndex);返回指定字符串在此字符串中最右边出现的索引
- 注意:indexOf 和 lastIndexOf方法如果未找到,都是返回-1
- String replace(char oldChar,char newChar):返回一个新的字符串,他是通过newChar替换此字符串中出现的国有oldChar;
- String replace(charSequence target,charSequence replacement):使用指定的字面值替换此字符所有匹配字面值目标序列的子字符串
- String replaceAll(String regex,String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的子字符串
- String replaceFirst(String regex,String replacement):使用给定的replacement替换此字符串所有匹配给定的正则表达式的第一个子字符串
- boolean matches(String regex):告知此字符串是否匹配给定的正则表达式
- String[] split(string regex);根据给定正则表达式的匹配拆分此字符串;
- String[] split(string regex,int limit);根据给定正则表达式的匹配拆分此字符串;最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中
1 @Test
2 public void test1() {
3 String s1 = "Helloworld";
4 String testNull = null;
5 String testEmpty = "";
6 System.out.println(s1.length());//获取数组长度
7 System.out.println(s1.charAt(0));//获取指定位置的字符
8 System.out.println(s1.isEmpty());//判断字符串是否为空
9 /// System.out.println(testNull.isEmpty());//报错
10 System.out.println(testEmpty.isEmpty());//判断字符串是否为空
11 System.out.println(s1.toUpperCase());//转换为大写
12 System.out.println(s1);//Helloworld 体现了不可变性
13 System.out.println(s1.toLowerCase());//转换为小写
14
15 String s2 = " Hello World ";
16 String s3 = s2.trim();//去除字符串首尾的空格
17 System.out.println("----"+s2+"------");//体现了不可变性
18 System.out.println("----"+s3+"------");
19
20 String s4 = "HELLOWORLD";
21 System.out.println(s1.equals(s4));
22 System.out.println(s1.equalsIgnoreCase(s4));//忽略大小写比较字符串内容
23
24 String s5 = "abc";
25 System.out.println(s5.concat("efg"));//拼接字符串
26
27 String s6 = "abf";
28 System.out.println(s5.compareTo(s6));//涉及到字符串排序
29
30 System.out.println(s6);
31 System.out.println(s6.substring(1));
32 System.out.println(s1.substring(2,5));//左闭右开 从2开始 到5结束 不包括5
33
34 boolean str1 = s1.endsWith("rld");
35 System.out.println(str1);
36
37 boolean str2 = s1.startsWith("he");
38 System.out.println(str2);
39
40 boolean str3 = s1.startsWith("He");
41 System.out.println(str3);
42
43
44 boolean str4 = s1.startsWith("He",0);
45 System.out.println(str4);
46
47 boolean str5 = s1.startsWith("el",1);
48 System.out.println(str5);
49
50 boolean str6 = s1.contains("w");
51 System.out.println(str6);
52
53 int str7 = s1.indexOf("lo");
54 System.out.println(str7);
55
56 int str8 = s1.indexOf("lol");
57 System.out.println(str8);
58
59 int str9 = s1.indexOf("lo",5);
60 System.out.println(str9);
61
62 int str10 = s1.lastIndexOf("lo",5);
63 System.out.println(str10);
64
65 int str11 = s1.lastIndexOf("w");
66 System.out.println(str11);
67 }
68
69 @Test
70 public void test2() {
71 String str1 = "Hello World";
72 String str2 = str1.replace("Hello", "Byby");
73 System.out.println(str1);
74 System.out.println(str2);
75 String str3 = str1.replace('H', 'B');
76 System.out.println(str3);
77
78 String str = "12hello34world5java789mysql456";
79 String string = str.replaceAll("\\d+", ",").replaceAll("^,|,$", "");//\\d匹配数字, +表示有多个数字,^,|,$ 开头或者结尾有逗号
80 System.out.println(string);
81
82 str = "12345";
83 boolean matches = str.matches("\\d+");
84 System.out.println(matches);
85 String tel = "0571-4534289";
86 boolean result = tel.matches("0571-\\d{7,8}");//0571开头 ,数字是7-8位
87 System.out.println(result);
88
89
90 str = "HELLO|WORLD|JAVA";
91 String[] strs = str.split("\\|");
92 for(int i = 0;i<strs.length;i++) {
93 System.out.println(strs[i]);
94 }
95 str2 = "hellow.world.java";
96 String[] strs2 = str2.split("\\.");
97 for(int i = 0;i<strs2.length;i++) {
98 System.out.println(strs2[i]);
99 }
100
101
102
View Code
★★★相关面试题:
1 package commonmethod;
2
3 public class Day20StringInterviewTest9 {
4
5 String str = new String("good");
7 char[] ch = {'t','e','s','t'};
8 public void change(String str,char ch[]) {
9 str = "test ok";
11 ch[0] = 'b';
12 }
13 public static void main(String[] args) {
14 Day20StringInterviewTest9 ex = new Day20StringInterviewTest9();
15 ex.change(ex.str, ex.ch);
16 System.out.println(ex.str);18 System.out.println(ex.ch);
19
20 }
21
22
这里的输出结果 :
good
best
对于这个结果,前两个解释一下;想看ex.str为什么结果还是good呢?
首先需要两个知识点:
①在对象的方法中,值传递的规则是:如果形参是基本数据类型时,方法参数传递的是参数本事的值,如果参数是引用数据类型时,那个参数传递的是地址值(不是对象本身);(以下内存解析中0X开头的部分);
②String 值的不可变性;
ex.change(ex.str, ex.ch);==》形参:ex.str,其实是0x002;
str = "test ok";赋值一个新的值;常量池中没有 “test ok”,那么常量池中创建一个value值是 “test ok”的对象(这个原则,就是String不可变性的体现(即体现1));此时在该方法中产生一个 str的副本,该str副本这里称 strx吧;strx 指向test ok ;最后方法结束自动销毁(由jvm垃圾回收);最后打印出ex.str,就是打印传入的对应地址值的value值即:good;
这里的ch就是普通的引用类型变量;如果要做扩展,那么他可以换成某个对象,那么结果是什么呢?
附上内存解析图:(参考文章https://zhuanlan.zhihu.com/p/266885142)
这里补充例子:
1 public static String changeString(String str){
2 return str+"ABC";
3 }
4 public static int changInt(int a){
5 a = 0;
6 return a;
7 }
8 @Test
9 public void testString1() {
10 String str1="abc123";
11 int a = 23;
12 System.out.println(str1);
13 System.out.println(changInt(a));
14 System.out.println(a);
15
这里的结果是 ?
abc123
abc123ABC
23
System.out.println(str1):这个还是跟上面那个套路是一样的;
System.out.println(a);是23原因是在ChangeInt方法中 a 其实是 a·,它在方法结束后自动销毁了;所以最后a仍然是 23;
六、String的转换:
1.String与基本数据类型的转换:
String-->基本数据类型、包装类:调用包装类的静态方法;parstXXX(str);
基本数据类型、包装类--》string 调用S挺重载的valueOf(xxx);
1 @Test
2 public void test1() {
3 String str1 = "123";
4 int num = Integer.parseInt(str1);
5 String str2 = String.valueOf(num);
6 String str3 = num+"";
7 System.out.println(str2);
8 System.out.println(str3 == str1);
9
2.String 其他数据机构的转换
string 与char数组的转换 调用string toCharArray方法
string 与byte数组的转换 调用string getBytes方法
编码:String-->byte[]:调用string getBytes方法
解码:byte[]-->string:调用String的构造器;
说明:解码时,要求解码使用的字符集必须与编码时使用的字符集一致,否则会出现乱码
1 @Test
2 public void test1() throws UnsupportedEncodingException {
3 String str1 = "abc123中国";//题目 把 abc123 变成 a321cb,那么就需要变成字符串再反转;
4 char[] charStr = str1.toCharArray();
5 for(int i=0;i<charStr.length;i++) {
6 System.out.println(charStr[i]);
7 }
8
9 char[] arr = new char[] {'h','e','l','l'};
10 String str2 = new String(arr);
11 System.out.println(str2);
12 System.out.println(arr);
13 System.out.println(Arrays.toString(arr));
14 byte[] toByteArr = str1.getBytes();//可以设置编码
15 for(int i=0;i<toByteArr.length;i++) {
16 System.out.println(toByteArr[i]);
17 }
18 System.out.println(toByteArr);
19 System.out.println(Arrays.toString(toByteArr));
20 byte[] toByteArr1 = str1.getBytes("gbk");//可以设置编码
21 System.out.println(Arrays.toString(toByteArr1));
22
23 String str3 = new String(toByteArr1);//设置解码
24 System.out.println(str3);
25
26 String str4 = new String(toByteArr1,"gbk");//解码没有出现乱码。原因是:编码集和节目集一致
27 System.out.println(str4);
28
View Code
七、String、StringBuilder 、StringBuffer
1.String、StringBuilder 、StringBuffer的区别
String:不可变的字符序列 底层使用char[]存放数据;
StringBuffer:可变的字符序列,线程安全,效率低;底层使用char[]存放数据;
StringBuilder:可变的字符序列,线程不安全,效率高;底层使用char[]存放数据;
源码分析
String str = new String()//new char[0];
String str1 = new String("abc")//new char[]{'a','b','c'}
StringBuffer sb1 = new StringBuffer();//new char[16];
StringBuffer sb1 = new StringBuffer("abc");//new char[19]; value[0] = 'a',value[1] = 'b',value[2] = 'c'
问题1.System.out.println(sb1.length)//3
问题2,扩容问题,若果要添加的数据底层数组承载不了,那就需要扩容底层数组;把原来的数组复制到新的value数组;默认情况下扩容为原来容量的2倍+2(详情可参考源码)
指导建议:开发中建议大家使用 StringBuilder(int capacity) 或者StringBuffer(int capacity)
2.String 转换成 StringBuilder 、StringBuffe
StringBuffer sb = new StringBuffer("aaa");
StringBulider sb = new StringBulider("aaa");
String str = new String(sb);
or
String str = sb.toString();
3.StringBuffer的常用方法:
StringBuffer append(xxx):提供了很多append方法,用于字符串拼接
StringBufferdelete(int start,int end)删除指定位置的内容(左闭右开)
StringBuffer replace(int start,int end,String str)把[start,end)位置替换为
StringBuffer insert(int offset,xxx),在指定位置插入XXX
reverse(),把当前字符串倒叙
public int indexOf(String str)
public String subString(int start,int end)
public int length();
public char charAt(int n)
public void setCharAt(int n,char ch);
总结:
增:append()
删:delete(int start,int end)
改:public void setCharAt(int n,char ch);/StringBuffer replace(int start,int end,String str)
查:public int indexOf(String str)
插:StringBuffer insert(int offset,xxx)
长度length();
1 @Test
2 public void test1() {
3 StringBuffer sb1 = new StringBuffer();
4 sb1.append(1);
5 sb1.append("1");
6 System.out.println(sb1.toString());
7 sb1.delete(0, 1);
8 System.out.println(sb1.toString());
9 sb1.insert(0, "112123");
10 System.out.println(sb1.replace(0, 2, "AA"));
11 System.out.println(sb1.toString());
12 sb1.insert(0, false);
13 System.out.println(sb1.toString());
14 System.out.println(sb1.reverse());
15 System.out.println(sb1.length());
16 System.out.println(sb1.indexOf("eslaf"));
17 System.out.println(sb1.charAt(10));
18 sb1.setCharAt(10, 'x');
19 System.out.println(sb1.toString());
20
View Code
补充面试题:
1.字符串反转:abcdefg==>abfedcg
1 public void testInterview1() {
2 String str = "abcdefg";
3 String str1 = str.substring(0,2);
4 String str2 = str.substring(2,6);
5 String str3 = str.substring(6);
6 StringBuffer sb = new StringBuffer(str2);
7 String res = str1+sb.reverse()+str3;
8 System.out.println("字符串反转:"+res);
9
View Code
2.abkkcadkabfkabkskab 问,ab一共出现过几次?
1 @Test
2 public void testInterview2() {
3 String str = "abkkcadkabfkabkskab";
4 int count = 0;
5 int index = -1;
6 for(int i=0;i<str.length();i++) {
7 if(i == 0) {
8 index = str.indexOf("ab",0);
9 }else {
10 index = str.indexOf("ab",index+1);
11 }
12
13
14 if(index >-1) {
15 count = count+1;
16
17 }else {
18 break;
19 }
20 }
21 System.out.println(str.length());
22 System.out.println(count);
23
24
View Code
3.获取两个字符串中的最大相同子串;str1 = "abcwerthelloyuiodef";str2 = "cvhellobnm";
1 @Test
2 public void testInterviwq3() {
3 String str1 = "abcwerthelloyuiodefn";
4 String str2 = "cvhellodefnm";
5 String min = "";
6 String max = "";
7 StringBuffer sb = new StringBuffer();
8 if(str1.length()<= str2.length()) {
9 min = str1;
10 max = str2;
11 }else {
12 min = str2;
13 max = str1;
14 }
15 for(int i=0;i<min.length();i++) {
16 for(int x=0,y=min.length()-i;y<=min.length();x++,y++) {
17 String tem = min.substring(x,y);
18 System.out.println(tem);
19 if(max.contains(tem)) {
20 sb.append(tem+"|");
21 }
22 }
23 if(sb.length()>1) {
24 break;
25 }
26 }
27 System.out.println("最大相同子串:"+sb.toString());
28
View Code
4.StringBuffer中注意的一个地方:
1 @Test
2 public void testInterview4() {
3 String str = null;
4 StringBuffer sb = new StringBuffer();
5 sb.append(str);//appendNull方法把 ‘null’ append进去了;
6 System.out.println(sb.length());
7 StringBuffer sb2 = new StringBuffer(str);//这里有一个 str.length;这里str是null,所以报错
8 System.out.println(sb.length());
9
10
我从来不相信什么懒洋洋的自由。我向往的自由是通过勤奋和努力实现的更广阔的人生。 我要做一个自由又自律的人,靠势必实现的决心认真地活着。