首页 > 代码库 > 【翻译】JAVA中抽象类和接口的区别

【翻译】JAVA中抽象类和接口的区别

不知道有没有人翻译过了,这篇是挺简单的,权当复习一遍内容吧。

很多常见的面试问题如“抽象类和接口有什么区别”,“你在什么时候用抽象类什么时候用接口”。所以在这篇文章里面,我们会讨论一下这个话题。

在开始讨论它们的区别之前,我们先看看它们的介绍。


Abstract class 抽象类

抽象类被用来抽象出子类的共同特征。它是不能被实例化的,它只能被子类继承作为超类使用。抽象类被用作它的子类下的层次结构创建模板(Abstract classes are used to create template  for its sub classes down the hierarchy.)。

来用JDK的自带GenericServlet类举一个例子:

  public abstract class GenericServlet implements  Servlet, ServletConfig,Serializable{    
       // 抽象方法   
        abstract  void service(ServletRequest req, ServletResponse res) ; 
        void init()     {
             // 方法的实现      
         }  
           // 其它Servlet的关联方法   
    }

当HttpServlet继承了 Generic servlet, 它要提供service() 方法的实现(因为父类service()方法是抽象方法,子类必须实现):

  public class HttpServlet extends GenericServlet
  {
           void service(ServletRequest req, ServletResponse res)
           {
               // 实现
           }
    
            protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
            {
                // 实现
            }
    
            protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
            {
                // 实现
            }
    
    // HttpServlet其它关联方法
  }


Interface 接口

一个接口是一系列抽象方法的集合。当一个类实现一个接口,就会因此继承到这个接口里面的抽象方法。所以它就像签了一个合约,你实现了这个接口就相当于同意了这个合约,你就需要去使用它的方法。当然,这只是一个模式,它自身是不能做任何事情的。

来看一个Externalizable 接口的例子:

public interface Externalizable
extends Serializable
{

    void writeExternal(ObjectOutput out)
            throws IOException;
    void readExternal(ObjectInput in)
            throws IOException,
            ClassNotFoundException;
}

当你实现这个接口,你需要去实现上面两个方法:

public class Employee implements Externalizable{ 

 int employeeId;
 String employeeName;


 @Override
 public void readExternal(ObjectInput in) throws IOException,
 ClassNotFoundException {  employeeId=in.readInt();
  employeeName=(String) in.readObject();
  
 } @Override
 public void writeExternal(ObjectOutput out) throws IOException {

  out.writeInt(employeeId);
  out.writeObject(employeeName); }
}

Abstract class vs Interface 抽象类和接口的区别

比较参数 抽象类 接口
默认方法实现 可以有默认的方法实现 接口是单纯的抽象,没有实现
实现

子类使用 extends 关键字去集成一个抽象类,需要在子类里面对抽象类声明的所有抽象方法提供实现方法,如果子类也是抽象类则不需要。

子类使用 implements 关键字去实现接口,需要在子类里面对接口声明的所有方法提供实现方法。

构造器 抽象类可以有构造器 接口不能有构造器
和普通java类的区别

抽象类大部分和普通java类一样除了不能实例化它。

接口是完全不同的类型

访问修饰符

抽象类可以有public protected private和default修饰符

接口方法默认都是public,不能使用其他修饰符。

Main() 方法

抽象类可以有main() 方法,所以我们可以执行它

接口不能有main()方法,所以我们不能执行它

多重继承

抽象类可以集成一个其他的类和实现一个或多个接口

接口只能继承一个或多个接口

速度 比接口快

接口相对较慢,它要用一定时间去找类里面的实现方法

增加新的方法

如果想要给抽象类增加新的方法,你可以对它提供默认的实现,因此你不需要去改变你当前的代码

If you add new method to interface, you have to change the classes which are implementing that interface

如果你要对接口增加新的方法,你需要去修改实现了该接口的类。

什么时候使用抽象类和接口:

  • 如果你需要大量的方法并且希望它们当中某些方法有默认实现,那么选择抽象类最好不过

  • 如果你想要实现多重继承,那就需要使用接口。因为java本身是不支持多重继承的,子类不能够继承多于一个父类,但是可以实现多个接口,因此你可以使用接口来间接达到多重继承。

  • 如果你的基本抽象内容经常改变,那么你应该使用抽象类,因为如果你的基本抽象内容经常改变而且使用接口的话,那么你就必须要连带把实现了这个接口的其它类都一并修改。


java 8里面的default和static方法介绍

Oracle 一直试图在接口中引进default和static方法的概念用以弥补抽象类和接口之间的间隙。所以现在我们可以在接口中提供方法的default实现而不强迫子类去实现它。我将会再下一个post里谈谈这个新东西。


相关链接:Difference between Abstract Class and Interface in java from our JCG partner Arpit Mandliya at the Java frameworks and design patterns for beginners blog.