String 类知识点
我们都知道,字符串是十分重要的的,为此,Java专门提供了一种String类。
String的构造方法
1、直接进行初始化
2、new String对象
3、通过char数组进行构造
public static void main(String[]args) { Stringstr1="stay";Stringstr2=newString("留");char[]ch={'s','t','a','y'};字符串str3=新字符串(ch);系统。出来。println(str1);系统 .出来。打印(str2); 系统。出来。打印(str3);
那么String类内部究竟是有哪些组成的呢?
查看源码并通过编译就可以知道
String类里面存储的是char类型的value数组以及hash
String是引用类型,里面存储的是地址
求字符串的长度
直接字符串名.length()
public static void main(String[]args) { Stringstr1="stay";系统。出来。println(str1.长度());int[]arr={1,2,3,4};系统。出来。println(arr.长度);}
需要注意的是,字符串里面的length是方法,要加上括号,而求数组的长度时,length是数组本身的属性,不需要加上括号
字符串的比较
1、字符串名==字符串名进行地址比较
2、equals()与equalsIgnoreCase()进行内容比较
3、compareTo()与compareToIgnoreCase()进行大小比较
public static void main(String[] args) { String str1 = new String("hello"); String str2 = new String("Hello"); System.out.println(str1 == str2);//str里面存放的是地址,new了两个不一样的对象,地址一定就不一样,所以输出结果是false System.out.println(str1.equals(str2));//equals比较的是字符串的内容 System.out.println(str1.equalsIgnoreCase(str2));//忽略大小写比较字符串的内容 System.out.println(str1.compareTo(str2));//调用compareTo方法,比较字符串的大小。要是str1大于str2就返回正数,否则返回负数 System.out.println(str1.compareToIgnoreCase(str2));//使用compareToIgnoreCase就会忽略大小写进行比较 }
字符串的查找
1、chaeAt()可以得到对应下标的字符
2、indexOf()用来会返回某个字符或者某个字符串首次出现的下标,要是找不到就返回-1
3、lastIndexOf从后往前找,先找到对应的字符再返回下标
public static void main(String[]args) { Strings1="保持饥饿";for(inti=0;i<s1 .length();i++){charch=s1.字符(i);系统。出来。打印(ch+" ");}系统。出来。 println(); int index = s1.indexOf('h'); System.out.println(index);//5 int index2 = s1.indexOf('g', 2);//从下标为2的位置开始查找 System.out.println(index2);//8 int index3 = s1.indexOf("hu"); System.out.println(index3);//5 }
public static void main(String[] args) { String str = "ababaryth" int n = str.lastIndexOf('t'); System.out.println(n);//7 int n2 = str.lastIndexOf('a', 3);//从abab开始向前找 System.out.println(n2);//2 }
转化
1、数字转化为字符串
公共 静态 无效 主(字符串[]args){ 字符串str=字符串。价值(123);系统。出来。println(str);//123}
另外,还可以将类也变成字符串
Stu类{ publicintID; 公共 Stu(int ID){ 这个。身份证=身份证;} @Override publicStringtoString() {return"Stu{"+"ID="+ID+'}';}}公共类测试{公共静态voidmain(String[]args) {Stringstr=String.valueOf(新斯图(12345));系统。出来。println(str);}} //Stu{ID=12345}
将字符串转化为数字(可以使用进制)
public static void main(String[] args) { int a = Integer.valueOf("12", 8);//按照八进制进行转化 System.out.println(a); //10 int b = Integer.parseInt("1234"); System.out.println(b); //10 //Integer.valueOf和Integer.parseInt都是一样的
在常量池里面相同的字符串只会存在一份
字符 字节 字符串的关系
2、字符与字符串
字符转化为字符串
公共静态无效主要(字符串[]参数){char[] val = {'a', 'b', 'c', 'd' };字符串 str = new String(val);System.out.println(str);//abcdString str2=new String(val,1,2);//偏移量是1,数量是2System.out.println(str2);//bc} 字符串转化为字符
公共静态无效主要(字符串[]参数){字符串 str1 = "饿了";char ch = str1.charAt(3);//输出偏移量(offset)(下标)为3的字母System.out.println(ch);//gchar[] val2 = str1.toCharArray();//将字符串变为数组System.out.println(Arrays.toString(val2));} 判断一个字符串是不是全是由数字组成的?
公共静态布尔 IsNum(字符串 str){for (int i = 0; i < str.length(); i++) {char ch = str.charAt(i);//获得数组的每一个元素如果 (ch < '0' || ch > '9') {返回假;}}返回真;}//判断一个字符串中是不是全部都是数字公共静态无效主要(字符串[]参数){字符串 str = "12345";boolean flg = IsNum(str);System.out.println(flg);} 3、字节与字符串
将字节转化为字符串
公共静态无效主要(字符串[]参数){字节[] e = {100, 101, 102,103};字符串 str = new String(e);System.out.println(str);//defgString str2 = new String(e,1,2);//偏移量(offset)为1,数量为2System.out.println(str2);//ef} 将字符串转化为字节
公共静态无效主要(字符串[]参数){字符串 str = "你好";字节[] e = str.getBytes();System.out.println(Arrays.toString(e));} 将字符串转化为一个字符数组
公共静态无效主要(字符串[]参数){字符串 s1 = "保持饥饿";char[] ch = s1.toCharArray();对于 (char x : ch) {System.out.println(x);}}//并不会改变s1,只是创建了一个新的对象 格式化
公共静态无效主要(字符串[]参数){String s1 = String.format("%d %d %d", 2021, 5, 31);System.out.println(s1);}//2021 5 31 下面就要介绍一下
equals是否区分大小写的两种方法
公共静态无效主要(字符串[]参数){字符串 str1 = "你好";字符串 str2 = "你好";System.out.println(str1.equals(str2));//严格区分大小写System.out.println(str1.equalsIgnoreCase(str2));//不进行大小写区分} 比较两个字符串的大小
公共静态无效主要(字符串[]参数){字符串 str1 = "你好";字符串 str2 = "地狱";System.out.println(str1.compareTo(str2));}//String里面已经重写了compareTo方法//要是str1大于str2就返回正数,否则就返回负数 字符串的替换
公共静态无效主要(字符串[]参数){字符串 str1 = "Hellooth";String str2 = str1.replace('H', 'k');//将所有的H替换成KSystem.out.println(str2);System.out.println("========================");字符串 str3 = str1.replace("ll", "yy");System.out.println(str3);System.out.println("========================");字符串 str4="shoopeoohe";字符串 str5=str4.replaceFirst("oo","uk");System.out.println(str5);}//replace既可以替换单个字符,也可以替换字符串(替换所有的字符串)//replaceFirst会替换第一次出现的单个字符或者字符串 字符串的截取
公共静态无效主要(字符串[]参数){字符串 str1 = "Hellooth";String ret = str1.substring(1);//从下标为1处开始往后截取System.out.println(ret);//elloothString ret2 = str1.substring(1,3);//左闭右开System.out.println(ret2);//el} 消去字符串的左右空格trim
公共静态无效主要(字符串[]参数){字符串 str1 = "他 llooth";字符串 ret = str1.trim();System.out.println(ret);}//他懒惰//只能消去左右两侧的空格,但是不能消去字符串中间的空格 修改字符的大小写
公共静态无效主要(字符串[]参数){字符串 s1 = "你好";字符串 ret = s1.toUpperCase();System.out.println(ret);字符串 s2 = "你好";字符串 ret2 = s2.toLowerCase();System.out.println(ret2);System.out.println("s2:" + s2);}//你好//你好//s2:HELLO 也就是说toUpperCase和toLowerCase并不会改变原来的字符串的值,它新创造了一个字符串 字符串的拆分
公共静态无效主要(字符串[]参数){String s1 = "欢迎来到这个世界";String[] ret = s1.split(" ");//以空格为拆分的标识对于(字符串 x:ret){System.out.println(x);}}//欢迎//至//这//世界 这个split方法是有重载的,也可以传两个参数,第二个参数表示最多拆分成几组
公共静态无效主要(字符串[]参数){String s1 = "欢迎来到这个世界";字符串[] ret = s1.split(" ",3);对于(字符串 x:ret){System.out.println(x);}}//欢迎//至//世界 字符串拆分的一些特例
字符"|","*","+"都得加上转义字符,前面加上"\" .
而如果是" 斜杠 " ,那么就得写成"\\" .
如果一个字符串中有多个分隔符,可以用"|"作为连字符.
公共静态无效主要(字符串[]参数){字符串 s1 = "123.45.1.1";String[] ret= s1.split("\\.");//两个斜杠表示真正的斜杠对于(字符串 x:ret){System.out.println(x);} 公共静态无效主要(字符串[]参数){String s1 = "123\\45\\1\\1";//要是只写一个斜杆就会被转义,所以就写成了两个斜杠String[] ret= s1.split("\\\\");//四个斜杠其实就是两个真正的斜杠对于(字符串 x:ret){System.out.println(x);} 要是有多个分隔符,就可以使用 | 进行了分隔
公共静态无效主要(字符串[]参数){String s1 = "zhangsan wangwu&lisi";String[] ret = s1.split(" |&");//以空格和&进行分隔对于(字符串 x:ret){System.out.println(x);}}//zhangsan//wangwu//lisi 多次拆分
公共静态无效主要(字符串[]参数){String s1 = "zhangsan=wangwu&yes=lisi";String[] ret = s1.split("&");//先拆分成两个部分对于(字符串 x:ret){String[] x2 = x.split("=");//再进行拆分对于(字符串 ret2:x2){System.out.println(ret2);}}}//zhangsan//wangwu//是的//lisi 字符串常量池
我们首先要知道什么是池?
"池" 是编程中的一种常见的, 重要的提升效率的方式, 特点就是随用随取,可以提高代码运行效率
常见的池包括Class文件常量池、运行时常量池、字符常量池……
公共静态无效主要(字符串[]参数){字符串 s1 = "停留";字符串 s2 = "停留";System.out.println(s1 == s2);//运行结果是true}
判断s1==s2时,会先去常量池里面看一下有没有相同的字符串,要是有就不会进行创建,直接使用同一份对象,要是没有就创建一份
公共静态无效主要(字符串[]参数){字符串 s1 = "停留";字符串 s2 = "停留";字符串 s3=新字符串(“你好”);System.out.println(s1 == s2);//真System.out.println(s1 == s3);//假}
s1与s3指向不同的对象,里面存的是不一样的地址,所以就是false
公共静态无效主要(字符串[]参数){char[] ch = new char[]{'s', 't', 'a', 'y'};字符串 s1 = 新字符串(ch);字符串 s2 = "停留";System.out.println(s1 == s2);//假}//常量池里面没有stay,所以s2就会创建一个对象,所以s1和s2里面存储不同的地址,所以就是false intern(手动入池)
公共静态无效主要(字符串[]参数){char[] ch = new char[]{'s', 't', 'a', 'y'};字符串 s1 = 新字符串(ch);s1.intern();字符串 s2 = "停留";System.out.println(s1 == s2);//假}////添加一个intern,就将s1指向的对象/字符串内容放进了常量池,所以接下来s2就可以在常量池里面找到stay,所以s1==s2成立 请解释一下String两种对象实例化的区别
前提:常量池中没有hello
1.String str="你好";
思路:创建一个对象,就是常量池对象hello
只会开辟一块内存空间,保存在字符串常量池中,然后str共享常量池的String对象
2.String str=new String("你好");
思路:创建两个对象:常量池的对象hello String对象本身
会开辟两块堆内存空间,字符串"hello"保存在字符串常量池中,然后用常量池中的String对象给新开辟 的String对象赋值。
3.String str = new String(new char[]{'h', 'e', 'l', 'l', 'o'})
思路:创建3个对象
现在堆上创建一个String对象,然后利用copyof将重新开辟数组空间,将参数字符串数组中内容拷贝到String对象中
字符串的不可变性
为什么字符串不可变?
是因为String里面的value数组是private的,外面是访问不到的,所以字符串不能被修改
公共静态无效主要(字符串[]参数){String str = "保持饥饿";str = "哈哈";System.out.println(str);}//哈哈 注意
这里的字符串stay hungry并没有被改变,只是s1这个字符串变量的指向发生了变化
计算机的内部会再产生一个字符串对象,给这个对象赋值为"hello",然后字符串变量s1指向这里的新产生的对象,所以打印出来的是haha
stringBuilder 和 StringBuffer
公共静态无效主要(字符串[]参数){字符串 s = "你好";s += "世界";System.out.println(s);}//也就是在world后面追加一个world 上面的追加代码的底层是什么样子的?
公共静态无效主要(字符串[]参数){StringBuilder stringBuilder = new StringBuilder();//首先会创建一个对象stringBuilder.append("hello");//append的意思是追加stringBuilder.append("world");字符串 s = stringBuilder.toString();System.out.println(s);}//输出结果是hello world 也就是说,每想要追加,就要创建一次对象
因此就要防止写出下面的代码:
公共静态无效主要(字符串[]参数){字符串 s = "你好";for (int i = 0; i < 5; i++) {s += "哈哈";}System.out.println(s);//追加了5次,也就是说,创建了5个临时的对象,占用空间,一定不要这么写 StringBuilder下面还有很多的很好用的方法
//字符串的逆置,直接调用StringBuilder下面的reverse方法公共静态无效main21(字符串[]参数){StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("你好");stringBuilder.append("world");System.out.println(stringBuilder);stringBuilder.reverse();System.out.println(stringBuilder);} StringBuilder和StringBuffer的区别
小总结
String StringBuilder StringBuffer三者的区别
1.String的内容不能被修改,但是StringBuilder和StringBuffer的内容可以被修改
2.StringBuilder和StringBuffer的功能几乎是一样的
3.StringBuffer采用同步处理,属于线程安全操作,但是StringBuilder没有采用同步处理,属于线程不安全操作
2、判断下面的一共创建了几个对象 (前提不考虑常量池之前是否存在)
字符串 str = new String("ab");
一共会创建两个对象,分别是“ab”常量池和 String对象
字符串 str = new String("a") + new String("b");
首先会创建“a”和 "b"两个常量池对象,其次会创建两个String对象,由于要进行拼接,所以会创建一个StringBuilder对象,最后还会调用一个toString方法,再创建一个对象,所以一共有6个对象
以上就是我对于String的知识的学习与理解,如有错误,还希望大家能够指正,我们一起进步。
查看1道真题和解析