大数据课程体系-学习笔记-第一阶段-Java Base

来源:互联网 发布:python 矩阵乘法 编辑:程序博客网 时间:2024/05/16 17:29

  • 接口和抽象类
    • 简要说明
        • 参考资料
    • 例子对比
    • 抽象类
    • 接口
    • 区别与联系
      • 语法区别
      • 设计区别
    • JDK8中的新特性-default方法defender方法转载

接口和抽象类

简要说明

当初在学习Java的时候,对于接口和抽象类的概念不是十分清晰,感觉二者几乎一样,没有什么本质的区别,在这个假期第二次读了《Android源码设计模式解析与实战》后,深刻认识到了抽象类和接口的重要性,在这里和大家一起梳理一下二者。

参考资料

  1. http://www.cnblogs.com/dolphin0520/p/3811437.html
  2. http://blog.csdn.net/chenssy/article/details/12858267
  3. http://www.importnew.com/7302.html

例子对比

  1. 请大家仔细对比,下面看一个网上流传最广泛的例子:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:
  2. 抽象类
abstract class Door {    String door;    //可以有默认变量    private String Name; //可以有私有变量    protected String name; //可以有保护变量    public String brand;//可以有公有变量    //可以有构造函数    public Component(String name){        this.name = name;    }    //可以有抽象方法    public abstract void open();    public abstract void close();    //可以有非抽象方法    public void doSomething(){         System.out.println("Open");    }}
  1. 接口
interface Door {    String door; //只有默认变量,为 public static final 修饰    public abstract void open();  //只有抽象方法    public abstract void close();}

抽象类

  1. 抽象方法:一种特殊的方法:它只有声明,而没有具体的实现
  2. 抽象方法必须用abstract关键字进行修饰。
  3. 抽象类必须在类前用abstract关键字修饰。
  4. 如果一个类含有抽象方法,则称这个类为抽象类,
  5. 因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。
  6. 在其他方面,抽象类和普通的类并没有区别。

接口

  1. 要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下:
  2. class ClassName implements Interface1,Interface2,[....]{
    }

  3. 一个类遵循多个特定的接口。

  4. 如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。
  5. 如果一个抽象类遵循某个接口,可以不实现该接口中的抽象方法。

区别与联系

语法区别

  1. 抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

  3. 接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

  4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口

设计区别

  1. 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。
  2. 回到上面门的例子上,将其简化
  3. 门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:
  4. 设计成抽像类:

    abstract class Door {
    public abstract void open();
    public abstract void close();
    }

  5. 或者设计成接口:

    interface Door {
    public abstract void open();
    public abstract void close();
    }

  6. 但是现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?下面提供两种思路:

      1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;

      2)将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的open( )和close( ),也许这个类根本就不具备open( )和close( )这两个功能,比如火灾报警器。

      从这里可以看出, Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。

interface Alram {    void alarm();}abstract class Door {    void open();    void close();}class AlarmDoor extends Door implements Alarm {    void oepn() {      //....    }    void close() {      //....    }    void alarm() {      //....    }}

JDK8中的新特性-default方法(defender方法)(转载)

原文链接
我们都知道在Java语言的接口中只能定义方法名,而不能包含方法的具体实现代码。接口中定义的方法必须在接口的非抽象子类中实现。下面就是关于接口的一个例子:

public interface SimpleInterface {  public void doSomeWork();}class SimpleInterfaceImpl implements SimpleInterface{  @Override  public void doSomeWork() {    System.out.println("Do Some Work implementation in the class");  }  public static void main(String[] args) {    SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();    simpObj.doSomeWork();  }}

那么,如果我们在SimpleInterface里面添加一个新方法,会怎样呢?

public interface SimpleInterface {  public void doSomeWork();  public void doSomeOtherWork();}
  1. 如果我们尝试编译上面的这段代码,会得到如下结果:
$javac .\SimpleInterface.java.\SimpleInterface.java:18: error: SimpleInterfaceImpl is not abstract and does not override abstract method doSomeOtherWork() in SimpleInterfaceclass SimpleInterfaceImpl implements SimpleInterface{^1 error

因为接口有这个语法限制,所以要直接改变/扩展接口内的方法变得非常困难。我们在尝试强化Java 8 Collections API,让其支持lambda表达式的时候,就面临了这样的挑战。为了克服这个困难,Java 8中引入了一个新的概念,叫做default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods)。Default方法是指,在接口内部包含了一些默认的方法实现(也就是接口中可以包含方法体,这打破了Java之前版本对接口的语法限制),从而使得接口在进行扩展的时候,不会破坏与接口相关的实现类代码。接下来,让我们看一个例子:

public interface SimpleInterface {  public void doSomeWork();  //A default method in the interface created using "default" keyword  //使用default关键字创在interface中直接创建一个default方法,该方法包含了具体的实现代码  default public void doSomeOtherWork(){    System.out.println("DoSomeOtherWork implementation in the interface");  }}class SimpleInterfaceImpl implements SimpleInterface{  @Override  public void doSomeWork() {    System.out.println("Do Some Work implementation in the class");  }  /* 1. Not required to override to provide an implementation  2. for doSomeOtherWork. 3. 在SimpleInterfaceImpl里,不需要再去实现接口中定义的doSomeOtherWork方法   */  public static void main(String[] args) {    SimpleInterfaceImpl simpObj = new SimpleInterfaceImpl();    simpObj.doSomeWork();    simpObj.doSomeOtherWork();  }}

该程序的输出是:

Do Some Work implementation in the classDoSomeOtherWork implementation in the interface

如果一个类实现了两个接口(可以看做是“多继承”),这两个接口又同时都包含了一个名字相同的default方法,那么会发生什么情况? 在这样的情况下,编译器会报错。用例子来解释一下:

public interface InterfaceWithDefaultMethod {  public void someMethod();  default public void someOtherMethod(){    System.out.println("Default method implementation in the interface");  }}public interface InterfaceWithAnotherDefMethod {  default public void someOtherMethod(){    System.out.println("Default method implementation in the interface");  }}

然后我们定义一个类,同时实现以上两个接口:

public class DefaultMethodSample implements  InterfaceWithDefaultMethod, InterfaceWithAnotherDefMethod{  @Override  public void someMethod(){    System.out.println("Some method implementation in the class");  }  public static void main(String[] args) {    DefaultMethodSample def1 = new DefaultMethodSample();    def1.someMethod();    def1.someOtherMethod();  }  }

如果编译以上的代码,会得到一个编译器错误,因为编译器不知道应该在两个同名的default方法中选择哪一个,因此产生了二义性。

1 0
原创粉丝点击