你真的知道JAVA中抽象类和接口的区别么?

原文链接

详解

在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象类的优势;接口中只能有抽象的方法。

public abstract class Person {
    void eat(){
        System.out.println("it is valid");
    }
}

接口中的方法不能有具体实现,以下代码报错

public interface Person {
  /**
   * Interface abstract methods cannot have body
   */
  void eat(){
      System.out.println("it is valid");
  }
}

抽象类中定义的方法默认不是public,接口中定义的方法默认是public,如我们用main方法测试一下

public abstract class Application {
    /**
     * JVM可以正确找到main方法
     * @param args
     */
    public static void main(String[] args) {
        System.out.println("no problem");
    }
}

下面代码无法正常运行

Error: Main method not found in class com.github.Application, please define the main method as:
public static void main(String[] args)
or a JavaFX application class must extend javafx.application.Application

public abstract class Application {
    /**
     * JVM可以正确找到main方法
     * @param args
     */
    static void main(String[] args) {
        System.out.println("no problem");
    }
}

可以直接运行(JDK8)

public interface Application {
    /**
     * JVM可以正确找到main方法
     * @param args
     */
    static void main(String[] args) {
        System.out.println("no problem");
    }
}

一个类可以继承一个抽象类(JAVA的单继承),但是可以实现多个接口

抽象类中的成员变量可以不初始化,接口中的成员变量必须初始化,默认为static, final

public abstract class Person {
    //no problem
    int age;
}

报错,需要初始化

public interface Person {
    //Variable 'age' might not have been initialized
    int age;
}

接口中的变量没有必要写上static final
screenshot from 2018-07-23 19-32-54

抽象类中可以定义构造函数,但是不能实例化,至于接口的话之前说过,是不能有方法具体的实现的,故不能有构造函数

public abstract class Person {
    String name;
    String age;
    Person(String name, int age) {

    }
}

screenshot from 2018-07-23 19-38-28

速度比较

public abstract class AbstractClass {
    public abstract void say();
}
public interface Interface {
    void say();
}
public class SubClass implements Interface{

    @Override
    public void say() {
        System.out.println("github/shellhub");
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            new SubClass().say();
        }
        System.out.println(System.currentTimeMillis() - startTime);

    }
}
public class SubClass extends AbstractClass{

    @Override
    public void say() {
        System.out.println("github/shellhub");
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 1000; i++) {
            new SubClass().say();
        }
        System.out.println(System.currentTimeMillis() - startTime);

    }
}

运行10次的时间比较
* 接口
18 35 22 30 37 31 30 46 32 40
* 抽象类
22 29 28 38 33 36 38 23 28 50

最终胜利:自己判断吧,这点测试结果说明不了什么问题,这个问题不能很片面,因为有很多因素,下面贴一个SO上的回答

screenshot from 2018-07-23 20-10-09

总结

  • 在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象类的优势;接口中只能有抽象的方法。

  • 抽象类中定义的成员变量默认不是public,接口中定义的方法默认是public,

  • 一个类可以继承一个抽象类(JAVA的单继承),但是可以实现多个接口 (WTF这是区别么)

  • 抽象类中的成员变量可以不初始化,接口中的成员变量必须初始化,默认为static, final

  • 抽象类中可以定义构造函数,但是不能实例化,接口不能定义构造函数

  • 速度比较(待定)

  • 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。 如果你往接口中添加方法,那么你必须改变实现该接口的类。

  • 想到在补充…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值