Java SE知识点七:抽象类和接口

1. 抽象类

1.1 抽象类概念

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果 一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

比如: 一个图形类,因为图形包括很多,圆,三角形,矩形。所以,图形类就可以设置成抽象类,因为它没办法描述一个具体的图形。

1.2 抽象类语法

要使一个类称为抽象类,需要用到 abstract 关键字。

public abstract class Shape {
    // 抽象方法:被abstract修饰的方法,没有方法体 
    abstract public void draw();
    abstract void calcArea();

    // 抽象类也是类,也可以增加普通方法和属性 
    public double getArea(){
        return area; 
    }

    protected double area; // 面积 
}

抽象类也是类,内部可以包含普通方法和属性,甚至构造方法。

1.3 抽象类特征和作用

特征:

1. 抽象类不能实例化对象

abstract class Shape {
    ....
}

.....

Shape shape = new Shape();

//error

2. 抽象方法不能用 private 修饰

abstract class Shape { 

    abstract private void draw(); //error

}

3. 抽象方法不能被 final 和 static 修饰,因为抽象方法要被子类重写

abstract class Shape { 

    abstract final void methodA(); 
    abstract public static void methodB();
    //error
}

4. 抽象类必须被继承,并且继承后子类要重写父类中的抽象方法,否则子类也是抽象类,必须要使用 abstract 修饰


abstract class Shape {

    abstract public void draw();
    abstract void calcArea ();

}

abstract class Triangle extends Shape {
    private double a; 
    private double b; 
    private double c;
    //重写
    @Override
    public void draw() {
        System.out.println("三角形:a = "+a + " b = "+b+" c = "+c);
    }

    public void calcArea(){ 
        
    }
    
}

5. 抽象类中不一定包含抽象方法,但是有抽象方法的类一定是抽象类

6. 抽象类中可以有构造方法,供子类创建对象时,初始化父类的成员变量

7. final 和 abstract 不能同时存在

8. 当一个抽象类不想被普通类继承,可以把这个普通类改为抽象类

作用:

抽象类本身不能被实例化, 要想使用, 只能创建该抽象类的子类。然后让子类重写抽象类中的抽象方法。所以,使用抽象类相当于多了一重编译器的校验。

使用抽象类的场景就如上面的代码, 实际工作不应该由父类完成, 而应由子类完成。那么此时如果不小心误用成父类了, 使用普通类编译器是不会报错的。 但是父类是抽象类就会在实例化的时候提示错误, 让我们尽早发现问题。

2. 接口

2.1 接口的概念

接口是Java中的一个特别的功能,可以根据字面意思来看,和电脑上的一些接口差不多的性质。

电脑的USB口上,可以插:U盘、鼠标、键盘...所有符合USB协议的设备。

接口就是公共的行为规范标准,大家在实现时,只要符合规范标准,就可以通用。 在Java中,接口可以看成是:多个类的公共规范,是一种引用数据类型。

2.2 接口的语法

接口需要用到 interface 关键字,在 IntelliJ IDEA 中可以在源文件中鼠标右键创建接口

//接口
public interface Iusb {
    void openDevice();
    void closeDevice();
}

接口的一些语法规则:

  • 接口中的成员变量,默认是public static final
  • 接口中的成员方法,默认是public abstract
  • 接口中不可以有普通方法(除非前面加default)
  • 接口中用static修饰的方法是可以具体实现的
  • 接口不可以通过new实例化
  • 接口可以通过关键字implements来实现接口

2.3 接口的用法

要实现接口,需要用到 implements 关键字,我们可以写一个Java文件,里面有一些设备类,然后实现这些设备的打开和关闭。

//接口的实现
class Mouse implements Iusb{
    //实现接口的方法
    @Override
    public void openDevice() {
        System.out.println("打开鼠标");
    }

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

    public void Click(){
        System.out.println("使用鼠标");
    }
}

class Keyboard implements Iusb{

    @Override
    public void openDevice() {
        System.out.println("打开键盘");
    }

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

    public void use(){
        System.out.println("使用键盘");
    }
}

class Computer implements Iusb{

    @Override
    public void openDevice() {
        System.out.println("打开电脑");
    }

    @Override
    public void closeDevice() {
        System.out.println("关闭电脑");
    }

    public void useC(){
        System.out.println("使用电脑");
    }
    //传入接口作为参数,控制接口
    public void useDevice(Iusb iusb){
        iusb.openDevice();
        if (iusb instanceof Mouse){
            Mouse mouse = (Mouse) iusb; //强转接口为鼠标,以便调用鼠标的方法
            mouse.Click();                //和父类强转子类差不多
        } else if (iusb instanceof Keyboard) {
            Keyboard keyboard = (Keyboard) iusb; //同理
            keyboard.use();
        }
        iusb.closeDevice();
    }
}

public class Device {
    public static void main(String[] args) {
        Computer computer = new Computer();
        computer.openDevice();
        computer.useC();
        //接口的具体实现
        computer.useDevice(new Mouse());
        computer.useDevice(new Keyboard());
        computer.closeDevice();
    }
}

注意,在类连接接口后,要重写接口的方法。然后在方法中传入 接口 作为参数,真正控制接口。

2.4 接口的特征

1. 接口类型是一种引用类型,不能用 new 关键字实例化。

2. 接口中每一个方法都是public的抽象方法, 即接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错,例如: private)

3. 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现,如上述代码。

4. 重写接口中方法时,不能使用默认的访问权限。因为接口中的方法是 public,所以重写时,权限不能小于接口中的权限。

5. 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量。所以,相当于常量,不能在其他类中修改。

6. 接口中不能有静态代码块和构造方法

7. 如果类没有实现接口中的所有的抽象方法(如果没有重写所有方法),则类必须设置为抽象类。

2.5 多接口

我们前面说过,继承中不支持多继承,即一个子类继承多个父类。但是在接口中,可以支持多接口,也就是一个类可以连接多个接口。

比如我们现在创建多个接口:

现在我们创建了三个接口,分别在三个文件中。

然后创建一个类,连接多个接口:

abstract class Animal {
    public String name;
    public int age;

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

    public abstract void eat();

}

class Dog extends Animal implements IRunning,ISwimming{

    public Dog(String name, int age) { //重写父类的构造方法
        super(name, age);
    }

    @Override
    public void eat() { //重写父类的方法
        System.out.println(name + "正在吃狗粮");
    }

    @Override
    public void run() { //重写接口 IRunning 的方法
        System.out.println(name + "正在奔跑");
    }

    @Override
    public void swim() { //重写接口 ISwimming 的方法
        System.out.println(name + "正在游泳");
    }
}

我们可以看到,Dog类在继承了 Animal 类后,连接了两个接口。

需要注意的是:一个类实现多个接口时,每个接口中的抽象方法都要实现,否则类必须设置为抽象类。

接口的好处就是可以让设计者不必关注具体类型,只关注某个类是否具备某种 “能力”。比如,不一定继承Animal类的一定是动物,只要需要名字或年龄的都可以继承,然后看是否具备接口的 “能力”。

2.5 接口间的继承

接口直接也是可以继承的,而且接口可以实现多继承,这是类不能实现的。

interface IRunning { 
    void run();
}

interface ISwimming { 
    void swim();
}
// 两栖的动物, 既能跑, 也能游
interface IAmphibious extends IRunning, ISwimming {
    ...
}

class Frog implements IAmphibious { 
    ...
}

以上就是接口的内容。

2.6 抽象类和接口的区别

核心区别:抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写), 而接口中不能包含普通方法, 子类必须重写所有的抽象方法.

再次提醒:抽象类存在的意义是为了让编译器更好的校验, 像 Animal 这样的类我们并不会直接使用, 而是使用它的子类. 万一不小心创建了 Animal 的实例, 编译器会及时提醒我们.

小结:

到此为止,Java SE中的重要语法都介绍的差不多了。后面还有一些比较零碎的语法,内部类,String的一些用法等。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值