Java抽象类与接口实战指南

目录

一、抽象类

1.不能通过new来实例化对象

2.抽象类中如果一个方法没有具体的实现,那么这个方法用abstract修饰

3.如果一个类有抽象方法,那么这个类是抽象类,相反,如果一个类是抽象类,那么可以没有抽象方法

4.如果一个类继承了抽象类,那么必须重写这个抽象类的抽象方法

5.如果一个类继承了这个抽象类,然后不想重写抽象类当中的方法,只能把当前这个类也被abstract修饰,但要注意的是,这些抽象方法最终都会被重写!只要有其他的普通类继承这些抽象类

二、接口

[1.接口中的成员变量默认是public static final修饰的,不写的时候也是这样的,为了方便我们一般不写](#1.接口中的成员变量默认是public static final修饰的,不写的时候也是这样的,为了方便我们一般不写)

2.接口当中的方法如果要有具体的实现,只能被static或者default修饰,这些方法默认都是public

[3.接口中的方法如果没有具体实现,那么就写成抽象方法,使用public abstract修饰,public abstract为了简洁代码可以不写](#3.接口中的方法如果没有具体实现,那么就写成抽象方法,使用public abstract修饰,public abstract为了简洁代码可以不写)

4.一个类与接口的关系我们使用implements实现

5.接口可以实现多态

6.一个类可以有多个接口

7.接口可以实现多继承

8.通过接口实现自定义类型比较

第一种使用Comparable接口进行比较

第二种使用Comparator接口进行比较

9.通过接口实现自定义类型排序

10.克隆接口

浅拷贝与深拷贝

1.浅拷贝

2.深拷贝


一、抽象类

下面是关于抽象类的一些注意事项

1.不能通过new来实例化对象
2.抽象类中如果一个方法没有具体的实现,那么这个方法用abstract修饰
3.如果一个类有抽象方法,那么这个类是抽象类,相反,如果一个类是抽象类,那么可以没有抽象方法
4.如果一个类继承了抽象类,那么必须重写这个抽象类的抽象方法
java 复制代码
public abstract class Animal {
    public String name;
    public int age;

    public abstract void shout();

    public void sleep() {
        System.out.println(this.name + "正在睡觉....");
    }
}

class Cat extends Animal{
    @Override
    public void shout() {
        System.out.println(this.name+"喵喵喵");
    }
}
5.如果一个类继承了这个抽象类,然后不想重写抽象类当中的方法,只能把当前这个类也被abstract修饰,但要注意的是,这些抽象方法最终都会被重写!只要有其他的普通类继承这些抽象类

二、接口

在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

接口使用interface关键字定义,和抽象类相同,不能被实例化。

1.接口中的成员变量默认是public static final修饰的,不写的时候也是这样的,为了方便我们一般不写
java 复制代码
public interface Canfly {
    public static final int a = 1;
    int b =2;
}
2.接口当中的方法如果要有具体的实现,只能被static或者default修饰,这些方法默认都是public
java 复制代码
public interface Canfly { 
    public static void fly(){
        System.out.println("可以飞....");
    }
}


public interface CanRun {
    public default void run(){
        System.out.println("可以跑...");
    }
}
3.接口中的方法如果没有具体实现,那么就写成抽象方法,使用public abstract修饰,public abstract为了简洁代码可以不写
java 复制代码
public interface Canswim {
    public abstract void swim(); 
}
4.一个类与接口的关系我们使用implements实现

实现该接口以后,就要重写该接口中的抽象方法

请实现笔记本电脑使用USB鼠标、USB键盘的例子

  1. USB接口:包含打开设备、关闭设备功能

  2. 笔记本类:包含开机功能、关机功能、使用USB设备功能

  3. 鼠标类:实现USB接口,并具备点击功能

  4. 键盘类:实现USB接口,并具备输入功能

java 复制代码
public interface USB {
    void open();
    void close();
}
java 复制代码
public class Mouse implements USB{
    @Override
    public void open() {
        System.out.println("打开鼠标");
    }

    @Override
    public void close() {
        System.out.println("关闭鼠标");
    }

    public void click(){
        System.out.println("点击鼠标");
    }
}
java 复制代码
public class Keyboard implements USB{
    @Override
    public void open() {
        System.out.println("打开键盘");
    }

    @Override
    public void close() {
        System.out.println("关闭键盘");
    }

    public void input(){
        System.out.println("键盘输入");
    }
}
java 复制代码
public class Computer{

    public void Poweron() {
        System.out.println("打开笔记本");
    }

    public void Poweroff() {
        System.out.println("关闭笔记本");
    }

    public void useDrived(USB usb){
        if(usb instanceof Keyboard){
            Keyboard keyboard = (Keyboard) usb;
            keyboard.input();
        }
        if(usb instanceof Mouse){
            Mouse mouse = (Mouse) usb;
            mouse.click();
        }
        usb.close();
    }
}
java 复制代码
public class Test {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.Poweron();

        computer.useDrived(new Keyboard());
        computer.useDrived(new Mouse());

        computer.Poweroff();
    }
}
5.接口可以实现多态

与继承实现的动态绑定不同,接口不关心你传过来的是什么类型,只要你的类型实现了该接口,

就具备了该功能

java 复制代码
public interface IRunable {
    void run();
}
java 复制代码
public interface ISwimable {
    void swim();
}
java 复制代码
public class Animal {
    public String name;
    public int age;

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

class Dog extends Animal implements IRunable,ISwimable{

    public Dog(String name, int age) {
        super(name, age);
    }


    @Override
    public void run() {
        System.out.println(this.name+"正在跑");
    }

    @Override
    public void swim() {
        System.out.println(this.name+"正在游泳");
    }
}

class Duck extends Animal implements IRunable,ISwimable{
    public Duck(String name, int age) {
        super(name, age);
    }

    @Override
    public void run() {
        System.out.println(this.name+"正在跑");
    }

    @Override
    public void swim() {
        System.out.println(this.name+"正在游泳");
    }
}
java 复制代码
public class Test {
    public static void walk(IRunable runable){
        runable.run();
    }
    public static void swim(ISwimable swimable){
        swimable.swim();
    }

    public static void main(String[] args) {
        Dog dog = new Dog("wangcai",6);
        Duck duck = new Duck("xiaoya",3);

        walk(dog);
        walk(duck);
    }
}
6.一个类可以有多个接口
java 复制代码
public interface IRunable {
    void run();
}
java 复制代码
public interface ISwimable {
    void swim();
}
java 复制代码
public class Animal {
    public String name;
    public int age;

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

class Duck extends Animal implements IRunable,ISwimable{
    public Duck(String name, int age) {
        super(name, age);
    }

    @Override
    public void run() {
        System.out.println(this.name+"正在跑");
    }

    @Override
    public void swim() {
        System.out.println(this.name+"正在游泳");
    }
}
7.接口可以实现多继承
java 复制代码
interface A {
    void test1();
}

interface B{
    void test2();
}

interface C extends A,B{
    void test3();
}
public class Test1 implements C {

    @Override
    public void test1() {
        
    }

    @Override
    public void test2() {

    }

    @Override
    public void test3() {

    }
}
8.通过接口实现自定义类型比较
第一种使用Comparable接口进行比较
java 复制代码
public class Student implements Comparable<Student>{
    public String name;
    public int age;
    public int score;

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

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

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }
}
java 复制代码
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("张三",19,90);
        Student student2 = new Student("李四",15,60);

        if(student1.compareTo(student2)>0){
            System.out.println("student1>student2");
        }else {
            System.out.println("student1<student2");
        }

    }
}

使用Comparable接口对Student类进行比较,但是使用Comparable接口有一个缺点只能对Student类的某个属性进行比较,比较限制,方法总比困难多,这里给出第二种比较方式,使用Comparator接口

第二种使用Comparator接口进行比较

使用Comparator接口,可以实现Student类任意属性的比较

java 复制代码
public class Student{
    public String name;
    public int age;
    public int score;

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

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

}
java 复制代码
public class NameComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
java 复制代码
public class AgeComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.age-o2.age;
    }
}
java 复制代码
public class ScoreComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.score-o2.score;
    }
}
java 复制代码
public class Test {
    public static void main(String[] args) {
        Student student1 = new Student("张三",19,90);
        Student student2 = new Student("李四",15,60);

        AgeComparator ageComparator = new AgeComparator();
        ScoreComparator scoreComparator = new ScoreComparator();
        NameComparator nameComparator = new NameComparator();

        if(ageComparator.compare(student1,student2)>0){
            System.out.println("student1>student2");
        }else {
            System.out.println("student1<student2");
        }

        System.out.println("================================");

        if(scoreComparator.compare(student1,student2)>0){
            System.out.println("student1>student2");
        }else {
            System.out.println("student1<student2");
        }

        System.out.println("================================");

        if(nameComparator.compare(student1,student2)>0){
            System.out.println("student1>student2");
        }else {
            System.out.println("student1<student2");
        }

    }
}
9.通过接口实现自定义类型排序

要实现给自定义类型排序,自定义类型内部肯定需要有比较规则,使用前面讲过的Compar接口,定义比较的规则为年龄

java 复制代码
public class Student implements Comparable<Student>{
    public String name;
    public int age;
    public int score;

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

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

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }
}
java 复制代码
public class Test1 {
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]=new Student("zhangsan",12,78);
        students[1]=new Student("lisi",17,98);
        students[2]=new Student("wangwu",14,56);

        Arrays.sort(students);
        System.out.println(Arrays.toString(students));

    }
}

还有一种方法,使用Comparator接口,在前者基础上,在 Arrays.sort(students)后面加上比较器,

比较规则是先对Comparable接口内部定义的比较方式进行比较,再对Comparator接口内部定义的比较方式进行比较

java 复制代码
public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]=new Student("zhangsan",12,78);
        students[1]=new Student("lisi",17,98);
        students[2]=new Student("wangwu",14,56);

        ScoreComparator scoreComparator = new ScoreComparator();
        
        Arrays.sort(students,scoreComparator);
        System.out.println(Arrays.toString(students));

    }

我们可以自己写一个排序方法bubbleSort(),内部通过接口实现排序

java 复制代码
public class Student implements Comparable<Student>{
    public String name;
    public int age;
    public int score;

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

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

    @Override
    public int compareTo(Student o) {
        return this.age-o.age;
    }
}
java 复制代码
public class Test1 {
    public static void bubbleSort(Comparable[] comparables){
        for (int i = 0; i <comparables.length-1 ; i++) {
            for (int j = 0; j < comparables.length-1-i; j++) {
                if(comparables[j].compareTo(comparables[j+1])>0){
                    Comparable tmp =comparables[j];
                    comparables[j]=comparables[j+1];
                    comparables[j+1]=tmp;
                }
            }
        }
    }
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0]=new Student("zhangsan",12,78);
        students[1]=new Student("lisi",17,98);
        students[2]=new Student("wangwu",14,56);
        bubbleSort(students);
        System.out.println(Arrays.toString(students));
    }
10.克隆接口

当我们想要实现克隆时,必须要有克隆接口Cloneable,我们定义一个类person实现克隆接口,创建person1对象,并且在创建一个person2对象负责接收person1的克隆,当我们调用clone方法时,发现调用不了

当我们搜索Object类时,发现clone方法由protected修饰

protected的访问权限为同个包的同个类/同个包的不同类/不同包中的子类,clone方法在package java.lang中,而Person在demo2这个包中无法调用,我们需要到Person类中重写clone方法

java 复制代码
public class Person implements Cloneable{
    public String name;

    public Person(String name) {
        this.name = name;
    }

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

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

需要注意的是需要在main函数后加上throws异常处理

这时可以调用clone方法了,但是还是报错那是因为右边是Object类型,需要强制转换为Person类型,这样就不会报错了

java 复制代码
package Demo2;

public class Person implements Cloneable{
    public String name;

    public Person(String name) {
        this.name = name;
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
java 复制代码
package Demo2;

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

克隆实现基本流程

浅拷贝与深拷贝
1.浅拷贝
java 复制代码
class Money{
    public double money = 11.1;
}
public class Person implements Cloneable{
    public String name;
    public Money m;

    public Person(String name) {
        this.name = name;
        this.m = new Money();
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
java 复制代码
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person("zhangsan");
        Person person2 = (Person) person1.clone();

        System.out.println(person1.m.money);
        System.out.println(person2.m.money);

        System.out.println("========================");

        person2.m.money = 99.9;
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
    }
}

通过修改person2.m.money,打印person1.m.money和person2.m.money结果都为99.9

2.深拷贝
java 复制代码
class Money implements Cloneable{
    public double money = 11.1;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
public class Person implements Cloneable{
    public String name;
    public Money m;

    public Person(String name) {
        this.name = name;
        this.m = new Money();
    }

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person tmp = (Person) super.clone();
        tmp.m = (Money) this.m.clone();
        return tmp;
    }
}
java 复制代码
public class Test2 {
    public static void main(String[] args) throws CloneNotSupportedException{
        Person person1 = new Person("zhangsan");
        Person person2 = (Person) person1.clone();

        System.out.println(person1.m.money);
        System.out.println(person2.m.money);

        System.out.println("========================");

        person2.m.money = 99.9;
        System.out.println(person1.m.money);
        System.out.println(person2.m.money);
    }
}

通过修改person2.m.money,打印person1.m.money和person2.m.money结果都为11.1,99.9

相关推荐
无籽西瓜a2 小时前
详解Stream流特性与常用操作
java
CS创新实验室2 小时前
《计算机网络》深入学:虚拟局域网(VLAN)技术与应用
开发语言·计算机网络·php·vlan·虚拟局域网
少控科技2 小时前
QT高阶日记011
开发语言·qt
昊坤说不出的梦2 小时前
互联网大厂Java面试实录:核心技术栈深度解析与业务场景落地
java·大数据·spring boot·微服务·ai·技术栈·互联网面试
tkevinjd2 小时前
2-初识JS
开发语言·前端·javascript·ecmascript·dom
mr_orange_klj2 小时前
关于K8s身份权限的AI问答(豆包)
java·容器·kubernetes
徐先生 @_@|||2 小时前
JetBrains 公司的产品策略和技术架构(IDEA(Java)和Pycharm(Python)的编辑器)
java·python·架构
鱼跃鹰飞2 小时前
面试题:说一下Spring的事务传播特性
java·数据库·spring
AAD555888992 小时前
光伏组件检测与识别基于RPN_X101-FPN模型实现含Python源码_1
开发语言·python