String
1.String的介绍
什么是String? String 在java中代表字符串,java程序中所有的的字符串字面值都可以理解为String类的实例实现,即String类的对象实现。并且字符串是常量,其值在创建后不可更改,也就是说String对象是不可变的。String的底层是char[],无论是String类还是char[]数组都有关键字final修饰,也就说明:String类是不可继承的,不可修改的,char[]一旦创建,只能赋值一次,不可修改。
例子一:
String s1 = "a";
s1 = "b";
System.out.println("s1="+s1);
结果显示为:s1=b
这里就有一个疑问,String对象不是不可变的嘛,为什么结果不是 s1=a 呢? String对象不可变,指的是我们创建的字符串字面值不可变,也就是“a” 、“b”这些字符串字面量是不可改变的,我们借助内存图来帮助我们理解。
String s1 = “a”;这条语句执行的时候,会先在运行时常量池中查看是否有字符串字面值“a”的存在,第一种情况:如果有,就将常量池中“a”的地址赋值给s1,第二种情况如果没有,就在常量池中创建一个对象空间,存储“a”,将该对象空间地址赋给s1。我们这里是 第二种。
接着执行 s1 = “b”; 也是第二种情况。由此可见:所谓字符串不可变,指的是我们在常量池中创建的字符串字面值不可变,像“a” 、“b” 一旦创建,就在常量池中开辟空间存储,这个“a” 、“b”是不可变的,并不是说我们定义的字符串变量s1不变,s1只是指向某一内存空间地址。为什么没有打印出s1所指向的空间地址,因为String类重写了Object的toString(),使其能够直接打印出字符串字面值。
例子二:
String s1 = "a";
String s2 = "a";
String s3 = new String("a");
System.out.println(s1 == s2);
System.out.println(s1 == s3);
结果显示为:true false
为什么 s1 == s2 会显示true,没搞明白的请细品例子一。我们重点分析 s1 == s3 为什么是false,我们仍然借助内存图帮助理解。
String s3 = new String(“a”) 这句话到底做了哪些事情,首先 String s3 = new String(“a”) 和 String s3 =”a” 是不一样的,当“a” 在常量池中没有时,前者其实是创建了两个对象,后者创建了一个对象。为什么 String s3 = new String(“a”) 创建了两个对象? 它首先会在堆内存中开辟一个空间,再去字符串常量池中查找有无“a”这个对象存在,如果没有存在,就会像例子一那样,如果已经存在,就把常量池中的“a”的内存空间地址 0x001 存储到堆内存开辟的空间,再将堆内存中开辟的内存空间地址 0x0001 赋值给s3。
s1 和 s3 所指向的地址当然不同,因此 结果为false。
2. String类的一些常用方法
length(); 返回字符串长度
isEmpty(); 如果字符串长度为0,返回true,否则返回false。
charAt(int index); 返回指定索引处的char值,可用于遍历每个字符
concat(String str); 将指定字符串连接到此字符串的末尾
contains(CharSequence s); 当且仅当此字符串包含指定的char值序列时,返回true
equals(Object anObject); 将此字符串于指定的对象进行比较,当且仅当两个字符串彼此字符所在位置和大小写均相同时返回true
indexOf(String str); 返回指定子字符串在此字符串中第一次出现处的索引。
toString(); 返回此对象本身(它已经是一个字符串!)。
trim(); 去除字符串头部和尾部的空格
3. String类相关面试题
题目一:
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2);
结果:true true
题目二:
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
结果 false true
题目三:
String s1 = "a" + "b" + "c";
String s2 = "abc";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
结果 true ture
题目四:
String s1 = "a";
String s2 = "ab";
String s3 = s1 + "b";
System.out.println(s2 == s3);
System.out.println(s2.equals(s3));
结果 false true
分析一下题目四中的 s2 == s3 为false。
String s3 = s1+”b” s1是一个变量,“b”是一个字符串字面值常量,在java编译器编译这条语句的时候,编译器并不知道s1的具体字面值,只知道s1是一个变量,因此它做了这么一个转化:
String s3 = (new StringBuilder(String.valueOf(s1))).append(“b”).toString()
就是在堆内存中new了一个用于存储StringBuilder的空间,最后再将这整个StringBuilder对象再转化为String对象赋值给s3,s3存储的应该就是这个new出来的堆内存的地址,当然不可能和s2所指向的常量池的地址相同。
总结:
本文介绍的String类的概念,String类的一些常用方法和String类常见面试题,分享给大家,有错误请指正。