浅谈Java接口

先不谈接口,不妨设想一个问题?

如果你写了个Animal类,有许多类继承了他,包括Hippo(河马), Dog, Wolf, Cat, Tiger这几个类。你把这几个类拿给别人用,但是别人想给动物加上宠物功能,要怎么办呢?

根据以往的知识,我们可以:

  1. 把Pet方法加入Animal类

    • 这样所有的派生类都有Pet方法,以后新继承Animal的动物也有这个方法。

    • 这个方案很简单,但是这个方案也很操蛋。为什么?

      • 有人会养河马吗?有人会养狼养狮子吗?不太行。
      • 如果都是Pet方法,狗需要遛,猫恐怕不太需要遛呀。不太行
    • 所以,这个方案,不太行。

  2. 还是和第一种方法一样,但是把Pet方法设成抽象方法

    • 方案很好,每个派生类可以覆盖自己方法。不是Pet的就不做动作,不同的Pet有不同的行为。
    • 可是,这个方案很友好吗?
      • 所有的派生类都需要覆盖这个方法,非常浪费时间,怕不是要累死程序员。
      • 这种实现很不理想,很不面向对象,不是宠物的派生类也需要覆盖这样的方法。
      • 使得基类Animal变得非常局限,如果加入复杂的程序会变得难以利用。
  3. 把方法具体加到需要的类里

    • 具体类具体实现。
    • 继承和多态完全失效。同样会累死程序员。
    • 无法确保写在派生类里的方法能够和基类产生合约,容易破坏面向对象的基本规则。
  4. 多继承

    • 这是最好的思路,一个类有两个基类。例如Cat既继承Animal,又继承Pet。而Tiger则只需要继承Animal。
    • 可是,出大问题!
      • 一是多继承本身的问题。假设我有一个基类1Cat,一个基类2Dog。两个基类里都有一个方法叫做play。那么一个派生类继承Cat同时继承Dog,那么派生类调用play方法时,就不知道是Cat的play还是Dog的play了。这就叫多继承的冲突。又称致命方块问题
      • 更何况,Java是不允许“实现多继承”,简称不允许“多继承”。 (毕竟往高端了说,Java的设计者是想设计一门不容易出错的工业型语言。往低端了说,Java设计者认为程序员都是弱弟弟)

难道这个问题就没有解决方案了吗?下面就欢迎我们今天的主角——

接口

首先,什么是接口?

接口(英文:Interface),在Java编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。

回到刚刚第四个方法,如果想用多继承的思路但是又不产生冲突,那要怎么办呢?那就用接口。

接口解决冲突的方法很简单,把所有方法都设为抽象的,如此一来,派生类要调用这些方法,就必须重新实现一遍,这样JVM就不会搞混了!

所有,接口就类似于一个100%的纯抽象类,可他又不是类

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。

接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

如何编写接口

public interface Pet{
// 关键词 interface
public abstract void play(); // public abstract可以省略,抽象方法没有内容
}

接口的实现

class Dog extends Animal implements Pet{
// 关键词 implements
// 接口的实现必须在某个类的继承之下
public void play(){
// 必须实现这个方法
}
}

接口的特性

  • 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。

    public interface Pet{
    public abstract void play(); // 抽象方法,分号结尾
    }

    其实不像上面那么写也可以

    public interface Pet{
    void play(); // 隐含了public abstract
    }
  • 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量(并且只能是 public,用 private 修饰会报编译错误)。

  • 接口中的方法是不能在接口中实现的,只能由实现接口的类来实现接口中的方法。

我们为什么需要接口?

  • 使用接口可以继承超过一个以上的来源。类可以继承一个基类同类实现其他许多接口。同时其他的类也可以实现同一个接口,这样可以为不同的需求组合出不同的继承层次。
  • 接口使得代码严谨。不论你来自哪里,只要你实现了这个接口,就一定会实现接口中的方法!
  • 接口更高层,同样的方法在不同层次的类有不同的实现细节,这是很合理的。

接口与抽象类的区别

  1. 抽象类中的方法可以有方法体,就是能实现方法的具体功能,但是接口中的方法不行。
  2. 抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是 public static final 类型的。
  3. 接口中不能含有静态代码块以及静态方法(用 static 修饰的方法),而抽象类是可以有静态代码块和静态方法。
  4. 一个类只能继承一个抽象类,而一个类却可以实现多个接口。

接口的继承

  • 接口和类一样,都可以继承。也使用extends关键词,子接口继承父接口的方法,但是可以改变传入参数。

    public interface Pet{
    void play();
    } interface wild_Pet extends Pet{
    void play(String location);
    }
  • 虽然类不可以多继承,但是接口可以呀! 在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。

    interface wild_Pet extends Pet, Sweeties{}

    Pet和Sweeties可能定义或继承了相同的方法,但是没有关系,他们都是抽象的!

浅谈Java接口(Interface)的更多相关文章

  1. 浅谈Java接口

    接口(英文:Interface)是Java中非常重要的内容,初学的时候可能感受不深,但是在做项目的时候,对面向接口编程的运用就变得尤为重要,不过这是后话了.现在先讨论假如是刚刚接触接口这个概念,该怎么 ...

  2. 浅谈Java中接口与抽象类的异同

    浅谈Java中接口与抽象类的异同 抽象类和接口这两个概念困扰了我许久,在我看来,接口与抽象类真的十分相似.期间也曾找过许许多多的资料,参考了各路大神的见解,也只能是简简单单地在语法上懂得两者的区别.硬 ...

  3. 浅谈JAVA集合框架

    浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...

  4. 浅谈Java代理一:JDK动态代理-Proxy.newProxyInstance

    浅谈Java代理一:JDK动态代理-Proxy.newProxyInstance java.lang.reflect.Proxy:该类用于动态生成代理类,只需传入目标接口.目标接口的类加载器以及Inv ...

  5. 浅谈Java的默认和静态方法

    目录 浅谈Java的默认和静态方法 Java新增默认方法有啥用 Java新增的静态方法有啥用 浅谈Java的默认和静态方法 允许在接口中声明默认方法和静态方法,是JDK1.8新增的特性.存在即合理,两 ...

  6. 浅谈Java的反射机制和作用

    浅谈Java的反射机制和作用 作者:Java大师 欢迎转载,转载请注明出处 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象 ...

  7. 浅谈Java中的深拷贝和浅拷贝(转载)

    浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...

  8. !! 浅谈Java学习方法和后期面试技巧

    浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...

  9. 浅谈Java中的深拷贝和浅拷贝

    转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...

随机推荐

  1. 什么是RPM

    RPM是RedHat Package Manager(RedHat软件包管理工具)的缩写,这一文件格式名称虽然打上了RedHat的标志,但是其原始设计理念是开放式的,现在包括OpenLinux.S.u ...

  2. 3L-最好、最坏、平均、均摊时间复杂度

    关注公众号 MageByte,设置星标点「在看」是我们创造好文的动力.后台回复 "加群" 进入技术交流群获更多技术成长. 本文来自 MageByte-青叶编写 上次我们说过 时间复 ...

  3. asyncio在爬虫中的使用

    # -*- coding: utf-8 -*- # 协程基础.py import asyncio import time async def request(url): print("正在请 ...

  4. Netty源码分析之ChannelPipeline—出站事件的传播

    上篇文章中我们梳理了ChannelPipeline中入站事件的传播,这篇文章中我们看下出站事件的传播,也就是ChannelOutboundHandler接口的实现. 1.出站事件的传播示例 我们对上篇 ...

  5. vim不能使用小键盘

    使用终端登录Linux后使用vim编辑文本,这时在默认设置下载插入模式使用小键盘会插入一些非数字的字符. 更改的方法: 在终端设置中选择终端类型为linux

  6. echarts legend文字配置多个颜色(转)

    困扰很久的问题终于解决了 oh yea! echarts legend文字配置多个颜色legend: {data: [{name:‘直接访问’,icon : ‘circle’,textStyle: { ...

  7. JavaScript(8)--- 闭包

    JavaScript(8)--- 闭包 理解闭包 我的理解是:闭包就是能够读取其他函数内部变量的函数.由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以简单这样理解 &q ...

  8. java触发full gc的几种情况概述

    前言 近期被问及这个问题,在此记录整理一下. System.gc()方法的调用 此方法的调用是建议JVM进行Full GC,虽然只是建议而非一定,但很多情况下它会触发 Full GC,从而增加Full ...

  9. 数据库-Mysql语句

    Mysql语句 不定时更新 1.数据库相关的语句 /* 数据库操作 */ ------------------ -- 启动MySQL net start mysql -- 接与断开服务器 mysql ...

  10. Redis 按正则获取keys

    首先,我被坑了很久由于不知道这个redis支持的正则只有3种 1. * 任意长度的任意字符 2. ? 任意单一字符 3. [xxx] 匹配方括号中的一个字符 2.从上面开来,keys的模糊匹配功能很方 ...