深入理解Java的接口与抽象类

首先,自己的理解: 接口类描述的是行为,抽象类描述的是根源;接口是对动作的抽象,抽象类是对根源的抽象。

其次,明确抽象方法:抽象方法没有方法体,abstract修饰符可修饰类、方法,不修饰字段。

一、抽象类

在了解抽象类之前,先来了解一下抽象方法。抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法的声明格式为:

abstract void fun();

抽象方法必须用abstract关键字进行修饰。抽象方法充当着占位的角色,它们的具体实现在子类中。

如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰。(但是抽象类不一定必须含有抽象方法,也就是说类即使不含抽象方法,也可以将类声明为抽象类)

因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象即不能实例化。

public abstract class ClassName {
    public abstract void fun();
}

扩展抽象类可以有两个选择:

  1. 在抽象类中定义部分抽象类方法或者不定义抽象类方法,这样就必须将子类也标记为抽象类;
  2. 定义全部的抽象方法,这样的话,子类就不是抽象的了。

需要注意的是,可以定义一个抽象类的对象变量,但是它只能引用非抽象子类的对象

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点区别

  1. 抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public。   
  2. 抽象类不能用来创建对象;
  3. 如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

在其他方面,抽象类和普通的类并没有区别。

二、接口

接口不是类,而是对类的一组需求描述。接口中所有的方法自动地属于public abstract。因此在接口中声明方法时,不必提供关键字public,不过在实现接口时,必须要声明方法为public。接口中可以包含多个方法,还可以定义变量

接口绝不能包含实例域,在JDK1.8之前,也不能在接口中实现方法(但是JDK1.8中,已经可以在接口中提供简单的方法,当然这些方法也不能引用实例域,因为接口没有实例)。

接口中可以含有变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法(JDK1.8已经可以)。

要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下:

class ClassName implements Interface1,Interface2,[....]{
}

可以看出,尽管每个类只能拥有一个超类,却可以实现多个接口。即允许一个类遵循多个特定的接口

如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。

让类实现接口,通常需要下面两个步骤:

  1. 将类声明为实现给定的接口。
  2. 对接口中的所有方法进行定义。

接口不是类,尤其不能使用new运算符实例化一个接口!接口中不能包含实例域或静态方法,但却可以包含常量。与接口中的方法都自动地设置为public一样,接口中的所有域都被自动设为public staic final。


三、接口与抽象类

1)共同点

接口和抽象类都是继承树的上层,他们的共同点如下:

  1. 都是上层的抽象层。
  2. 都不能被实例化,只用于被其他类实现和继承。
  3. 接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

2)区别

  1. 抽象类中可以包含普通方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象类的优势;接口中只能有抽象的方法public abstract。
  2. 一个类只能继承一个直接父类,这个父类可以时普通的类也可以是抽象类;但一个类可以实现多个接口,通过实现多个接口可以弥补Java单继承不足。。(java语言禁止多继承)
  3. 抽象类中的成员变量可以是各种类型的;而接口中的成员变量只能是public static final类型的;
  4. 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;
  5. 接口里只能定义静态常量,不能定义普通成员变量,抽象类里则既可以定义普通成员变量,也可以定义静态常量。
  6. 接口不能包含构造器,抽象类可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让其子类调用这些构造器来完成属于抽象类的初始化操作。
  7. 接口里面只能对方法进行声明(JDK1.8可以进行简单的实现),抽象类既可以对方法进行声明也可以对方法进行实现。
  8. 抽象类里面的抽象方法必须全部被子类实现,如果子类不能全部实现,那么子类必须也是抽象类。接口里面的方法也必须全部被子类实现,如果子类不能实现那么子类必须是抽象类。
  9. 抽象级别(从高到低):接口>抽象类>实现类。

观点:

抽象类是不能实例化的,即不能被分配内存,而static修饰的方法在类实例化之前就已经别分配了内存,这样一来矛盾就出现了:抽象类不能被分配内存,而static方法必须被分配内存。所以抽象类中不能有静态的抽象方法。这和接口是一样的,接口中的方法也只能是 public abstract修饰的,不能加上static。 


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

  • 如果你拥有一些方法并且想让它们中的一些有默认实现,那么使用抽象类吧。 
  • 如果你想实现多重继承,那么你必须使用接口。由于Java不支持多继承,子类不能够继承多个类,但可以实现多个接口。因此你就可以使用接口来解决它。 
  • 如果基本功能在不断改变,那么就需要使用抽象类。如果不断改变基本功能并且使用接口,那么就需要改变所有实现了该接口的类。

猜你喜欢

转载自blog.csdn.net/qq_27139155/article/details/79558808
今日推荐