Java的抽象类和接口

一.抽象类

首先看抽象方法:抽象方法只有方法签名,没有方法的实现。并且被abstract修饰。 例如:  abstract void test();

有抽象方法的类只能被定义为抽象类,抽象类里可以没有抽象方法

抽象类的规则

抽象类必须使用abstract修饰符来修饰

抽象类不能被实例化,无法使用new关键字来创建实例,即使抽象类中没有抽象方法,也不可以创建实例。只能当做父类被其他子类继承。

抽象类可以包含成员变量方法(普通方法和抽象方法都可以)、构造器(不能用于创建实例,主要是被子类调用)、初始化块内部类(接口、枚举)5种成分

含有抽象方法的类。(直接定义了一个抽象方法;或者继承了一个抽象父类,但没有完全实现父类包含的抽象方法;或者实现了一个接口,但没有完全实现接口包含的抽象方法)这三种情况,只能被定义成抽象类。

当使用abstract修饰类时,表明这个类只能被继承;当使用abstract修饰方法时,表明这个方法必须由子类提供实现(即重写),因此abstract方法不能定义为private访问权限(用public和protected修饰),即private和abstract不能同时修饰方法。而final修饰的类不能被继承,final修饰的方法不能被重写。因此,final和abstract永远不能同时使用。

static和abstract不能同时修改某个方法,即没有所谓的类抽象方法。

抽象类的作用:

作为子类的模板,从而避免了子类设计的随意性。抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会大致保留抽象类的行为。

二. 接口

基本语法如下:

[修饰符] interface 接口名 extends 父接口1, 父接口2...

{

  零到多个常量定义... (因为接口是一种规范,不能包含构造器和初始化块定义。只能是静态常量。)

  零到多个抽象方法定义...

  零到多个内部类、内部接口、内部枚举定义...

  零到多个默认方法或类方法定义... (只有在java8以上版本才允许)

}

说明:

 修饰符可以是public或者省略,如果省略了public访问控制符,则默认采用包权限访问控制符,即只有在相同包结构下可以访问该接口。

 接口名应该与类名采用相同的命名规则。合法的标识符,并具有可读性,可以使用形容词。

 一个接口可以有多个直接父接口,但接口只能继承接口,不能继承类

注意:

  接口中定义的是多个类共同的公共行为规范,因此接口里所有成员,包括常量、方法、内部类和内部枚举都是public访问权限。定义接口成员时,可以忽略访问控制修饰符,如果指定访问控制修饰符,则只能使用public访问控制修饰符。

  对于接口里定义的静态常量而言,它们是接口相关的,因此系统会自动为这些成员变量增加static和final两个修饰符。也就是说,在接口中定义成员变量时,不管是否使用public static final修饰符,接口中的成员变量总是使用这三个修饰符修饰。而且接口中没有构造器和初始化块,因此接口里定义的成员变量只能在定义时指定默认值

  接口里定义的方法只能是抽象方法、类方法和默认方法,因此如果不是定义默认方法,系统将自动为普通方法增加abstract修饰符;定义接口里的普通方法时不管是否使用public abstract修饰符,接口里的普通方法总是使用public abstract来修饰。接口里的普通方法不能有方法实现(方法体);但类方法、默认方法都是必须有方法实现(方法体)。

  接口里定义内部类、内部接口、内部枚举默认都采用public static两个修饰符,不管定义时是否指定这两个修饰符,系统都会自动使用public static对它们进行修饰。

  Java8允许在接口中定义默认方法,默认方法必须使用default修饰,不能使用static修饰,无论程序是否指定,默认方法总是使用public修饰。需要使用接口的实现类的实例来调用。

  Java8允许在接口中定义类方法,类方法必须使用static修饰,不能使用default修饰,无论程序是否指定,类方法总是使用public修饰。类方法可以直接使用接口来调用。

使用接口

  接口不能创建实例,但是可以用于声明引用类型变量。当使用接口来声明引用类型变量时,这个引用类型变量必须引用到到其实现类的对象。用途如下:

  1. 定义变量,也可以用于强制类型装换

  2. 调用接口中定义的常量

  3. 被其他类实现

  一个类可以继承一个父类,但是可以实现一个或多个接口, 类实现接口的语法如下:

  [修饰符] class 类名 extends 父类 implements 接口1, 接口2, ....

  {

    类体部分

  }

  一个类实现了一个或多个接口之后,这个类必须完全实现这些接口里的所定义的全部抽象方法(也就是重写这些抽象方法);

  否则,该类将保留从父接口那里继承到的抽象方法,该类也必须定义为抽象类。

抽象类和接口的比较:

  相同之处:

  1. 接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他类实现和继承。

  2. 接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

  差别:

  1. 接口里只能包含抽象方法、静态方法和默认方法,不能为普通方法提供方法实现;抽象类则完全可以包含普通方法。

  2. 接口里只能定义静态常量,不能定义普通成员变量;抽象类里则既可以定义普通成员变量,也可以定义静态常量。

  3. 接口里不包含构造器;抽象类里可以包含构造器,抽象类里的构造器并不是用于创建对象,而是让子类调用这些构造器来完成属于抽象类的初始化操做。

  4. 接口里不能包含初始化块;但抽象类里完全可以包含初始化块。

  5. 一个类最多只有一个直接父类,包括抽象类;但一个类可以直接实现多个接口,通过实现多接口,可以弥补Java单继承的不足。

  接口作为系统与外界交互的窗口,接口体现的是一种规范。当在一个程序中使用接口,接口是多个模块间的耦合标准;当在多个应用程序之间使用接口时,接口是多个程序之间的通信标准。

  抽象类作为系统中多个子类的共同父类,它体现的是一种模板式设计。

  利用接口,面向接口编程,例如:简单工厂模式,命令模式。

原文地址:https://www.cnblogs.com/FocusIN/p/6779930.html