接口为我们提供了一种将接口与实现分离的更加结构化的方法。在选择使用接口通常有俩个目的:
- 一是,为了可以向上转型
- 二是,避免被创建对象(实例),这一点和抽象类是一致的。
任何抽象性都是应真正的需求而产生的,所以在开发中不能一味地使用接口,而要根据设计的需求。
《Java编程思想》给出的建议是:优先选择类,如果接口的必需性变得非常明确,那么就进行重构。
一、抽象类和抽象方法
抽象类提供一批通用接口,希望可以通过这些接口操纵一系列类
抽象方法——一种不完整的方法,只有声明而没有方法体,具体如下
abstract void f();//含有关键字abstract
抽象类——即含有一个或多个抽象方法,并用关键字abstract修饰的类
//创建抽象类 abstract Animal{ public void eat(String time);//抽象方法 public void sleep(){ System.out.print("Sheep!"); } } class Dog extends Animal{ public void eat(String time){ System.out.print("Dog "+time+"eat meat!"); } } class Sheep extends Animal{ public void eat(String time){ System.out.print("Sheep "+time+"eat grass"); } } public class Test{ public void turn(Animal a){ a.eat("8:00"); a.sleep(); } public static void main(String[] args){ Animal[] a={new Dog(),new Sheep()}; for(Animal sub:a){ turn(sub); } } } out: Dog 8:00 eat meat! Sleep! Sheep 8:00 eat grass! Sleep!
需要注意一点的是,抽象类是不能进行实例化的,所以Java为了让用户可以很清晰的清楚这一点采用了”抽象方法的机制“,利用其不完整性和关键字abstract的使用来告知编译器自身的特殊性,防止误导使用者。
二、接口
interface是一个极度抽象的类,接口里面的方法同样没有方法体,它的存在就是为了保持一部分其他类的一致性。创建一个接口需要用关键字interface代替class,关键字前可以添加限定修饰符,但是如同类一样,一个接口文件中只能有一个public修饰的接口,且接口名必须与文件名一致。接口同样可以包含域,但是这些域隐式的是static和final。
接口的使用形式很像继承,但是与继承又有很大区别,继承要求每一子类只能继承一个父类,但是接口则可以通过implements关键字进行多个接口的实现(相当于创建了一个可以向上转型为多种基类的类型,很像多重继承),
需要注意的是在接口中所有的方法都应该被声明为public,因为Java编译器是不允许接口的访问权限被降低的。
接口的具体实例如下:
package com.interface; //创建接口 public interface Animal{ String time="8:00";//static&final public void eat(String time); public void sleep(); } package com.animalclass; import com.interface.Animal;//导入接口 class Dog implements Animal{ public void eat(String time){ System.out.print("Dog "+time+"eat meat!"); } public void sleep(){ System.out.print("Dog sleep!"); } } class Sheep implements Animal{ public void eat(String time){ System.out.print("Sheep "+time+"eat grass"); } public void sleep(){ System.out.print("Sheep sleep"); } } public class Test{ public void turn(Animal a){ a.eat(Animal.time);//time默认为static,所以可以通过接口名直接调用 a.sleep(); } public static void main(String[] args){ Animal[] a={new Dog(),new Sheep()}; for(Animal sub:a){ turn(sub); } } } out: Dog 8:00 eat meat! Dog sleep! Sheep 8:00 eat grass! Sheep sleep!
三、接口中的域
- 默认都是static和final类型的,且自动是public的;
- 不能是变量,不能是“空final”,但可以是非常量表达式;
Random RAND=new Random(20); int ONE=RAND.nextInt(10); double TWO=RAND.nextDouble()*10;
//注:这些域并不属于这个接口的一部分,它们被存储在该接口的静态存储区域内,可通过接口名直接调用
- 接口域在Java没有枚举enum时起到了补充的作用,但是现在很少在接口中创建域。
四、嵌套接口
即接口之间可以进行互相嵌套,这种嵌套主要分为俩种:
- 类中嵌套接口
class A{ public interface B{void show();} public interface C{void show();} public interface D{void show();} //嵌套的也可以是私有接口,但是此时的接口不能被外部类或者接口进行访问,只能是通过方法(类似于访问类中的私有成员变量需要get方法) private interface E{void show();} }
- 接口中嵌套接口
interface A{ public interface B{void show();} public interface C{void show();} public interface D{void show();} }
除了上述内容,书中还介绍了关于接口的完全解耦的问题和接口在设计模式中的应用(策略设计模式、工厂设计模式),关于这俩点感觉很抽象,所以会在后边重点学习和记录。