分享

Java笔试题分类总结

 为你放纵一生 2016-04-14

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

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

Stringstr1 ='abc';Stringstr2 =newString('abcd');

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

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

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

1、

publicstaticvoidmain(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、

publicstaticvoidmain(String args) { String str1 ='abc'; String str2 =newString('abc'); String str3 =newString('abc'); System.out.println(str1 == str2);// falseSystem.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、

publicstaticvoidmain(String args) { String str1 ='hello'; System.out.println(str1 =='he'+'llo');// true}

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

4、

publicstaticvoidmain(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、

publicstaticvoidmain(String args) { String str1 ='hello'; String str2 =newString('hello'); System.out.println(str1 == str2.intern);// true}

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

6、

publicstaticvoidmain(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、下面这段代码的运行结果是什么?

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

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

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多