1、interface不仅仅只是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类型的类,来实现某种类似C++多重继承变种的特性。
2、像类一样,可以在interface关键字前面添加public关键字(但仅限于该接口在与其同名的文件中被定义),或者不添加它而使其只是具有包访问权限,这样它就只能在同一个包内可用。
3、可以选择在接口中显示地将方法声明为public的,但即使你不这么做,它们也是public的。因此当实现一个接口时,在接口中被定义的方法必须被定义为public。
4、Java中,在方法的继承过程中,其可访问权限不能被降低。
5、接口也可以包含字段,但是它们隐式为static和final的。
6、因为接口是根本没有任何具体实现的——也就是说,没有任何与接口相关的存储;因此,也就无法阻止多个接口的组合,也就是“多重继承”。如下例子:
- interface CanFight{
- void fight();
- }
- interface CanSwim{
- void swim();
- }
- interface CanFly{
- void fly();
- }
- class ActionCharacter{
- public void fight(){
- System.out.println("ActionCharacter.fight()");
- }
- }
- class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly{
- public void swim(){
- System.out.println("Hero.swim()");
- }
- public void fly(){
- System.out.println("Hero.fly()");
- }
- /**1.注意CanFight中的fight()方法并没在这里定义
- * 2.这是因为CanFight接口与ActionCharacter类中的fight()方法的特征签名是一样的。
- * 3.所以即使Hero没有显式地提供fight()的定义,其定义也因ActionCharacter而随之而来。
- * 4.若把ActionCharacter的fight()改为private,就会出现提示说
- * “类型 Hero必须实现继承的抽象方法 CanFight.fight()”的错误。
- * 5.若把ActionCharacter的fight()改为private,就会出现提示说
- * “继承的方法 ActionCharacter.fight()不能隐藏 CanFight中的公用抽象方法”的错误。
- */
- }
- public class Adventure{
- public static void t(CanFight x){x.fight();}
- public static void u(CanSwim x){x.swim();}
- public static void v(CanFly x){x.fly();}
- public static void w(ActionCharacter x){x.fight();}
- public static void main(String[] args){
- Hero h = new Hero();
- t(h);
- u(h);
- v(h);
- w(h);
- }
- }
运行结果:
1).注意CanFight中的fight()方法并没有在Hero定义
2).这是因为CanFight接口与ActionCharacter类中的fight()方法的特征签名是一样的。
3).所以即使Hero没有显式地提供fight()的定义,其定义也因ActionCharacter而随之而来。
4).若把ActionCharacter的fight()改为private,就会出现提示说“类型 Hero必须实现继承的抽象方法CanFight.fight()”的错误。
5).若把ActionCharacter的fight()改为private,就会出现提示说“继承的方法 ActionCharacter.fight()不能隐藏CanFight中的公用抽象方法”的错误。
7、以上例子所展示的就是使用接口的核心原因:为了能够向上转型为多个基类型。
8、使用接口的第二原因:与使用抽象基类相同,防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。
9、应该使用接口还是抽象类:当要创建不带任何方法定义和成员变量的基类时,使用接口。
10、事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口,只有在强制你必须具有方法定义和成员变量时,才应该选择抽象类,或者在必要时使其成为一个具体类。
11、接口通过继承来扩展,如下:
- interface Plant{
- void grow();
- }
- interface Flower extends Plant{
- void bloom();
- }
- interface Apple extends Plant, Flower{
- void fruit();
- }
- class RedApple implements Apple{
- public void grow(){
- System.out.println("RedApple isgrowing.");
- }
- public void bloom(){
- System.out.println("RedApple isblooming.");
- }
- public void fruit() {
- System.out.println("RedApple isfruiting.");
- }
- }
心细的人可能看到了Apple接口后extends Plant, Flower。一般情况下,只可以将extends用于单一类,但是既然接口可以由多个其它接口产生,那么在创建一个新接口时,extends当然可以引用多个基类接口。此语法仅适用与接口的继承。
12、Java中构建如同C++的enum类型那样具备类型安全(变量的取值被限定在一个有限的范围内):
- public final class Month{
- private String name;
- //private构造器,无法创建它的任何实例,所有实例都是在类的内部有其身创建的finalstatic实例
- private Month(String name){
- this.name = name;
- }
- public String toString(){
- return name;
- }
- public static final Month
- JAN = new Month("January"),
- FEB = new Month("February"),
- MAR = new Month("March"),
- APR = new Month("April"),
- MAY = new Month("May"),
- JUN = new Month("June"),
- JUL = new Month("July"),
- AUG = new Month("August"),
- SEP = new Month("September"),
- OCT = new Month("October"),
- NOV = new Month("November"),
- DEC = new Month("December");
- public static final Month[] month = {
- JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
- };
- public static final Month number(int order){
- return month[order - 1];
- }
- public static void main(String[] args){
- //curMonth是一个Month对象,它仅可以被赋予一个Month对象。这就体现了类型安全性。
- Month curMonth = Month.JAN;
- System.out.println(curMonth);
- curMonth = Month.number(12);
- System.out.println(curMonth);
- //这种方式同样也允许你可互换地使用==或equal(),因为Month的每一个值都仅有一个实例。
- System.out.println(curMonth == Month.DEC);
- System.out.println(curMonth.equals(Month.DEC));
- System.out.println(Month.month[3]);
- }
- }
运行结果:
13、接口可以嵌套在类或其他接口中。嵌套接口可以拥有public和“包访问”两种可视性。同时,public和包访问的嵌套接口都可以被实现为public、包访问以及private的嵌套类。
- class A{
- interface B{
- void fromB();
- }
- interface D{
- void fromD();
- }
- //嵌套接口可以是private访问权限。
- //它带来的好处是:强制接口中的方法定义不要添加任何类型信息(也就是说,不允许向上转型),不明白,请看看最后的解说。
- private interface I{
- void fromI();
- }
- //private的嵌套接口可以被实现为private
- private class J implements I{
- public void fromI() {
- System.out.println("E.J.fromI()");
- }
- }
- //private的嵌套接口也可以被实现为public
- public class J1 implements I{
- public void fromI() {
- System.out.println("E.J1.fromI()");
- }
- }
- //结合getI()和setI()方法实现“向上转型”?!
- public I getI(){
- return new J1();
- }
- public void setI(I i){
- i.fromI();
- }
- //接口之间可以嵌套,嵌套在另一个接口中的接口只能是public的
- interface K{
- interface L{//此处也默认是public的
- void fromL();
- }
- }
- }
- public class E implements A.D{
- public void fromD() {
- System.out.println("E.fromD()");
- }
- //内部类F public
- public class F implements A.B{
- public void fromB() {
- System.out.println("E.F.fromB()");
- }
- }
- //内部类G protected
- protected class G implements A.B{
- public void fromB() {
- System.out.println("E.G.fromB()");
- }
- }
- //内部类I private
- private class H implements A.B{
- public void fromB() {
- System.out.println("E.I.fromB()");
- }
- }
- public static void main(String[] args){
- E e = new E();
- e.fromD();
- //内部的实例化
- E.F f = e.new F();
- f.fromB();
- E.G g = e.new G();
- g.fromB();
- E.H h = e.new H();
- h.fromB();
- //"实现了private接口I"的"public类J1"的实例化。
- A.J1 j1 = new A().new J1();
- j1.fromI();
- A a = new A();
- //A.I i = a.getI();//类型 A.I 不可视
- //A.J1 j = a.getI();//不能从 A.I转换为 A.J1
- //a.getI().fromI();//类型 A.I 不可视
- a.setI(a.getI());
- }
- }
getI(),返回private接口的引用的public方法。在main()中,数次使用返回值的行为都失败了。只有一种方式可以成功,那就是将返回值交给有权使用它的对象。在上例中,是一个A的对象a同过setI()方法来实现的。
以上内容整理自《Java编程思想》,如有遗漏,请您不吝指出!