Java知识:抽象类与接口

最近发现一位博客大神chenssy,他写的博客总结的很好,我以后会用他的博客进行知识复习与巩固,特此说明,希望他不要介意。

要想明白抽象类与接口首先要知道二者之间有什么联系。

抽象类与接口是相互补充的。

一个类只能单继承,不能多继承,接口使得继承变得更加完善(接口是对继承的补充)。
抽象类与实现类之间是is-a继承关系,接口与实现类之间是like-a实现关系。(设计层面)
例子:Door
我们有一个Door的抽象概念,它具备两个行为open()和close(),此时我们可以定义通过抽象类和接口来定义这个抽象概念:
抽象类:
abstract class Door{  
    abstract void open();  
    abstract void close();  
}  
接口
interface Door{  
    void open();  
    void close();  
}  

但是现在如果我们需要门具有报警的功能,那么该如何实现呢?

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

interface Alarm{  
    void alarm();  
}  

class AlarmDoor extends Door implements Alarm{  
    void open(){}  
    void close(){}  
    void alarm(){}  
}  

AlarmDoor它是一个门,这表明他的继承关系,他还有报警功能,因为已经有了继承关系,所以报警功能只能是接口来实现了。这个例子我用的篇幅较少,因为我认为这个例子理解起来不是很难,如果大家看不明白可以看看其他人的详细解释。我在这里主要想表达的是:分清is-a还是like-a可以让程序设计起来更清晰,另外也可以看出接口使得继承更加完善。


抽象类的特点:

1. .抽象类不能被实例化,实例化的工作应该交由它的子类来完成。

首先我们说明一下实例化有几种方法:第一、new是最常见的;第二、Class.forName(“”).newInstance()/getInstance()方法;第三、clone()方法;第四、IO流的反序列化。
我们遇到的与抽象类实例化挨边的方法就是前两种,第一种大伙都知道是不可以的,第二种很多人都有疑惑。
这里我们有个疑问:在jdk中发现有好多抽象类都被实例化了,例如calendar类,FormatDate类
calender源代码如下:

 public static Calendar getInstance()
    {
         Calendar cal = createCalendar(TimeZone.getDefaultRef(), Locale.getDefault());
cal.sharedZone = true;
return cal;
    }
private static Calendar createCalendar(TimeZone zone,
   Locale aLocale)
    {
// If the specified locale is a Thai locale, returns a BuddhistCalendar
// instance.
if ("th".equals(aLocale.getLanguage())
    && ("TH".equals(aLocale.getCountry()))) {
    return new sun.util.BuddhistCalendar(zone, aLocale);
} else if ("JP".equals(aLocale.getVariant())
   && "JP".equals(aLocale.getCountry())
   && "ja".equals(aLocale.getLanguage())) {
    return new JapaneseImperialCalendar(zone, aLocale);
}

“把父类calendar的引用cal指向了子类.GregorianCalendar的对象”
不过按照具体情况calendar的应用ca还可能指向GregorianCalendar子类的对象
我们发现创建的不是抽象类的实例。也就是说之前提到的实例化抽象类不成立!

3. 只要包含一个抽象方法的抽象类,该方法必须要定义成抽象类,不管是否还包含有其他方法。

4. 抽象类中可以包含抽象的方法,当然也可以不包含抽象方法。

这条要和上一条一起理解,有抽象方法的类肯定是抽象类,抽象类中不一定有抽象方法。

6. abstract不能与final并列修饰同一个类。

如果某个类用final修改,表明该类是最终类,它不希望也不允许其他类继承它。有关final的知识点我放在最后面,大家相互学习。

7. abstract 不能与private、static、final或native并列修饰同一个方法。

static与private不能修饰同一方法原因:
首先明白abstract方法需要重写(不是继承)才有意义!
如果一个抽象类(含有抽象方法的类就是抽象类)的某一个抽象方法定义为private那么这个方法对子类来说是拥有却不可见的(private权限修饰符的原因),即使你把那个private方法写出来了,你新写出来的方法也不属于重写,它应当算是子类特有的方法,因为子类压根看不到父类的private方法尽管它确实存在(子类确实继承了父类的private方法)。
父类的private方法子类能继承但是却对子类不可见所以没有重写。


static与abstract不能修饰同一方法原因:
你要调用一个别的类中的方法,就2种方式,如果这个是静态方法,直接类名.方法名()调用,如果不是静态方法,就得先生成这个类的实例,再通过实例名.方法名()调用(当然,前提是public的,其它关键字要考虑是否在包中或者是否子类等等,pirvate肯定是不行的),另一方面,一个类如果包含一个抽象方法,这必然是个抽象类,而抽象类是不能实例化的,它必须通过被继承来实现其中的抽象方法。本来static不需要子类就能用,可是加上abstract之后却需要子类实现才能用。


final与abstract不能修饰同一方法原因:
final修饰的方法不可修改,abstract修饰的方法如果不重写那么就没有意义。

接口的特点:

Interface的方所有法访问权限自动被声明为public且仅能是public。
接口中变量会自动变为为public static final。
接口中不存在实现的方法(所有方法都是抽象的)。
不能使用new操作符实例化一个接口,但可以声明一个接口变量,该变量必须引用(refer to)一个实现该接口的类的对象。(向上转型可以)
在实现多接口的时候一定要避免方法名的重复。

说完联系我们来说说他俩的区别

主要是设计理念不同,is-a和like-a的关系。


再说说他俩的共同点

从设计角度两者都需要子类对其进行重写。
且二者无法实例化。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值