Java中的interface 和abstract class 引用类型是用来创建抽象的。
interface 和abstract class 都不能直接实例化。它们需要由其他类来实现或扩展。
但是这两种引用类型有很多不同之处,它们改变了你的抽象的工作方式。
一个明显的区别是,一个abstract class 是一个类。一个Javaclass 只能扩展一个类,但它可以实现许多接口。
下面是Javainterface 和abstract class 引用类型之间的一些明显的区别。
成员的访问修改器
一个abstract class 可以有带访问修饰符的成员(如private,protected, 和public ),而interface 成员都是public :
abstract class Individual {
protected String tribe = "Hominini";
private String species = "Homo Sapiens";
public String name = "Nathan";
}
interface Human {
protected String tribe = "Hominini";
// ERROR: protected modifier not allowed
private String species = "Homo Sapiens";
// ERROR: private modifier not allowed
public String name = "Nathan";
// WARNING: public modifier is redundant
}
protected 和private 的访问修饰符不允许出现在interface 中。
public 修饰符是多余的,因为interface 的所有变量成员默认都是公共的。
成员的非访问修饰符
默认情况下,一个interface 的成员都是static 和final 。
另一方面,一个abstract class 的成员可以是final 、static ,或者都不是。
考虑一下下面的interface 代码例子:
interface Human {
String name = "Nathan";
}
public class Main {
public static void main(String[] args) {
System.out.println(Human.name); // Nathan
Human.name = "Jack" // ERROR
}
}
一个interface 成员可以被直接调用,因为它们默认是static 。
在一个abstract class ,你需要将成员声明为static ,以便直接访问它们:
abstract class Individual {
String first_name = "Nathan";
static String last_name = "Sebhastian";
}
public class Main {
public static void main(String[] args) {
System.out.println(Individual.first_name); // ERROR
System.out.println(Individual.last_name); // OK
Individual.first_name = "Smith"; // ERROR
Individual.last_name = "Smith"; // OK
}
}
你也可以添加final 修改器来使成员的值不可改变:
abstract class Individual {
// this is the default in interface:
final static String last_name = "Sebhastian";
}
因为abstract class 变量默认不是最终的,你可以声明变量而不初始化它们,如下所示:
abstract class Individual {
String first_name;
String last_name;
}
而这就是interface 和abstract class 在非访问修饰符方面的不同之处。
引用类型中的方法修饰符
默认情况下,一个interface 只能有抽象的方法。声明一个带实现的方法将导致一个编译时错误:
interface Human {
void greetings() {
System.out.println("Hello!");
}
// ERROR: abstract methods cannot have a body
void call(); // Correct abstract method
}
从Java 8开始,interface 类型得到了改进,所以它也可以有default 和static 方法。
当你想为interface 方法提供一个默认的实现时,请添加default 修饰符,如下所示:
interface Human {
default void greetings() {
System.out.println("Hello!");
}
// You can also declare a static method:
static void call() {
System.out.println("Hi!");
}
}
在一个abstract class ,你可以同时声明常规和抽象方法,如下图所示:
abstract class Individual {
void greetings() {
System.out.println("Hello!");
}
abstract void call();
}
注意,在一个abstract class 中声明抽象方法时,需要添加abstract 修饰符。
继承规则
interface 和abstract class 没有特殊的继承规则。
当你需要的时候,你可以扩展一个单一的类并实现多个接口到一个abstract class:
class A {}
class B {}
interface ZX {}
interface ZY {}
abstract class C extends A, B {}
// ERROR: only one class allowed
abstract class C extends A implements ZX, ZY {}
// OK
另一方面,一个interface 只能扩展另一个接口:
class A {}
interface ZX {}
interface ZY {}
interface Test implements ZX {}
// ERROR: implements not allowed
interface Test extends A {}
// ERROR: interface expected, class A received
interface Test extends ZX, ZY {}
// OK
而这些就是Java中的interface 和abstract class 的明显区别。
什么时候使用接口或抽象类?
要记住的关键点是,一个interface 是用来实现完全抽象的,而一个abstract class 是用来实现部分抽象的。
一个interface 是用来提供实现class 将提供的能力。
例如,Animal 接口承诺实现对象可以行走:
interface Animal {
void walk();
}
但是walk 方法的实现是留给实现它的对象的。
一个Dog 类将用四条腿行走,而一个Kangaroo 类用两条腿行走:
class Dog implements Animal {
@Override
public void walk() {
System.out.println("4 legs");
}
}
class Kangaroo implements Animal {
@Override
public void walk() {
System.out.println("2 legs");
}
}
尽管现在你可以有default 和static 方法,但规则仍然是一样的:一个interface 定义了一个对象能做什么。
另一方面,一个abstract class 对一个对象是什么更感兴趣。
当使用一个abstract class ,你是在赋予实现对象之间的共同特征:
abstract class Person {
String first_name;
String last_name;
int lungs = 2;
void breathe() {
System.out.println("Breathe in.. breathe out");
}
}
一个人的first_name 和last_name 通常是在这个人出生时给出的,所以它们被声明,但没有被初始化。
你不能用一个interface 做同样的事情,因为在一个interface 中声明的任何变量都是final 。
总而言之,一个interface 是用来提供一个对象可以做什么和拥有什么的承诺的。
同时,abstract class 提供一个对象可以做和拥有的共享事物。
我希望这个教程能帮助你理解interface 和abstract class 之间的区别。👍