2021-07-15

1. 浅克隆和深克隆
首先要想克隆的类,需要实现Cloneable接口。这个接口是一个标志接口,没有任何内容。需要克隆的类要override clone()方法,默认是浅克隆,即super.clone()。那么会把对象和对象中的基本数据类型的值复制一份,但是引用类型的变量无法复制,即克隆之后,原来的那个引用还是指向同一个。比如:

public class Teacher implements Cloneable {
    private String name;
    private int age;
    Student student;

    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;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", student=" + student +
                '}';
    }

    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    @Override
    public Teacher clone() throws CloneNotSupportedException {
//        return (Teacher)super.clone();浅克隆方法
        Teacher tea = (Teacher)super.clone();
        Student stu = (Student)tea.getStudent().clone();
        tea.setStudent(stu);
        return tea;
    }
}

public class Student implements Cloneable {
    private String name;
    private int age;

    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;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

测试:

public class cloneTest {
    public static void main(String[]agrs) throws CloneNotSupportedException {
        cloneTest c = new cloneTest();
        Student stu1 = new Student();
        stu1.setAge(18);
        stu1.setName("张三");


        Teacher tea1 = new Teacher();
        tea1.setAge(30);
        tea1.setName("老师");
        tea1.setStudent(stu1);

        Teacher tea2 = (Teacher)tea1.clone();
        tea2.setName("新的老师");
        tea2.setAge(25);
        Student stu2 = tea2.getStudent();
        stu2.setName("李四");
        stu2.setAge(25);

        System.out.println(tea1);
        System.out.println(tea2);
    }

}

当使用浅克隆的时候,会发现输出的两个teacher对象的student是同一个对象。使用深克隆的时候,tea2的student对象更改属性并不影响tea1的student,说明引用变量复制成功。

使用克隆的tip:
1:要进行克隆的类必须实现Cloneable接口
2:必须重写clone方法,并抛出异常,clone方法需要用public修饰
3:对于要实现深克隆的类,不能简单使用super.clone(),要重写clone方法,并对要深克隆的引用类型变量进行克隆。

2. 抽象类和接口

从组成来看
抽象类不能被实例化,可以有普通成员变量,可以有抽象方法,可以有普通方法,有构造函数,可以有静态成员变量和方法,但不能是抽象的;接口不能被实例化,不能有普通成员,所有成员默认为public static final,方法只能是Public abstract的,没有构造函数,不能有静态方法(abstract和static不能共存)。所有类继承抽象类如果没有完全实现其中的抽象方法,那么这个子类也是抽象类。

关于抽象类的构造函数
既然抽象类不能被实例化为什么还要有构造函数
子类是可以实例化的,在子类实例化的时候,往往需要对父类中的属性进行初始化,在这个时候会调用super()来使用父类的构造函数。

接口和抽象类的使用
接口更多的是在系统架构上发挥作用,实现模块间的通信规则,抽象类更多的是实现代码的重用。

3:super.getClass()

根据Object类的源码,getClass方法用final修饰,子类不能覆盖这个方法,这个方法实际上是返回当前正在运行的类,如果加上getName就是当前运行调用方法的类的名字,而与父类毫无关系。如果想获取父类的类名可以:getClass().getSuperClass().getName()

4. String s = “Hello”;s = s + " world!";这两行代码执行后,原始的String对象中的内容到底变了没有?

第一行代码:String s = “Hello”;将会在字符串常量池中寻找是否存在内容为Hello的字符串,如果有,s指向它,否则创建一个新的String对象,放入常量池和堆中。
第二行代码:s = s + “world!”;由于String 属于不可变类,因此一开始创建出来内容为Hello的字符串依旧不变,变的只是s的指向,s将会指向一个叫做Hello world!的字符串。

由于每次修改String的内容,实际上都是在创建新的String对象,因此开销会比较大,最好是使用StringBuffer,StringBuffer属于可变类,而且多线程安全。

5.String和StringBuffer
String重写了equals方法,所以new String(“abc”).equals(new String(“abc”))结果为true,而StringBuffer没有重写equals方法。String属于不可变类,当对String进行改变的时候,会创建新的对象,而StringBuffer不会。

6.StringBuffer和StringBuilder
StringBuffer中的所有方法都是用synchronized修饰的,因此是线程安全的,而StringBuilder没有,所以StringBuilder的效率要远大于StringBuffer。StringBuffer的toString方法每次都会获取缓冲区的toStringCache,但是StringBuilder的toString方法每次都会复制一遍字符数组,再构建字符串。

7::内部类访问局部变量的时候,局部变量必须用final修饰
个人理解,局部变量在方法访问结束的时候,生命周期就会消亡,但是内部类和外部类具有相同的生命周期,如果内部类要访问局部变量,局部变量提前消亡了,就会导致错误,因此用final修饰可以让局部变量和内部类具有相同的生命周期。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值