Java接口全解析

来源:互联网 发布:php商城thinkphp 编辑:程序博客网 时间:2024/03/29 18:50
接口:
所有的开发里面可以不使用抽象类,但是没有不使用接口的。
本次讲解知识点:
1.接口的基本概念与主要特点;
2.接口的各个使用;
3.工厂设计模式、代理设计模式。


接口的基本定义:
如果不会接口,其他任何语言都难以理解。
如果一个类之中只是由抽象方法和全局常量所组成,那么不会将其定义为一个抽象类,而只会将其定义为接口,所以严格来讲接口属于一个特殊的类,而且这个类里面只有抽象方法与全局常量。
范例:定义接口
interface A{//定义了接口
   public abstract void print();//抽象方法
   public static final String MSG = "Hello";//全局常量
}
由于接口里面存在抽象方法,所以接口不能直接使用关键字new进行实例化操作,所以接口的使用原则如下:
  1.接口必须有子类,但是此时一个子类可以使用implement关键字实现多个接口
  2.接口的子类(如果不是抽象类),必须覆写接口中的全部抽象方法;
  3.接口的对象可以利用子类对象的向上转型进行实例化操作。
范例:实现接口:  
interface A{//定义了接口
  public static fianl String MSG = "Hello";
  public abstract void print();//抽象方法
}
interface B{
  public abstract void get();
}
class X implements A,B{//X实现了A,B两个接口
   public void print(){
     System.out.print("A接口的抽象方法");
   }
   public void get(){
     System.out.println("B接口的抽象方法");
   }
}
public class TestDemo{
   public static void main(String args[]){
     X x = new X();//实例化子类对象
A a = x;//向上转型
B b = x;//向上转型
a.print();//调用A接口的print()方法
b.get();//调用B接口的get()方法
   }
}
A和B这两个接口没有直接的关系,但是这两个接口却同时拥有一个子类:X子类,千万不要被类型和名称所迷惑。
如果一个子类既要继承抽象类,又要实现接口,那么要先extends抽象类,再写implements接口。


接口的组成仅仅有抽象方法和全局常量。接口中只能使用一种访问权限public。


以下两个代码相同:
interface A{
  public static final String MSG = "HELLO";
  public abstract void fun();
  }
interface A{
  String MSG = "HELLO";
  void fun();
}
为了防止某些不熟悉语法的开发者出现错误,所以强烈建议在接口定义方法的时候一定要写上public
接口的促成,一般都是以抽象方法为主。


一个抽象可以继承一个抽象类,一个接口可以使用extends同时继承多个接口。但是接口不能继承抽象类。
范例:接口继承多个接口
interface A{
   public void funA();
}
interface B{
   public void funB();
}
//C接口同时继承了A和B两个父接口
interface C extends A,B{//此处使用的是extends
   public void funC();
}
class X implements C{
  //此时,X类要覆写3个抽象类
  public  void funA(){};
  public  void funB(){};
  public  void funC(){};
}
从继承关系上讲抽象类的限制比接口多很多:
  1.一个抽象类只能继承一个抽象的父类,而接口没有此限制。
  2.一个子类只能继承一个抽象类,而接口可以实现多个接口。
在Java中,接口的主要功能是解决单继承局限问题。
尽管所有的接口都是由抽象方法和全局常量组成,但是所有的内部结构不受到这些要求的限制。
所以,在接口里面可以定义普通内部类、抽象内部类、内部接口。


注意:接口中定义抽象方法不用写abstract,而抽象类中定义抽象方法必须写abstract


范例:在接口中定义抽象类
interface A{
   public void funA();
   abstract class B{//A接口中定义的一个抽象类
      public abstract void funB();
   }
}
Class X implements A{//X实现了A接口
  public void funA(){
  System.out.println("覆写A抽象方法");
  }
} 类X实现接口A,只需要覆写A抽象方法就行,至于接口A中的抽象类B不用管他,它是一个类文件,与我们无关.
如果想使用接口A中的抽象类B,只需要在X中定义一个内部类Y:
class Y extends B{}//内部抽象类的子类
但是上面的代码一般不会这样写。


范例:在一个接口内部如果使用了static定义一个内部接口,表示是一个外部接口
interface A{
  public void funA();
  static interface B{//外部接口
    public void funB();
  }
}
class x implements A.B{//X实现A接口,注意:是A点B
   public void funB();
}
总结:接口在实际的开发中,有三大核心作用:
1.定义不同层之间的操作标准
2.表示一种操作的能力
3.表示将服务器的远程方法视图暴露给客户端


接口的实际应用————标准:
范例:定义USB的标准
//标准可以连接不同层的操作类
interface USB{//定义标准一定就是接口
   public void start();
   public void stop();
}
范例:定义电脑
class Computer{
   public void plugin(USB usb){//插入
   usb.start();//固定操作
   usb.stop();
   }
}
范例:定义U盘
class Flash implements USB{
   public void start(){
     System.out.println("U盘开始使用");
   }
   public void stop(){
     System.out.println("U盘停止使用");
   }
}
范例:定义打印机
class Print implements USB{
   public void start(){
     System.out.println("打印机开始使用");
   }
   public void stop(){
     System.out.println("打印机停止使用");
   }
}
public class TestDemo{
  public static void main(String args[]){
     Computer com = new Computer();
com.plugin(new Flash());
com.plugin(new Print());
  }
}
显示生活中,标准的概念随处可见,而在程序里面标准就是用接口来定义的。




接口的应用————工厂设计模式(Factory):
首先观察一段代码:
interface Fruit{
  public void eat();
}
class Apple implements Fruit{
  public void eat(){
    System.out.println("吃苹果");
  }
}
public class TestDemo{
   public static void main(String args[]){
     Fruit f = new Apple();
f.eat();
   }
}
此代码不存在语法错误,但问题出现在关键字new上。
确认一个代码真的好的几个标准:
  1.客户端调用简单,不需要关注具体的细节
  2.客户端之外的代码修改,不影响用户的使用。
新类Orange:
class Orange implements Fruit{
  public void eat(){
    System.out.println("吃橘子");
  }
}
现在的客户端上想要得到这个新的子类对象,需要修改代码,修改为:Fruit f = new Orange();
我们发现,直接在客户端上产生了实例化对象,那么每一次要想更换对象,都需要修改客户端上的执行代码,这样的做法明显是不好的。
  在整个代码中,我们只需要关心如何取得一个Fruit对象,之后进行方法的调用,至于这个对象是被谁实例化的,那不是我客户端的工作。
  这一类问题就叫做耦合问题,即耦合度太高。耦合的太高会导致代码不方便维护,相当于A一直要与B绑定在一起。


我们可以参考Java虚拟机的设计思想:
   程序--》JVM--》适应不同的操作系统
即,开发程序时无需考虑适应不适应操作系统,这写都由JVM解决。
 
大部分类中如果有static方法,基本上表示这个类中不需要定义属性,或者可能需要取得实例化对象。
增加一个工厂类:
class Factory{
   public static Fruit getInstance(String className){
    if("apple".equals(className)){
return new Apple();
} else if("orange".equals(className)){
  return new Orange();
} else {
  return null;
}    
   }
}
现在的客户端不会看见具体的子类,因为所有的接口对象都是通过Factory类取得的。


面试题:请编写一个Factory程序




接口的应用————代理设计模式(Proxy)
范例:
interface Subject(//整个操作的核心主题
   public void make();//整个临幸的核心功能
)
class RealSubject implements Subject{//真是主题(例如皇帝)
   public void make(){
      System.out.println("皇帝陛下正在XX");
   }
}
class ProxySubject implements Subject{//代理主题(例如太监)为真实主题而活
   private Subject subject;
   //要接收一个真实主题的操作对象
   public ProxySubject(Subject subject){
      this.subject = subject;
   }
   public void prepare(){
      System.out.println("为临幸做准备!");
   }
   public void make(){
     this.prepare();
     this.subject.make();//告诉皇帝可以开始了
this.destroy();
   }
   public void destroy(){
      System.out.println("把娘娘搬走了,皇帝伺候睡觉!");
   }
}
public class TestDemo{
   public static void main(String args[]){
      Subject sub = new ProxySubject(new RealSubject);
 sub.make();//调用的是代理主题操作
   }
}
代理设计模式的核心精髓在于有一个主题操作接口(里面可能有多种方法),核心业务主题只完成核心功能,例如,吃饭。而代理主题负责完成所有与核心主题有关的操作。 
面试题:请编写一个Proxy程序。


无论理解不理解工厂设计模式和代理设计模式,不管用什么方法,一定要把它们背下来。




抽象类和接口的区别(面试题):
抽象类和接口在使用的形式上时非常相似的,所以很多人乐意解释两者的区别:
1.关键字:抽象类是abstract class ,接口是interface
2.组成:抽象类的组成有:构造方法、普通方法、抽象方法、static方法、常量、变量;接口组成有:抽象方法、全局常量。
3.子类使用:抽象类的子类使用是:class 子类 extends 抽象类;接口的子类使用是:class 子类 implements 接口,...,...,..
4.关系:抽象类可以实现多个接口;接口不能继承抽象类,却可以继承多个父接口
5.权限:抽象类可以使用各种权限;接口只能使用public权限。
6.限制:单继承局限;没有单继承局限
7.子类:抽象类和接口都必须有子类,子类必选覆写全部的抽象方法
8.实例化对象:抽象类和接口都依靠子类对象的向上转型进行对象的实例化
比较后发现,抽象类支持的功能比接口更多,但是只有一点不好,就是单继承局限,这一点掩盖了所有抽象类的优点,即:当抽象类和接口都可以使用时,优先考虑接口。


参考:
   1.在进行某些公共操作的时候一定要定义出接口。
   2.有了接口就需要利用子类完善方法。
   3.如果是你们自己写的接口,那么绝对不要使用关键字new直接实例化接口子类,用工厂类完成。


总结:
1.接口与抽象类定义的不同
2.接口作为标准用于解耦合以及不同层之间的连接桥梁
3.一定要将工厂设计模式与代理设计模式的结构记下来







原创粉丝点击