String类的常见面试题,以及String,StringBuffer和StringBuilder的区别

写几个String类的常见面试题,觉得可以的老铁点赞哈,欢迎各路大神指教!内容有点多需要耐心点看完.
先说说String,StringBuffer和StringBuilder的区别吧
    String是字符串常量,用final修饰,StringBuffer是字符串变量,它是线程安全的,StringBuilder也是字符串变量,但是他是线程不安全的.
    String和StringBuffer的区别在于性能,String是不可变的对象,每次对String进行操作实际上是生成了一个新String的对象,而原来的就会成为垃圾,所以我们在代码中尽量不对String做大量的操作,但是有一点需要注意的是,JVM对字符串拼接做了一定的优化,比如:String  s = "ab" +"dc";会在编译的时候直接生成String = "abdc";此时就不存在拼接过程.

StringBuffer和StringBuilder相比较StringBuffer是线程安全的可变字符串,其内部实现是可变的数组,StringBuilder是java5.0新增的一个类,功能和StringBuilder类似,但是线程非安全,因此在没有多线程问题的前提下,StringBuilder会获得更好的性能.

    然后说说String的常见面试题:
1.判断定义为String类型的s1和s2是否相等
* String s1 = "abc";
* String s2 = "abc";
* System.out.println(s1 == s2); //true
        * System.out.println(s1.equals(s2));    //true

我先直接上一张内存图然后在解释一下:

简单的说创建s1的时候会在常量池中创建一个"abc",这个"abc"有一个地址值,然后s1把引用指向"abc"的地址值;创建s2的时候会在常量池中去检查是否有"abc",如果有就直接把引用指向"abc"的地址值,所以s1和s2的地址值相等.

2.下面这句话在内存中创建了几个对象?
* String s1 = new String("abc");
我们先来看一下String类的构造方法:

String(String original)
    初始化一个新创建的 String 对象,使其表示一个与参数相同的字符序列;换句话说,新创建的字符串是该参数字符串的副本。
然后在画一下内存图:
综合构造方法和内存图简单的解释一下:内存的顺序是这样的,先是方法进栈,创建一个s1对象,然后在常量池创建一个"abc",然后在堆内存中复制一个"abc"的副本,但有自己的地址值0x0011,最后再把s1的引用指向0x0011.

3.判断定义为String类型的s1和s2是否相等
* String s1 = new String("abc");
* String s2 = "abc";
* System.out.println(s1 == s2); //false
* System.out.println(s1.equals(s2));    //true
这个题和上面的题很像,创建的两个对象一个引用指向的是堆内存,另一个地址是指向常量池.

 4.判断定义为String类型的s1和s2是否相等
* String s1 = "a" + "b" + "c";
* String s2 = "abc";
* System.out.println(s1 == s2); //true
* System.out.println(s1.equals(s2));    //true
这个题是考的jvm的对String类的常量优化机制, String s1 = "a" + "b" + "c";代码在编译的时候就会生成String s1 = "abc";在创建s2的时候常量池中已经有"abc"了,会直接把引用指向"abc",所以s1和s2的地址值是一样的.

5.判断定义为String类型的s1和s2是否相等
* String s1 = "ab";
* String s2 = "abc";
* String s3 = s1 + "c";
* System.out.println(s3 == s2);     //false
* System.out.println(s3.equals(s2));    //true
String类的api这样说的:
Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。字符串串联是通过 StringBuilder (或 StringBuffer )类及其 append 方法实现的。字符串转换是通过 toString 方法实现的,该方法由 Object 类定义,并可被 Java 中的所有类继承。
然后我们再来看一张内存图:

简单的解释一下内存中的顺序:

①主方法进栈,创建s1对象,然后在常量池中创建"ab",s1把引用指向"ab"的地址值,
②创建s2对象,然后在常量池中创建"abc",s2把引用指向"abc"的地址值,
③创建s3,然后在堆内存中创建StringBuffer或者StringBuilder的对象,利用append()方法,把"abc"赋值给该对象,再利用toString()方法在堆内存中创建出String对象,值为"abc",地址值为"0x0022,最后把s3的引用指向0x0022
所以,s2和s3地址值不相等.

猜你喜欢

转载自blog.csdn.net/iteen/article/details/80371818