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

相关推荐
Scott9999HH3 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔3 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社4 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海4 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖5 小时前
JDK 26 新特性详解
java·开发语言
马优晨6 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117767 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao7 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
人邮异步社区8 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大8 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf