抽象类和接口

来源:互联网 发布:mac guid分区方案 编辑:程序博客网 时间:2024/05/17 22:01

曾经在校招的时候被问到抽象类和接口的区别和使用选择,无奈当时我主攻的是C++,因而对接口几无所知,自然也没回答上来。
前些时候看《设计模式》的,其中说到继承某个类和实现一个接口可以用两个关系来表示:is-a和has-a。也就是说,类A继承类B,表示A is a B;而类A实现接口C,意味着A has a C,可以理解为A具有什么样的能力。is-a和has-a总结的相当好,设计模式中推荐尽可能地使用实现接口(has-a)。

Java语言本身,类只能单继承,因而实际中我们也是更多地选择使用实现接口。

接口

早前我误认为接口不可以有默认实现以及不可以有定义变量,其实这都是不对的,接口中方法可以有默认的实现,只需要在方法前加上default关键字就可以;接口中的变量都是static final的,这不需要使用static或final关键字,因为它就是static final的,无论你写或者不写,字节码中也可以很清楚地看出。一个简单的接口定义如下:

public interface Interface {    int a = 0;    static int b = 0;    int foo();    default int foo2() {        return 0;    }}

它的字节码如下:

{  public static final int a;    descriptor: I    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL    ConstantValue: int 0  public static final int b;    descriptor: I    flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL    ConstantValue: int 0  public abstract int foo();    descriptor: ()I    flags: ACC_PUBLIC, ACC_ABSTRACT  public int foo2();    descriptor: ()I    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: iconst_0         1: ireturn      LineNumberTable:        line 12: 0}SourceFile: "Interface.java"

抽象类

相比接口,Java语言对抽象类的使用更加自由一些,默认的方法实现、更自由的变量定义。因为Java的类是单继承的,一个类不能继承多个类,接口也从另一个角度实现了“多继承”。
一个简单的抽象类定义如下:

public abstract class Abstract {    int a;    static int b;    final int c = 0;    public abstract int foo();    public int foo2() {        return 0;    }}

字节码如下:

{    int a;    descriptor: I    flags:  static int b;    descriptor: I    flags: ACC_STATIC  final int c;    descriptor: I    flags: ACC_FINAL    ConstantValue: int 0  public abstractcls.Abstract();    descriptor: ()V    flags: ACC_PUBLIC    Code:      stack=2, locals=1, args_size=1         0: aload_0         1: invokespecial #1                  // Method java/lang/Object."<init>":()V         4: aload_0         5: iconst_0         6: putfield      #2                  // Field c:I         9: return      LineNumberTable:        line 3: 0        line 9: 4  public abstract int foo();    descriptor: ()I    flags: ACC_PUBLIC, ACC_ABSTRACT  public int foo2();    descriptor: ()I    flags: ACC_PUBLIC    Code:      stack=1, locals=1, args_size=1         0: iconst_0         1: ireturn      LineNumberTable:        line 14: 0}SourceFile: "Abstract.java"

总结

如何选择使用抽象类还是接口呢?
我的一些不成熟的观点:
1、抽象类一般是名词性的,表示事物的,接口表示能力,一般来讲是动词性的;
2、没有特别问题的,优先使用接口或许是一个更好的选择。

原创粉丝点击