您的位置:首页 > 职场人生

Java面试准备九:Java的接口和抽象类

2017-04-13 00:04 211 查看
这里只是为了记录,因为时间有限,自己熟悉的知识点就不再叙述了,只是把自己模糊的或者怕忘了的记录下来。日后有时间会再做整理。

参考详细解析Java中抽象类和接口的区别

理解抽象类

从语法定义层面看abstract class 和 interface

从设计理念层面看abstract class 和 interface

接口和抽象类的概念不一样。接口是对动作的抽象,抽象类是对根源的抽象。

抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。

人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.

所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。

1. 理解抽象类

抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列本质上相同但具体实现起来却不同的具体概念的抽象。在Java语言中,abstract class 和 interface都是用来进行抽象类定义的。下面将从语法定义层面上和设计理念层面上比较这两种抽象类。

2. 从语法定义层面看abstract class 和 interface

在语法层面,Java语言对于abstract class和interface给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。

 使用abstract class的方式定义Demo抽象类的方式如下:

 

abstract class Demo {
abstract void method1();
abstract void method2();
void method3(){
System.out.println("do something...");
}
...
}


使用interface的方式定义Demo抽象类的方式如下:

interface Demo{
void method1();
void method2();
...
}


二者之间在语法定义层面上的比较如下:

————abstract classInterface备注
成员变量可以是各种类型的成员变量只能够有静态的不能被修改的数据成员(也就是必须是static final的,且必须给其初值,不过在interface中一般不定义数据成员)(个人理解:如果是非static的话,因一个类可以继承多个接口,出现重名的变量,如何区分呢;如果是非final的话,因为接口是一种规范,功能定义的声明,所有可变的东西都应该归属到实现类中,这样接口才能起到标准化、规范化的作用)
成员方法(1)可以有非abstract的成员方法。
(2)抽象方法必须是public或者是protected的(因为如果为private则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public
所有的成员方法只能是abstract的(隐式指定为public abstract,用其他关键字,比如private、protected、static、final等修饰会报错)。(1)从某种意义上说,interface是一种特殊形式的abstract class
(2)所以在abstract class中,我们可以赋予方法的默认行为。但是在interface中,方法却不能拥有默认行为,就会导致同样的方法实现出现在该抽象类的每一个派生类中,造成代码重复,同样不利于以后的维护。
静态代码块和静态方法可以有没有,接口的所有方法都是抽象需要被重写的,而有static的方法是不能被重写的,所以abstract和static是不能同时作用于一个方法上。个人理解:接口只是用来规范一些行为,并不需要具体实现,所以静态代码块和静态方法不适合放在接口里面。
编程角度在Java语言中表示的是一种继承关系,一个类只能使用一次继承关系(因为Java不支持多重继承)一个类可以实现多个interface这也许是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧
子类继承时需要注意的问题子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须子类也定义为abstract类。必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。
3. 从设计理念层面看abstract class 和 interface

上面参考文中的作者认为:从设计理念层面看分析才能理解二者概念的本质所在。

abstract class 在Java语言中体现了一种继承关系,要想是的继承关系婚礼,父类和派生类之间必须存在“is-a”关系,即父类和派生类在概念本质上应该是相同个。

而对于interface来说则并不要求派生类和父类在概念本质上是一致的,而仅仅是实现了interface定义的契约而已,父类和派生类之间必须存在“like-a”关系。下面举个例子说明:

假设Door具有执行两个动作open和close,此时我们可以通过abstract class 或者 interface来定义一个表示该抽象概念的类型,定义方式分别如下所示:

abstract class Door:

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


interface Door:

interface{
void open();
void close();
}


看起来好像使用abstract class和interface没有大的区别。如果现在要求Door还要有报警的功能。那该如何设计呢?

可以在abstract class Door里面再添一个方法alarm(),或是在interface里面再添一个方法alarm(),如下:

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


interface Door:

interface{
void open();
void close();
void alarm();
}


那那些仅仅依赖于Door这个概念即仅有open和close行为而没有alarm行为的模块则被迫要加上alarm这个行为,这是不符合人们的需求的。所以,这个方案不通过。

又一解决方案:

既然open、close和alarm属于两个不同的概念,那应该把它们分开定义在代表这两个概念的抽象类中。定义方式有:1. 这两个概念都是用abstract class方式定义;2. 两个概念都使用interface方式定义;3. 一个使用abstract class方式定义,一个使用interfac方式定义。

显然,由于Java语言不支持多重继承,第一种方式是不行的,唯有后两种可行。由于AlarmDoor在概念本质上是Door而不是警报器,又abstract class父类与派生类的关系是is-a的关系,interface父类与派生类的关系是like-a的关系,所以应该用abstract class的方式定义door的概念,而用interface的方式定义alarm的概念。如下所示:

abstract class Door{
abstract void open();
abstract void close();
}
interface Alarm{
void alarm();
}
class Alarm Door extends Door implements Alarm{
void open(){…}
void close(){…}
void alarm(){…}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java 面试