Java笔试题分类总结--String

来源:互联网 发布:烯牛数据 编辑:程序博客网 时间:2024/06/01 07:55

Java中字符串对象是一种特殊的对象。String类是一个不可变的(final)类,也就说,String对象一旦创建就不允许修改。String类有一个对应的常量池(String pool),每一个内容相同的字符串在常量池里都会有一个对象与之对应。

首先,让我们来看一下下边这两种定义String的区别。

String str1 = "abc";   String str2 = new String("abcd"); 

那么,它们两个在内存中是怎么分配的呢。

这里写图片描述

str1和str2是两个对象的引用,存放在Java栈中。第一条语句没有在堆中分配内存,而是将“abc”保存在常量池中。对于第二条语句,同样会在常量池中保存一个“abcd”的字符串,当new时,会拷贝一份该字符串存放到堆中,于是str2指向了堆中的那个“abcd”字符串。同理,如果我们再定义一句String str3 = “abc”;那么,栈中的引用str3会指向跟str1相同的那个常量池中的”abc”。

接下来,让我们通过几段代码来分析一下String。

1、

 public static void main(String[] args) {      String str1 = "abc";       String str2 = "abc";       System.out.println(str1 == str2); // true }

分析: 这里结果为true。当程序加载String str1 = “abc”; 这句代码时,会去常量池中检查有没有”abc”这个对象,如果没有,则在常量池中创建一个”abc”对象。同样,当加载String str2 = “abc”; 这句代码时,因为常量池中已经存在了”abc”这个对象,则str2直接指向常量池中的”abc”对象,它们两个指向的是同一个常量池中的对象,所以输出为true。

2、

public static void main(String[] args) {    String str1 = "abc";    String str2 = new String("abc");    String str3 = new String("abc");    System.out.println(str1 == str2); // false    System.out.println(str2 == str3); // false} 

分析: 当程序加载String str1 = “abc”;这句的时候,在常量池里会创建”abc”这个对象,str1指向常量池中的”abc”对象。当程序加载String str2 = new String(“abc”);这句的时候,因为常量池里已经有了”abc”这个对象,所以在常量池中不新建对象,但是在java堆中会新建一个”abc”对象,str2指向Java堆中新建的”abc”对象。当程序加载String str3 = new String(“abc”);这句的时候,同样因为常量池中已经有”abc”这个对象,所以不在常量池中新建”abc”对象,但是也会在Java堆中新建一个”abc”对象,str3指向Java堆中新建的这个”abc”对象,注意,这个”abc”对象跟str2指向的”abc”对象不是同一个,str1、str2和str3指向的都是不同的对象,所以输出结果都为false。

3、

public static void main(String[] args) {    String str1 = "hello";    System.out.println(str1 == "he" + "llo"); // true}

分析: 这里输出为true。”he” + “llo” 两个双引号形式的字符串常量相加, 在编译的时候直接会被转为一个字符串常量”hello”并保存在常量池中。

4、

public static void main(String[] args) {    String str1 = "hello";    String str2 = "he";    System.out.println(str1 == str2 + "llo"); // false}

分析: 这里输出为false。str2 + “llo” 字符串变量和字符串常量相加的时候,内部是使用StringBuilder类的append()方法和toString()方法来实现的。而StringBuilder类toString()方法返回的字符串是通过构造函数创建的。所以生成的”hello”对象是在JAVA堆里。

5、

public static void main(String[] args) {    String str1 = "hello";    String str2 = new String("hello");    System.out.println(str1 == str2.intern()); // true}

分析: 这里输出为true。String的intern()方法是扩充常量池的一个方法,当String实例str2调用intern()方法时,Java会在常量池中查找是否有相同Unicode的字符串常量对象,如果有,则返回其引用,如果没有,则在常量池中增加一个Unicode等于str2的字符串常量对象并返回它的引用。这里str2.intern()方法返回的是指向常量池中”hello”的引用,所以输出为true。

6、

public static void main(String[] args) {    String str1 = "hello";    str1.concat(" world");    System.out.println(str1); // hello}

分析: 这里输出为”hello”。因为String是不可变(final)的,所以输出为”hello”。如果想可变,可以使用StringBuilder或StringBuffer类,或者定义一个新的变量接收一下方法的返回值String str2 = str1.concat(” world”);。


通过上边几个例子,我们应该能对Java中的字符串String有了一个很好的了解。下边来介绍一些在笔试面试中,经常遇到的问题。

1、String s = new String(“xyz”); 创建了几个String Object?

答案是1个或2个。如果之前在常量池中已经创建过"xyz"对象的话,那么只会在Java堆中创建一个"xyz"对象,如果常量池中没有的话,也会在常量池中创建一个"xyz"对象,所以说是1个或2个。

2、是否可以继承String类?

String类是final类故不可以被继承。

3、数组有没有length()这个方法? String有没有length()这个方法?

数组没有length()这个方法,有length属性。String有length()这个方法。

4、Java中判断字符串值是否相等是用”==”还是”equals”?

Java中字符串的"equals"方法是判断两个字符串的值是否相等,"=="是判断两个字符串的地址是否相同。

5、Java的String,StringBuffer,StringBuilder有什么区别?

String是不可变(final)类,每次在String对象上的操作都会生成一个新的对象;StringBuffer和StringBuilder是可变的,它允许在原来对象上进行操作,而不用每次增加对象;StringBuffer是线程安全的,但效率较低,而StringBuilder则不是线程安全的,效率最高。

6、下面这段代码的运行结果是什么?

代码如下:public static void main(String[] args) {    String[] strs = new String[10];    System.out.println(strs[1]);    System.out.println(strs[10]);}
解答:第一个打印输出为null,因为字符串默认值为null;第二个打印会报ArrayIndexOutOfBoundsException,因为数组的下标是从0开始的。

7、下面这段代码的运行结果是什么?

代码如下:public static void main(String[] args) {    String str;    System.out.println(str);} 
解答:编译器中System.out.println(str);这一行会报错,因为局部变量str必须要初始化才能输出。
1 0