Java SE 抽象类和接口

1. 抽象类

简而言之,如果没有足够的信息去描述一个对象,那么这样的类就是抽象类。
抽象类用abstract来修饰。例如图型Shape类

package demo1;

public abstract class Shape {
    public abstract void draw();

}

在shape类中,我们没有足够的信息去描述这个模糊的shape,所以我们可以去将Shape类去定义为一个抽象类。
在抽象类中,内部也可以包含普通的方法和属性,但在抽象类中不能去实例化对象。在其中的抽象方法也不能被private,final,static修饰。
抽象类的作用主要是用来被继承,在被继承的类中,要重写父类中的抽象方法。除非子类也是抽象类。
通过继承抽象类Shape,在子类中重写抽象方法

package demo1;

public class Cycle extends Shape{
    @Override
    public void draw() {
        System.out.println("画一个圆形");
    }
}

而重写抽象方法后,编译器会自动进行校验,强制了子类实现抽象方法,确保了代码的正确性。

2. 接口

接口通过interface来实现,其在生活中有很多体现,例如USB的接口。

package demo2;

public interface USB {
    void openService();
    void closeService();
}

在USB接口中,定义了openService和closeService方法。其方法的固定搭配为public abstract,但是最好进行省略,保证代码的简洁性。
除此之外,在接口中,接口类型不能直接进行实例化;
接口中的方法不能进行具体的实现;
接口中的变量会被隐式地指定为public static final;
接口中不能含有静态代码块和构造方法

在USB的例子中,我们接着可以定义鼠标,键盘类通过implements来连接我们的接口USB。在鼠标键盘类中,要重写我们的接口方法,在方法中,我们就可以进行具体的功能实现。
Mouse:

package demo2;

public class Mouse implements USB{
    @Override
    public void openService() {
        System.out.println("打开鼠标");
    }
    @Override
    public void closeService() {
        System.out.println("关闭鼠标");
    }
    public void click(){
        System.out.println("点击鼠标");
    }
}

Keyboard:

package demo2;

public class Keyboard implements USB{
    @Override
    public void openService() {
        System.out.println("打开键盘");
    }
    @Override
    public void closeService() {
        System.out.println("关闭键盘");
    }
    public void input(){
        System.out.println("键盘输入");
    }
}

另外,我们可以再定义computer类,用来实现使用USB设备的功能。

package demo2;

public class Computer {
    public void Open(){
        System.out.println("打开笔记本");
    }
    public void Close(){
        System.out.println("关闭笔记本");
    }
    public void Use(USB usb){
        usb.openService();
        if(usb instanceof Mouse){
            Mouse mouse = (Mouse) usb;
            mouse.click();
        }
        else if(usb instanceof Keyboard){
            Keyboard keyboard = (Keyboard) usb;
            keyboard.input();
        }
        usb.closeService();
    }
}

值得注意的是,在Use方法中,我们接受USB类型的参数,其可能为Mouse也可能为Keyboard,所以我们要进行判断,从而实现其正确的功能。

3. 实现多个接口

我们知道,在Java中是不支持多继承的。但是一个类可以实现多个接口。
我们可以通过Animal类来进行举例。

package demo3;

public abstract class Animal {
    public String name;

    public Animal(String name) {
        this.name = name;
    }
    public abstract void eat();
}

在Animal类中,我们将其定义为抽象类,定义了抽象方法eat。
因此我们在其子类Dog类和Duck类中,必须重写eat方法。
Dog会跑步,可以定义一个接口来进行实现。但是鸭子不仅会跑,还会飞甚至会游,所以这就体现出多接口的作用。
因此,我们可以定义多个接口来实现鸭子的功能。
Duck:

package demo3;

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

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

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

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

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

IFlyable:

package demo3;

public interface IFlyable {
    void fly();
}

IRunable:

package demo3;

public interface IRunable {
    void run();
}

ISwimable:

package demo3;

public interface ISwimable {
    void swim();
}

除此之外,我们在测试类中,也可以通过这些接口来调用方法。(此处的Dog类省略)

package demo3;

public class Test2 {
    public static void CanRun(IRunable runable){
        runable.run();
    }
    public static void main(String[] args) {
        Dog dog=new Dog("旺财");
        Duck duck=new Duck("唐老鸭");

        CanRun(dog);
        CanRun(duck);
    }
}

4.Comparable和Comparator接口

假如,我们拥有一个Student类,其中定义了name和age的属性,实例化时需要通过构造方法进行传参。
如果我们实例化了若干个对象,现在想通过age进行排序,该怎么进行?
所以,我们可以通过Comparable接口来进行功能的实现。

package demo4;

import java.util.Comparator;

public class Student implements Comparable<Student> {
    public String name;
    public int age;

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

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

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

首先,当我们连接上接口后,要通过<>将所要进行排序的类输入。
其次,在其中重写campareTo方法。
最后,按升序和降序的要求调整this与o的位置。
通过测试类Test1,我们可以进行排序。

package demo4;

import java.util.Arrays;

public class Test1 {
    public static void main(String[] args) {
        Student student1=new Student("Alpha",20);
        Student student2=new Student("Bob",18);
        Student student3=new Student("Jack",22);
        Student[] students = new Student[3];
        students[0] = student1;
        students[1] = student2;
        students[2] = student3;
        System.out.println(Arrays.toString(students));
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }
}

运行结果1
但是,如果我们想通过名字进行排序,该怎么办呢?
这时我们就应该通过Comparator接口进行实现。

package demo4;

import java.util.Comparator;

public class NameCompare implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}

通过在重写方法compare中传入两个需要比较的Student,通过compareTo进行比较,就可以实现排序。
但要注意其中的返回值是int类型,所以要通过在测试类Test2中与0的大小关系进行比较。

package demo4;

public class Test2 {
    public static void main(String[] args) {
        Student student1=new Student("Alpha",20);
        Student student2=new Student("Bob",18);
        NameCompare nameCompare=new NameCompare();
        int ret1 = nameCompare.compare(student1,student2);
        System.out.println("根据姓名比较:");
        if(ret1>0){
            System.out.println("student1>student2");
        }
        else if(ret1 == 0){
            System.out.println("student1=student2");
        }
        else{
            System.out.println("student1<student2");
        }

        AgeCompare ageCompare=new AgeCompare();
        int ret2 = ageCompare.compare(student1,student2);
        System.out.println("根据年龄比较:");
        if(ret2>0){
            System.out.println("student1>student2");
        }
        else if(ret2 == 0){
            System.out.println("student1=student2");
        }
        else{
            System.out.println("student1<student2");
        }
    }
}

运行结果2
动图1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值