区别

  • 最重要的区别是:接口的方法不可以有实现,并且是绝对的抽象方法。抽象类可以有实例方法用来实现默认行为
  • 接口中的变量申明默认是final, 而抽象类中变量申明可以是非final
  • 接口中的成员默认是public修饰,而抽象类中成员可以是private, protected等等
  • 接口通过关键字implements被其他类实现,而抽象类则是通过extends关键字被其他类扩展
  • 接口可以扩展(extends)另外一个/或多個接口,抽象类可以扩展(extends)另一个Java类并(或)实现(implements)多个Java接口
  • Java类可以实现多个接口但是只能扩展一个抽象类
  • 接口是绝对抽象而且无法实例化,抽象类也无法实例化但是如果类中有main()方法是可以被调用的
  • 与抽象类相比,接口更慢,因为它需要额外的间接寻址

使用场合

接口用来定义契约行为,也可作为两个系统间的契约进行交互。而抽象类主要用来为子类定义默认行为,也就是说所有的继承子类都需要运行相同的功能。

  • 如果我们使用继承概念,那么抽象类是个不错的选择。因为它为派生类提供了一个通用基类实现。
  • 当定义非public成员时,抽象类也是不错的选择,而接口内,所有的方法都必须是public
  • 在未来需要添加新方法时,选择抽象类更为合适。因为当我们在接口内添加新的方法时,所有实现该接口的类都需要添加新的方法
  • 如果想创建多版本的组件,那么使用抽象类。抽象类提供一个简单且方便的方式来版本转换我们的组件。通过更新基类,所有继承子类都自动被更新为新的。另一方面,若使用接口则一旦创建则无法修改。如果我们需要新版本的接口只能创建一个全新的接口。
  • 抽象类具有更佳的向后兼容性,我们可以添加新的行为而不影响原有代码,但是如果调用方使用的是接口,我们则无法修改它。
  • 如果想为组件的所有实现中提供公共的且已实现的功能,那么使用抽象类,它允许我们部分实现类。而接口不为任何成员提供任何实现。

抽象类示例

1
2
3
4
5
6
7
8
9
abstract class Car {
public void accelerate() {
System.out.println("Do something to accelerate");
}
public void applyBrakes() {
System.out.println("Do something to apply brakes");
}
public abstract void changeGears();
}

现在任意的Car类想要实例化必须实现changeGears()方法.

1
2
3
4
5
6
7
8
9
10
class Alto extends Car {
public void changeGears() {
System.out.println("Implement changeGears() method for Alto Car");
}
}
class Santro extends Car {
public void changeGears() {
System.out.println("Implement changeGears() method for Santro Car");
}
}
  • 如果我们实现的功能是对迥然不同的对象都很有用,那么使用接口。抽象类主要用作紧密相关的对象之间,然而在给非相关的类提供通用方法时,接口是更好的选择。
  • 在我们认为API在短期内不会修改时,接口是更好的选择。
  • 当我们有一些相似的多重继承时考虑使用接口,因为我们可以实现多重接口。
  • 如果我们设计小巧而简单的功能时使用接口,如果我们设计庞大的功能单元,使用抽象类。

接口示例

1
2
3
4
5
6
public interface Actor {
void perform();
}
public interface Producer {
void invest();
}

现在大多数演员都很有钱,可以制作自己的电影。如果我们使用接口而不是抽象类,那么我们可以同时实现Actor和Producer。另外,我们可以定义一个新的ActorProducer接口来扩展两者。

1
2
3
public interface ActorProducer extends Actor, Producer{
// some statements
}

参考