一. 概述
接口interface和抽象类abstract Class是支持抽象类定义的两种机制。接口和抽象类都是不能够被实例化的,同时继承了抽象类的子类和实现了接口的实现类只有实现了接口和抽象类中的抽象方法才可以被实例化。
抽象类:
1. 可以有私有方法和私有变量的,且成员变量都是default,可以在子类中重新定义,也可以被重新赋值。
2. 通过关键字abstract来声明一个类为抽象类,同时抽象类中的抽象方法没有方法体。
3. 子类实现方法必须含有相同的或者更低的访问权限(public > protected > private)。
4. 抽象类的子类必须实现父类中的所有抽象方法,否则子类也为抽象类。
5. 抽象类中可同时有关键字abtract修饰的抽象方法(只能定义不能实现,抽象方法被abstract
修饰,不能被private
、static
、synchronized
和native
等修饰,必须以分号结尾,不带花括号)和普通方法(既能定义又能实现)。
6. 抽象类必须用public、procted 修饰(如果为private修饰,那么子类则无法继承,也就无法实现其抽象方法)。默认缺省为 public。
接口:
1. 可以看作为一种特殊的抽象类,接口是公开的,不能有私有的方法和变量,且变量默认隐式为public static final,且必须赋初值,且不能被重新赋值,即不能被修改。
2. 通过关键字interface来声明一个类为接口,接口中的所有方法都是抽象方法且没有方法体,抽象方法默认隐式都是public abstract 关键字修饰(并且只能是 public ,如果是 private,procted,那么就编译报错),且不能是 static,接口中的方法也不允许子类覆写,抽象类中允许有static 的方法。
3. Java是单继承多实现的语言,即一个类可以实现多个接口,所以可以通过接口来间接实现多重继承。
4. 接口中的只由被定义,而不能实现的抽象方法,Java1.8可以定义default方法体。
5. 接口中没有 this
指针,没有构造函数,不能拥有实例字段(实例变量)或实例方法。
二. 代码示例
抽象类:
public abstract class Test{
//普通成员变量
private int age;
//抽象方法
abstract void method();
//普通成员方法
public string method() {
C
System.out.println("This is abstract class!");
}
}
Jdk8前的接口:
interface Test {
public static final int age = 18;
//方法隐式的是public abstract修饰
String getString(参数列表);
}
Jdk8后的接口允许我们在接口中定义static方法和default方法且可以使用default关键字实现默认的方法:
//jdk8及以后,允许我们在接口中定义static方法和default方法。
public interface JDK8Interface {
//static 修饰定义静态方法
static void staticMethod(){
System.out.println("接口中的静态方法。");
}
//default修饰符定义默认方法
default void defaultMethod() {
System.out.println("接口中的默认方法。");
}
}
总结:
- 抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
- 抽象类要被子类继承,接口要被类实现。
- 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
- 抽象类里可以没有抽象方法。
- 接口可以被类多实现(被其他接口多继承),抽象类只能被单继承。
- 接口中没有 this 指针,没有构造函数,不能拥有实例字段(实例变量)或实例方法。
- 抽象类不能在Java 8 的 lambda 表达式中使用。
三. final关键字
final关键字可以修饰类,成员变量和方法中的局部变量。
1. final类
final类是不能被继承的,即不能够有子类。
2. final方法
如果用final修饰父类中的一个方法,那么这个方法就不允许子类进行重写,也就是说,不允许子类隐藏可以继承的final方法(只能继承,不能重写)。
3. 常量
如果成员变量或者局部变量被修饰为final,那么它就是常量。由于常量在运行期间不允许修改,所以常量在声明时是没有默认值的,这就是要求我们在声明变量时必须指定该变量的值。