抽象类和接口

正文:

抽象类:

1. 抽象类的语法形式:

只需在class前加上一个abstract关键字。

public abstract class 类名 {


}

2. 为什么会有抽象类的出现?

在我们写在一个类中写一个没有具体实现的方法,在正常类中是无法实现的,但是在抽象类中就可以实现,这大大提高了开发的效率。

3. 这种没有具体实现的方法叫作抽象方法,也需要abstract关键字来修饰,抽象方法只能出现在抽象类中,在普通类中会报错,这也是普通类和抽象类的区别所在。

4. 抽象类不能进行实例化,所以也就不能用final来修饰。

原因:被final修饰的类不能被继承,但是抽象类不能进行实体化,两者之间存在矛盾。

5. 如果一个普通类继承了这个抽象类,那么这个普通类就必须重写这个抽象类当中的所有抽象方法。如果一号抽象类继承了二号抽象类,那继承一号的普通类也要重写二号抽象类的抽象方法。

接口:

语法:

public interface 接口名 {

}

1. 接口当中的成员变量,默认是public static final修饰的,不能是别的修饰,在定义的时候任何一个关键字都可以省略。

2. 接口中的抽象方法默认都是public abstract修饰的,定义方式可与接口中的成员变量类比。

3. 接口中的方法只能是抽象方法,不能有具体实现,如果需要定义一个有具体实现的方法,需要用default或者static修饰,那么可以有具体实现。

4. 接口是不能进行实例化的。

5. 类和接口之间可以使用关键字implements来实现接口,并且类中必须实现接口中的抽象方法。

 

6. 一个接口对应一个字节码文件。

7. 如果一个类不想实现接口中的方法,那么此时这个类可以定义为抽象类,但这个抽象类如果被继承,他的子类就必须实现所有没有被实现的方法。

8. 接口的出现解决了Java不能多继承的问题。

Bird类:

public class Bird extends Animal implements IMove, ILive{
    @Override
    public void move() {
        System.out.println(this.name + "正在飞...");
    }

    @Override
    public void eat() {
        System.out.println(this.name + "正在吃虫子...");
    }

    @Override
    public void live() {
        System.out.println(this.name + "住在鸟窝里...");
    }
}

Dog类:

public class Dog extends Animal implements IMove,ILive{
    @Override
    public void move() {
        System.out.println(this.name + "正在跑...");
    }

    @Override
    public void eat() {
        System.out.println(this.name + "正在狗粮...");
    }

    @Override
    public void live() {
        System.out.println(this.name + "住在狗窝里...");
    }
}

IMove接口:

public interface IMove {
    void move();
}

ILive接口:

public interface ILive {
    void live();
}

9. 接口与接口之间也存在继承关系,也是用extends关键字。

ILive接口:

public interface ILive extends IMove{
    void live();
}

IMove接口:

public interface IMove {
    void move();
}

接下来介绍一些比较常用的接口:

comparable接口:

Student类:

public class Student{
    private String name = "xxx";
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public 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 "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

Students类:

import java.util.Arrays;


public class Students {
    Student[] students;

    public Students(Student[] students) {
        this.students = students;
    }

    public Student[] getStudents() {
        return students;
    }

    public void setStudents(Student[] students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Students{" +
                "students=" + Arrays.toString(students) +
                '}';
    }
}

如果我们想要对Student[]数组中的元素进行排序,刚开始可能会这样写:

Test类:

import java.util.Arrays;


public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("小明", 15);
        Student student2 = new Student("大宏", 12);
        Student[] students = new Student[2];
        students[0] = student1;
        students[1] = student2;
        Students students1 = new Students(students);
        System.out.println("排序前:" + students1);

        Arrays.sort(students1.students);
        System.out.println("排序后:" + students1);
    }
}

运行起来就会报错:

解决问题:

让Student类实现Comparable接口:

public class Student implements Comparable<Student>{
    private String name = "xxx";
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public 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 "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

 编译器有报错:

按住Ctrl鼠标左键点进去观察Comparable的源代码:

观察发现在Comparable接口中存在一个抽象方法,我们需要对其重写:

@Override
    public int compareTo(Student o) {
        return this.age - o.age;
    }

 编译器不报错后我们可以再次尝试运行:

将代码修改一下: 

    @Override
    public int compareTo(Student o) {
        return o.age - this.age;
    }

 运行:

发现Arrays.sort()的底层其实是compareTo() 。

那如果我们想要根据姓名来进行排序,可以这样修改:

    @Override
    public int compareTo(Student o) {
        return this.name.compareTo(o.name);
    }

运行:

观察这种方法是可行的,那就会产生一个痛点,我们只能选择一个参考系,如果想更改就只能对代码动手,这里我们引入Comparator接口可以解决这一问题:

Comparator接口:

CompareByAge类:
import java.util.Comparator;
public class CompareByAge implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getAge() - o2.getAge();
    }
}
CompareByName类:
import java.util.Comparator;
public class CompareByName implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getName().compareTo(o2.getName());
    }
}

Student类:
public class Student{
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = 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 +
                '}';
    }
}
Students类:
import java.util.Arrays;
public class Students {
    Student[] students;

    public Students(Student[] students) {
        this.students = students;
    }

    public Student[] getStudents() {
        return students;
    }

    public void setStudents(Student[] students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Students{" +
                "students=" + Arrays.toString(students) +
                '}';
    }
}

Test类:
import java.util.Arrays;
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("小明", 15);
        Student student2 = new Student("大宏", 16);
        Student[] students = new Student[]{student1,student2};
        Students students1 = new Students(students);
        System.out.println("排序前:" + students1);

        CompareByName compareByName = new CompareByName();
        Arrays.sort(students1.students, compareByName);

        System.out.println("排序后:" + students1);
    }
}

 运行结果:

 我们可以通过写成多个类来选择我们比较的根据。

Clone接口:

当我们需要创建一个一模一样的对象时可以使用Clone接口实现,举个例子:

Test类:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person("wyh", 13);
        Person person2 = (Person) person1.clone();
        System.out.println(person1);
        System.out.println(person2);
    }
}

Person类:

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

    public Person(String name, int age) {
        this.name = name;
        this.age = 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 "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

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

运行结果: 克隆成功

我们还可以去测试一下克隆的具体实现是什么样的:

Test类:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person("wyh", 13);
        Person person2 = (Person) person1.clone();
        person1.setName("tjy");
        System.out.println(person1);
        System.out.println(person2);
    }
}

 运行结果:

我们改变了person1,但person2并没有跟着改变,由此可以看出Clone是重新在堆中开辟一块空间并将值放进去的:

 深拷贝:

Test类:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException{
        Deposit deposit = new Deposit(5000);
        Person person1 = new Person("wyh", 13, deposit);
        Person person2 = (Person) person1.clone();
        person1.setName("tjy");
        System.out.println(person1);
        System.out.println(person2);
    }
}
Deposit类:
public class Deposit {
    double money;

    public Deposit(double money) {
        this.money = money;
    }
}
Person类:
public class Person implements Cloneable{
    private String name;
    private int age;
    private Deposit deposit;

    public Person(String name, int age, Deposit deposit) {
        this.name = name;
        this.age = age;
        this.deposit = deposit;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }

    public Deposit getDeposit() {
        return deposit;
    }

    public void setDeposit(Deposit deposit) {
        this.deposit = deposit;
    }

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

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

运行结果:

我们发现当一个类的成员变量中存在另一种类,在克隆的时候就会出现克隆出来后的成员变量在同一块空间。

原因:

这时候我们就需要对其深拷贝:

Test类:

public class Test {
    public static void main(String[] args) throws CloneNotSupportedException{
        Deposit deposit = new Deposit(5000);
        Person person1 = new Person("wyh", 13, deposit);
        Person person2 = (Person) person1.clone();
        person1.setName("tjy");
        System.out.println(person1);
        System.out.println(person2);
    }
}
Deposit类:
public class Deposit implements Cloneable{
    double money;

    public Deposit(double money) {
        this.money = money;
    }

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

 Person类:

public class Person implements Cloneable{
    private String name;
    private int age;
    private Deposit deposit;

    public Person(String name, int age, Deposit deposit) {
        this.name = name;
        this.age = age;
        this.deposit = deposit;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = 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;
    }

    public Deposit getDeposit() {
        return deposit;
    }

    public void setDeposit(Deposit deposit) {
        this.deposit = deposit;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person) super.clone();
        tmp.deposit = (Deposit) this.deposit.clone();
        return tmp;
    }
}

运行结果:

不再指向同一块区域,问题成功解决。

 补充:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值