搞定Java中的string类
Copyright©Stonee
String类在日常的编程工作中所用甚多,这里就string的常用方法和面试题做些记录和说明
1. 概述
看这么一行代码:String str = "abc";
我们可以把abc看成一个字符串对象,栈里面的str引用的是abc的地址
当再次 str = "bcd";
此时,abc在常量池中就变成了垃圾,等待jvm去回收
2. 常用构造方法
打开jdk11的文档: 发现一共15中构造方法,当然我们不用全都记住,列出下列几种:
package scanne;
//string的构造方法
public class Demo3_stringCOn {
public static void main(String [] args){
String s = new String();
System.out.println(s); //返回空串
byte [] arr = {97,98,99};
System.out.println(new String(arr)); //把字节数组转换为字符串
byte [] arr2 = {97,64,65,83,52,62,98};
System.out.println(new String(arr2,1,3)); //转换一部分
char [] arr3 = {'s','t','o','n','e'};
System.out.println(new String(arr3)); //将字符数组转换成字符串
String ss1 = new String("stonee");
System.out.println(ss1);
}
}
3. 从内存图中解析String常用面试题
一共五道题,直接以程序形式呈现出来:
package stringg;
//java只要有+,就会变成字符串
public class Demo3_String {
public static void main(String [] args){
String s1 = "abc"; //s1等这些变量名在在栈中其实就是地址
String s2 = "abc"; //abc在常量池中,s1和s2引用的同一个值
System.out.println(s1 == s2); //ture
System.out.println(s1.equals(s2)); //ture
// 问题1,在上述代码中,为什么结果为true
String s3 = new String("abc"); //此时堆里面会拷贝常量池中的“abc”,所以有两个“abc”
// 问题2,在上述代码中,内存中一共有几个abc?
System.out.println(s1 == s3);// false 常量池和堆中地址不一样
System.out.println(s1.equals(s3)); //ture 值相等
// 问题3,在上述代码中,为什么结果为false和true
String s4 = "a"+"b"+"c";
System.out.println(s1 == s4); // true 编译器有常量优化机制,会把s4的值指向s1
System.out.println(s1.equals(s4)); //true
// 问题4,在上述代码中,为什么结果为true
String s5 = "ab" ;
String s6 = s5 + "c"; //s5是变量,不存在常量优化机制
System.out.println(s6 == s1); //false
System.out.println(s1.equals(s6)); //true
// 问题5,在上述代码中,为什么结果为false和true
}
}
在上面的代码中,每个问题基本都有详细的解答,这里通过内存图的形式详细解答:
刚开始会在常量池中建立常量“abc”和“ab”。因为s1-6代表的是对象的地址,所以s1 == s2 == s4。在第二个问题中,因为new是在堆中新建一个String的实例,所以需要把常量池中的“abc”拷贝到堆中去。故而s1和s3的地址不一样。对于第五个问题,在jdk6的文档中可以看到当连个字符串“+” 运算的时候,会先在堆里初始化一个StringBuffer或者StringBuilder实例,通过其中的append方法将两个字符串加起来,形成“abc”,但是要注意,此时还不是字符串,需要用到toString方法变为字符串。
4. String中常用的方法
还是那句话:点击打开jdk11的文档:
package stringg;
public class Demo4_StingMethod {
public static void main(String [] args){
String s1 = "Stonee";
String s2 = "Stonee is so cool";
String s3 = "stonee";
System.out.println(s1.equals(s3));
System.out.println(s1.equalsIgnoreCase(s3));
System.out.println(s2.contains(s1)); //是否包含s1
System.out.println(s2.startsWith(s1)); //是否以传入字符串开头
System.out.println(s2.endsWith(s1));
System.out.println("cool".isEmpty());
System.out.println("".isEmpty()); //System.out.println(null.isEmpty); null不是空字符串,是一个空常量,不能调用任何方法,否则会出现现空指针异常。null可以给任意引用常量赋值
System.out.println("王星星真帅".length()); //5 获得字符个数,不是字节码
int arr[] = {1,2,3};
System.out.println(arr.length); //数组的length是属性,不是方法,它没有括号
System.out.println(s1.charAt(2)); //索引越界会抛出异常
System.out.println(s2.indexOf(" ")); //6 如果不存在返回-1
System.out.println(s2.indexOf(" i")); //indexof可以找字符或者字符串
System.out.println(s2.indexOf('o',5)); //从第五个后面找O
System.out.println(s2.lastIndexOf( '0',5)); //和上个相反
System.out.println(s2.substring(4,9)); //从4位置开始截取到9结束
byte [] arr2 = s1.getBytes(); //通过码表把字符串转化为byte
for (int i = 0; i < s1.length(); i++)
System.out.print(arr2[i] + " ");
char [] arr3 = s2.toCharArray(); //把字符串转换为char数组
for (int i = 0; i < arr3.length; i++){
System.out.print(arr3[i] + " ");
}
s3 = String.valueOf(arr3); //把任意类型转换为字符串
System.out.println("\n" + s3); //value底层用的string的构造方法
//当String.valueof(对象)时,用的是对象从Object类中的toString方法,不包括重写
System.out.println(s1.toUpperCase()); //转换大写
System.out.println(s1.toUpperCase().toLowerCase()); //转小写
System.out.println(s1.replace('o','6')); //替换,不存在则不替换
System.out.println(" stonee ".trim()); //去掉两边空格
System.out.println(" stonee ".trim()); //去掉两边空格
System.out.println(s1.compareTo(s2)); //比较码表值,返回int行码表的差值,不区分大写小,可看源码了解
}
}
要注意,如果是字符串常量和变量比较,常写作:
"stonee".equals(s);
为了防止空指针异常
上面这些方法像valueof等之类的许多Java内置类中都有,要在学习中逐步锻炼举一反三的能力