您的位置:首页 > 大数据

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

2016-02-17 17:02 681 查看
接口和抽象类
简要说明

参考资料

例子对比

抽象类

接口

区别与联系
语法区别

设计区别

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

接口和抽象类

简要说明

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

参考资料

/article/4719052.html

/article/1384930.html

http://www.importnew.com/7302.html

例子对比

请大家仔细对比,下面看一个网上流传最广泛的例子:门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:

抽象类

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");
}
}


接口

interface Door {
String door; //只有默认变量,为 public static final 修饰
public abstract void open();  //只有抽象方法
public abstract void close();
}


抽象类

抽象方法:一种特殊的方法:它只有声明,而没有具体的实现

抽象方法必须用abstract关键字进行修饰。

抽象类必须在类前用abstract关键字修饰。

如果一个类含有抽象方法,则称这个类为抽象类,

因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。

在其他方面,抽象类和普通的类并没有区别。

接口

要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下:

class ClassName implements Interface1,Interface2,[....]{

}


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

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

如果一个抽象类遵循某个接口,可以不实现该接口中的抽象方法。

区别与联系

语法区别

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

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

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

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

设计区别

抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。

回到上面门的例子上,将其简化

门和警报的例子:门都有open( )和close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:

设计成抽像类:

abstract class Door {

public abstract void open();

public abstract void close();

}


或者设计成接口:

interface Door {

public abstract void open();

public abstract void close();

}


但是现在如果我们需要门具有报警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();
}


如果我们尝试编译上面的这段代码,会得到如下结果:

$javac .\SimpleInterface.java
.\SimpleInterface.java:18: error: SimpleInterfaceImpl is not abstract and does not
override abstract method doSomeOtherWork() in SimpleInterface
class 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 class
DoSomeOtherWork 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方法中选择哪一个,因此产生了二义性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: