1. 抽象类、接口
interface关键字使抽象的概念更向前迈进了一步。abstract关键字允许人们在类中创建一个或多个没有任何意义的方法——提供了接口部分,但是没有提供任何相应的具体实现,这些实现石油是由此类的继承者创建的。interface这个关键字产生一个完全抽象的类,它根本就没有提供任何具体实现。它允许创建者确定方法名、参数列表和返回类型,但是没有任何方法体。
接口只提供了形式,而未提供任何具体实现。抽象类中是可以有方法实现的,但是接口中全部没有方法体。
抽象类也可以没有抽象方法,即便如此,抽象类也不可以被实例化。
接口可以继承自多个接口。
但是,interface不仅仅是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类的类型,来实现某种类似多重继变种的特性。
可以在interface关键字前面添加public关键字(但仅限于该接口与其同名的文件中被定义)。如果不添加public关键字,则它只具有包访问权限,这样它就只能在同一个包内可用。接口也可以包含域,但是这些隐式地是static和final的。
可以选择在接口中显式地将方法声明为public的,但即使你不这么做,它们也是public的。因此,当要实现一个接口时,在接口中被定义的方法必须被定义为是public的;否则,它们将只能得到默认的包访问权限,这样在方法被继承的过程中,其可访问权限就被降低了,这是Java编译器所不允许的。
2. 完全解耦
创建一个能够根据所传递的参数对象不同而具有不同行为的方法,被称为策略设计模式。
3. 使用接口的核心原因
为了能够向上转型为多个基类型(以及由此而来的灵活性)。然而,使用接口的第二个原因确实与使用抽象基类相同:防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。这就带来了一个问题:我们应该使用接口还是抽象类?如果要创建不带任何方法定义和成员变量的基类,那么就应该选择接口而不是抽象类。事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口。
4. 接口组合的名字冲突
interface I1 {
void f();
}
interface I2 {
int f(int i);
}
interface I3 {
int f();
}
class C {
public int f() {
return 1;
}
}
class C2 implements I1, I2 {
public int f(int i) {
return 1;
}
public void f() {
}
}
class C3 extends C implements I2 {
public int f(int i) {
return 1;
}
}
class C4 extends C implements I3 {
public int f() {
return 1;
}
}
//class C5 extends C implements I1 {
//}
//interface I4 extends I1, I3 {
//}
最后注释的内容是编译器报错的,因为不能通过方法的返回值来重载方法。
5. 适配接口
我们可以在任何现有类之上添加新的接口,所以这意味着让方法接受接口类型,是一种让任何类都可以对该方法进行适配的方式。这就是使用接口而不是类的强大之处。
6. 接口中的域
在接口中定义的域不能是“空final”,但是可以被非常量表达式初始化。
既然域是static的,它们就可以在类第一次被加载时初始化,这发生在任何域首次被访问时。当然这些域不是接口的一部分,它们的值被存储在该接口的静态存储区域内。
7. 嵌套接口
接口内部可以拥有其他接口,但不能有private的修饰的接口。
一个类不能实现其他类中的私有接口。
当实现某个接口时,并不需要实现嵌套在其内部的任何接口,而且,private接口不能在定义它的类之外被实现。
class A {
private interface D {
void f();
}
public class DImp2 implements D {
public void f() {
}
}
public D getD() {
return new DImp2();
}
}
public class TestInterface {
public static void main(String[] args) {
A a = new A();
// 除了返回D之外,什么都没有返回,不能赋值给A.DImp2
// A.DImp2 di2 = a.getD();
}
}
8. 接口是实现多重继承的途径,而生成遵循某个接口的对象的典型方式就是工厂方法设计模式。这与直接调用构造器不同,我们在工厂对象上调用的是创建方法,而该工厂对象将生成接口的某个时间对象。理论上,通过这种方式,我们的代码将完全与接口的实现分离,这就是使得我们可以透明地将某个实现替换为另一个实现。
恰当的原则应该是优先选择类而不是接口。从类开始,如果接口的必须行变的非常明确,那么就进行重构。接口是一种重要的工具,但是它们容易被滥用。