去哪儿网面试面经(2面)

#软件开发笔面经#

6.26北京时间上午10点1面

简单自我介绍,项目介绍

-----------------------------开始问些简单八股(面试题精选)--------------------------

1. 为什么要使用克隆?

想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克隆针对的是类的实例。

2. 如何实现对象克隆?

有两种方式:

1). 实现Cloneable接口并重写Object类中的clone()方法;

2). 实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,(推荐深拷贝)代码如下:

 
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
 
public class MyUtil {
 
    private MyUtil() {
        throw new AssertionError();
    }
 
    @SuppressWarnings("unchecked")
    public static <T extends Serializable> T clone(T obj) throws Exception {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bout);
        oos.writeObject(obj);
 
        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bin);
        return (T) ois.readObject();
 
        // 说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
        // 这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
    }
}

下面是测试代码:

 
import java.io.Serializable;
 
/**
 * 人类
 * @author nnngu
 *
 */
class Person implements Serializable {
    private static final long serialVersionUID = -9102017020286042305L;
 
    private String name;    // 姓名
    private int age;        // 年龄
    private Car car;        // 座驾
 
    public Person(String name, int age, Car car) {
        this.name = name;
        this.age = age;
        this.car = car;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public Car getCar() {
        return car;
    }
 
    public void setCar(Car car) {
        this.car = car;
    }
 
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", car=" + car + "]";
    }
 
}
 
/**
 * 小汽车类
 * @author nnngu
 *
 */
class Car implements Serializable {
    private static final long serialVersionUID = -5713945027627603702L;
 
    private String brand;       // 品牌
    private int maxSpeed;       // 最高时速
 
    public Car(String brand, int maxSpeed) {
        this.brand = brand;
        this.maxSpeed = maxSpeed;
    }
 
    public String getBrand() {
        return brand;
    }
 
    public void setBrand(String brand) {
        this.brand = brand;
    }
 
    public int getMaxSpeed() {
        return maxSpeed;
    }
 
    public void setMaxSpeed(int maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
 
    @Override
    public String toString() {
        return "Car [brand=" + brand + ", maxSpeed=" + maxSpeed + "]";
    }
 
}
class CloneTest {
 
    public static void main(String[] args) {
        try {
            Person p1 = new Person("郭靖", 33, new Car("Benz", 300));
            Person p2 = MyUtil.clone(p1);   // 深度克隆
            p2.getCar().setBrand("BYD");
            // 修改克隆的Person对象p2关联的汽车对象的品牌属性
            // 原来的Person对象p1关联的汽车不会受到任何影响
            // 因为在克隆Person对象时其关联的汽车对象也被克隆了
            System.out.println(p1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是好过把问题留到运行时。

------------------------------------over----------------------------------------------

#软件开发笔面经#
全部评论

相关推荐

不愿透露姓名的神秘牛友
08-16 09:00
点赞 评论 收藏
分享
#去哪儿旅行秋招#&nbsp;一天面完一二面和hr面,面完马上出结果1.自我介绍2.项目3.数据库中的表的设计?4.数据库事务的实现原理?其实问的就是ACID特性的实现原理:【原子性】实现原理:undo&nbsp;log实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。InnoDB实现回滚,靠的是undo&nbsp;log:当事务对数据库进行修改时,InnoDB会生成对应的undo&nbsp;log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo&nbsp;log中的信息将数据回滚到修改之前的样子。【持久性】在Inonodb中使用到了Buffer&nbsp;Pool来提高数据库的访问速度,但是由于buffer&nbsp;pool带来了新的问题,如果MySQL宕机,而此时Buffer&nbsp;Pool中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证。当数据修改时,除了修改Buffer&nbsp;Pool中的数据,还会在redo&nbsp;log记录这次操作;当事务提交时,会调用fsync接口对redo&nbsp;log进行刷盘。如果MySQL宕机,重启时可以读取redo&nbsp;log中的数据,对数据库进行恢复。redo&nbsp;log采用的是WAL(Write-ahead&nbsp;logging,预写式日志),所有修改先写入日志,再更新到Buffer&nbsp;Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。【隔离性,一致性】隔离性追求的是并发情形下事务之间互不干扰实现原理:锁机制行锁与表锁5.BNSE是什么?应该说的是修正的第三范式6.最新的JDK版本是什么?常用的是哪个版本7.HashMap底层?8.为什么HashMap底层采用红黑树,而不用B+树这种数据结构?9.红黑树左旋右旋?10.算法题:按照单词翻转字符串,例如I&nbsp;love&nbsp;qunar,翻转结果为qunar&nbsp;love&nbsp;I,这个写了一下,比较简单,然后扩展求I&nbsp;love&nbsp;qunar和qunar&nbsp;love&nbsp;I最长公共子串,知道是使用KMP算法,但是公式忘了,面试官就没让写了11.反问#软件开发笔面经##面经##秋招#
查看11道真题和解析 软件开发笔面经
点赞 评论 收藏
分享
2 8 评论
分享
牛客网
牛客企业服务