首页 > 代码库 > 【翻译】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.