最近在看一些String的面试题,然后就想着把它整理起来,之后如果还有看到其他的也会继续添加进来
常见问题
1.String中,==和equals()的区别
答:equals本质上是==,但是String重写了equals方法,在String中,==比较的是两个对象的引用地址是否相等,而equals比较的是两个字符串对象的字面量是否相等。
2.两个对象的hashCode相同,equals一定相同吗?
答:不是,两个对象的hash相同,equals不一定相同,但是equals相同,hashCode一定相同
3.创建String对象有几种方式
String a = "";
String b = new String();
String c = String.class.newInstance();
clone的方式
反序列化的方式
4.在Java中,创建对象有几种方式
1)new一个 对象
2)通过构造方法
3)利用反射创建一个对象--String.class.newInstance()
4)利用Object的clone方法
5)反序列化方式
5.以下代码创建出几个对象?---4个
String a = "abc";
String b = new String("abc");
String c = "abc";
String d = new String("xyz");
6.以下代码创建出几个对象?
答:根据不同的编译器有不同的情况
- 有的java编译器是创建3个对象,"abc"一个,"xyz"一个,两者相加以后又形成一个对象"abcxyz"
- 官方的编译器,只会创建出1个,在编译阶段它将"abc"和"xyz"拼接在一起形成一个对象"abcxyz",对象a存着该"abcxyz"的引用地址
String a = "abc" + "xyz"
7.以下代码会创建几个对象?
答:0个,只会有一个新的索引a,空串在Java虚拟机启动的时候默认生成的
String a = "";
8.以下代码会创建几个对象?
答:4个,首先"abc"对象在常量池里被创建,然后在堆内存里创建了对象b,之后"xyz"对象在常量池被创建,然后用+=进行拼接的时候,b被构造成StringBuilder对象,调用append拼接了"xyz",之后本来应该是要调用toString()方法转换成String对象,但是+=把这一步给省略了
String b = new String("abc");
b += "xyz";
9.以下的第三行代码创建出几个对象(第一和第二行不算入)
String var1 = "abc";
String var2 = new String("abc");
String str = var1 + var2;
答:两个对象,一个是String对象,另一个是StringBuilder对象,当我们没有使用str变量时,底层会创建一个StringBuilder对象,调用append方法把var1和var2拼接起来,最后调用toString()方法返回。
而当我们使用str变量时,产生出一个String对象,编译器会做一个优化。底层是通过var1+var2方法拼接字符串,比如如下.class代码:
使用str:
public static void main(String[] args) {
String var1 = "abc";
String var2 = new String("abc");
String str = var1 + var2;
System.out.println(str);
}
不使用str:
public static void main(String[] args) {
String var1 = "abc";
String var2 = new String("abc");
(new StringBuilder()).append(var1).append(var2).toString();
}
10.new String("abc")底层的创建过程?
答:首先,先在常量池里面创建一个"abc"字符串对象,这个对象指向了一个char数组['a','b','c'],然后在堆内存里开辟一块空间创建了String对象,这个字符串对象也指向了这个char数组
11.String字符串的hash值什么时候被赋值
答:默认hash值为0,当调用带String参数的构造方法时会被初始化为传入的那个字符串参数的hash,还有就是当调用字符串的hashCode方法时hash值会被计算出来
12.以下代码打印出来的结果是什么
答:是abc,使用带char数组参数的构造方法,底层是把char数组的内容复制一份给了字符串,所以chars数组和str底层的value数组不是同一个数组,即使改变了chars数组的内容,str还是不变。
char[] chars = {'a','b','c'};
String str = new String(chars);
chars[0] = 'x';
System.out.println(str);
13.以下三种创建String对象的方式有什么区别吗?
String str1 = new String();
String str2 = new String("");
String str3 = "";
答:str1和str2都是在堆内存里创建了一个对象,并指向了""字符串的引用地址,但是str2在构造的时候并把""字符串的hash值赋给了str2,所以相比于str1来说,在之后的操作中,就不用再去计算hash值,性能会提高。而str3相比于前两种,它只是在栈内存里开辟了一个空间指向了常量区里的""字符串对象
14.以下代码中,str2和str3哪种创建方式更好?
String str1 = "abc";
String str2 = new String("abc");
String str3 = new String(str1);
答:str2和str3两个对象都是指向常量区里面同一个"abc"字符串对象的value数组,所以从运行层面上来看两种方法都是一样的。
但在编译的时候,如果直接用字符串常量的方式构造,编译器会去遍历常量区里的所有字符串,直到找到"abc"字符串,再去构造str2。而str3在构造的时候,由于str1指向的是一个引用地址,相当于直接告诉str3你要的字符串常量就在我保存的这个位置,这样就省去了遍历常量区的过程,速度会更快一点。
15.为什么在循环的时候,String用+号进行字符串拼接效率低?
答:因为使用+进行拼接的话,编译器每一次的拼接都会创建一个StringBuilder对象将每个+号后面的字符串通过append方法拼接起来,但是每循环一次都会产生一个StringBuilder对象,当循环的次数很大的时候,效率自然就降低了