此处记录做面试题时有疑惑的问题
参考面试题的网址
文章目录
一、String相关的面试题
剖析String的底层原理的一些面试题解答
1、String创建几个对象的问题
知识点:字符串常量池,JVM中有一个字符串常量池,用来保存被共享的String对象,如果使用相同的字符串,首先去常量池中找,如果存在,不再创建新的对象,直接返回已存在对象的引用:如果不存在,才创建这个对象,并放入字符串常量池中,再返回其引用。String类是final的,是不可变类,可以调用intern()方法访问字符串池
String str="aaa";
创建了几个对象?
1个。String str只定义了一个名为str的String类型的变量,没有创建对象;=是对str变量的赋值;"aaa"创建了一个aaa对象,放入了字符串常量池中。String str1="aaa"; String str2="aaa";
创建了几个对象?
1个。只创建了一个aaa对象,对str2赋值时,在字符串常量池中找到了aaa对象,直接使用。String str=new String("abc");
2个。一个abc对象,放在字符串池中,一个new String()对象,用来引用常量池中的对象String a="ab"+"cd";
1个。只创建一个abcd对象,ab、cd最终是没有被使用的,在jdk1.8之后,JVM内部,会将程序简化为:String a = “abcd”String str1 = "abc"; String str2 = "ab"; String str3 = str2 + "c"; System.out.println(str1 == str3); //false
String str3 = str2 + "c"
涉及到了变量的相加,不全是常量,比如"ab"+"cd"
,其内部的实现是:先new一个StringBuffer,然后调用append方法,append(str)、append(“c”),最后再让str3调用toString返回对象。
网上对于这道题目的说法有很多种,如果各位大佬觉得我写的有问题,麻烦帮我指出来,非常感谢!
二、克隆问题
1、定义:克隆是对一个对象进行复制
2、为什么要克隆?为什么不直接new?
克隆的对象可能包含一些已经修改过的属性,而new出来的对象的属性都还是初始化时候的值,所以当需要一个新的对象来保存当前对象的“状态”就靠clone方法了。
注意:常见的Object a=new Object();Object b;b=a;
这是对引用进行复制,即对象在内存中的地址,a和b对象仍然指向了同一个对象。
而通过clone方法赋值的对象跟原来的对象时同时独立存在的。
3、实现:浅克隆(ShallowClone)和深克隆(DeepClone)
- 浅克隆
- 被克隆的类需要实现Cloneable接口
- 覆盖clone()方法,访问修饰符设为public方法,方法中调用super.clone()方法得到需要的复制对象
class Student implements Cloneable{ //关键点1
private int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone(); //关键点2
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
}
public class Test {
public static void main(String args[]) {
Student stu1 = new Student();
stu1.setNumber(12345);
Student stu2 = (Student)stu1.clone(); //关键点3
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
stu2.setNumber(54321);
System.out.println("学生1:" + stu1.getNumber());
System.out.println("学生2:" + stu2.getNumber());
}
}
System.out.println(stu1 == stu2); // false 说明这两个不是同一个对象
在浅克隆中,如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
简单来说,在浅克隆中,当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有复制。 在Java语言中,通过覆盖Object类的**clone()**方法可以实现浅克隆。
- 深克隆
在深克隆中,无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。简单来说,在深克隆中,除了对象本身被复制外,对象所包含的所有成员变量也将复制。
在Java语言中,如果需要实现深克隆,可以通过覆盖Object类的clone()方法实现,也可以通过序列化(Serialization)等方式来实现。
4、序列化
如果引用类型里面还包含很多引用类型,或者内层引用类型的类里面又包含引用类型,使用clone方法就会很麻烦。这时我们可以用序列化的方式来实现对象的深克隆。
序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。
5、总结实现对象克隆有两种方式:
1. 实现Cloneable接口并重写Object类中的clone()方法;
2. 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
未完待续…