Bootstrap

Java中的抽象类与接口

目录

一、抽象类

1.1 抽象方法

1.2 抽象类的定义

二、接口

2.1 接口的定义

2.2 接口的使用

2.3 接口与抽象类的异同

2.3.1 相同点

2.3.2 不同点


一、抽象类

1.1 抽象方法

当一个方法只有方法的声明,没有方法的实现时,这个方法就只能被 abstract 关键字修改。而被 abstract 关键字修饰的方法就叫抽象方法。

abstract class Father {
    String name;

    public abstract void sayHi();
}
class Son extends Father {
    public Son() {

    }
    public Son(String name) {
        this.name = name;
    }
    public void sayHi() {
        System.out.println(name);
    }
}

public class FinalDemo {
    public static void main(String[] args) {
        Son son = new Son("小华");
        son.sayHi();
    }
}

当父类中声明的方法,但又不确定子类如何去实现这个方法时,就需要将父类中的方法定义为抽象方法。此时,父类中的这个抽象方法就是一种约定,或者叫规则。

1.2 抽象类的定义

一个类如果被 abstract 关键字修饰,那么这个类就叫抽象类。抽象类必须有子类,因为抽象类不能直接实例化。

abstract class Father {
    String name;

    public abstract void sayHi();
    public abstract void sayBye();
}
abstract class Son extends Father {
    public Son() {

    }
    public Son(String name) {
        this.name = name;
    }
   /* public void sayBye() {

    }*/
    public void sayHi() {
        System.out.println(name);
    }
}

如果某个子类继承了抽象类,那么它必须实现抽象类中的所有抽象方法,如果没有实现所有的抽象方法,那么它也只能是抽象类。

注意:因为被final修饰的类必须不能被继承,而被abstract关键字修饰的类必须有子类。所以它们两个不能同时使用。即抽象类不能被final修饰。

二、接口

2.1 接口的定义

如果一个抽象类中所有的方法都是抽象方法,那么这个类就无需定义成抽象类,而是定义为接口。

在 JDK1.8 之前,接口中只能声明抽象方法,而在 JDK1.8 中定义默认方法和静态方法,这两种方法都是实现了的。如果定义为接口,那么需要使用 interface 关键字来进行修饰。例如:

public interface InterfaceDemo {
    public static final String company = "open";
    public abstract void say();
    public abstract void show();
    public abstract int getAge();
}

2.2 接口的使用

在上面的接口,所有的方法都是抽象方法。对接口而言,由于都是抽象方法,因此,对象 public abstrace 关键字是可以省略。

public interface InterfaceDemo {
    String company = "open";
    void say();
    void show();
    int getAge();
}

接口中的方法都是抽象的,公共的方法;接口的属性都是静态常量。

在 JDK1.8中,定义默认方法和静态方法。默认方法是使用 defalut 关键字来修饰的,而静态方法是使用 static 关键字来修饰的。

public interface InterfaceDemo {
    String company = "open";
    void say();
    void show();
    int getAge();

    default void run() {
        System.out.println("run() 方法,它是一个默认方法");
    }

    static String print(String str) {
        return str.toUpperCase();
    }
}

接口定义后,不能直接实例化,需要有子类,子类通过implements关键字来实现接口。

public class InterADemo implements InterA {
    @Override
    public void say() {
        System.out.println("say()");
    }

    @Override
    public void show() {
        System.out.println("show()");
    }

    @Override
    public int getAge() {
        return 18;
    }

    public static void main(String[] args) {
        InterADemo id = new InterADemo();
        id.say();
        id.show();
        System.out.println(id.getAge());
        id.run();
    }
}

2.3 接口与抽象类的异同

2.3.1 相同点

  1. 接口和抽象类都不能直接实例化,都需要有子类

  2. 它们都是多态前提,多态前提是要么继承,要么实现,另一个就是要重写

2.3.2 不同点

  1. 抽象类是使用 abstract 关键字来修饰,而接口是使用 interface 关键字来修饰

  2. 抽象类子类使用 extends 来继承,而接口的子类是使用 implements 来实现

  3. 抽象类中是可以有抽象方法也可以没有抽象方法,但接口中不能有非抽象方法

  4. 抽象类中可以有构造方法,而接口中是没有构造方法的

  5. 抽象类中的属性可以不是常量,而接口中所有属性都是常量

  6. 子类只能继承一个父类,但是可以实现多个接口。如果一个类既要继承又要实现,那么是先继承后实现

例如:

abstract class AbsTest {
    private String name;
    public final int age = 18;

    public AbsTest() {

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

}

interface InterB {
    String name = "张三";
    // 在接口中不允许有构造方法
    /*public InterB() {

    }*/
}

interface InterC {

}

interface InterD extends InterC {
    
}

public class AbstractDemo extends AbsTest implements InterB, InterC {
}

在上面的例子中我们知道,接口与接口也可以通过extends进行继承。

注意:

在接口中是支持多继承的

interface InterB {
String name = "张三";
// 在接口中不允许有构造方法
/*public InterB() {

}*/
}

interface InterC {

}

interface InterD extends InterC, InterB {

}

这是为什么呢?

1)对于普通的类:

// Java中为什么不支持多继承
class ClassA {
public void show() {
  System.out.println("ClassA.show");
}
}
class ClassB {
public void show() {
  System.out.println("ClassB.show");
}
}
public class ExtendsDemo extends ClassA, ClassB {
public static void main(String[] args) {
  ExtendsDemo ed = new ExtendsDemo();
  ed.show();
}
}

由于JVM不知道调用show()方法时执行的是哪个类中的,所以Java避免这种不确定因素,不支持多继承。

2)在接口中;

// 接口支持多继承
interface InterAA {
void show();
}
interface InterBB {
void show();
}

interface InterCC extends InterAA, InterBB {
void show();
}

public class ExtendsDemo2 implements InterCC  {
@Override
public void show() {
  System.out.println("ExtendsDemo2.show");
}
}

在接口中支持多继承的原因是:接口中的方法只是声明没有实现,也就是说,在接口中只是定义一种规范,具体的实现在子类中完成。所以就不存在不确定的因素,所以支持多继承 。

;