0


java 接口 详解


一、概述

1.介绍 :

  1. **接口技术用于描述类具有什么功能,但并不给出具体实现,当某个类要使用接口时,再去实现接口中的这些方法。类需要遵从接口中描述的统一规则进行定义,所以,接口是对外提供的一组规则,标准。**

2.定义 :

  1. ①**定义接口**要用到**关键字interface**,格式如下 :
  2. **interface **接口名 {
  3. }
  4. ②类和接口之间不再是继承,而是**实现关系**,用**implements关键字**表示。如下 :
  5. **class **类名 **implements **接口名 {
  6. }
  7. Δ需要注意的是:**与类的定义类似,接口的访问权限修饰符只能是public或者默认**。
  8. **IDEA中定义接口的步骤如下 : **
  9. 1>先像平时创建类一样正常点击New——>Java Class;如下图所示 :

  1. 2>然后在弹出的窗口中选择Interface,输入接口名,回车即可。如下图所示 :

二、特点

1.接口成员变量的特点 :

  1. Δ**接口中没有成员变量,只有公有静态常量。**
  2. 即**默认情况**下属性前都会有public static final 这三个关键字修饰。如下 :
  3. **public static final ****数据类型****常量名** = **常量值**;
  4. Δ还记得我们在final关键字详解中讲到的——关于final修饰属性的初始化问题吗?
  5. 当时,我们说,final修饰的属性必须进行初始化,而对于公有静态常量,初始化的途径只有两条——①定义时②静态代码块中。但是很遗憾,接口中不允许存在代码块,而且接口没有构造方法。因此,这就要求我们**在接口中定义公有静态常量时,必须在定义时就赋初值**。否则IDEA报错。
  1. **演示 : **
  2. 我们以DemoInterface接口为演示接口,在该接口中定义i变量,并定义Test类作为测试类,如下所示 :

  1. 可以看到,IDEA对于i变量前的三个关键字均作了灰色处理,表明这三个修饰符是默认的,你写不写它都在!在测试类中,我们尝试更改i变量的值,IDEA会马上报错,如下图所示 :

  1. 而可通过接口名来调用i变量也体现出static关键字的存在。

2.接口成员方法的特点 :

  1. **①**在JDK**7.0**版本及其之前版本中,接口中仅支持**公有的抽象方法**:
  2. **public abstract** 返回值类型 方法名();
  3. Δ事实上,**接口中的方法默认就是公有抽象方法,因此在接口中定义抽象方法时,可以省略掉abstract关键字**。
  4. **②**从JDK**8.0**开始,接口中可以由**默认方法**和**静态方法**:
  5. **默认方法**——**public default **返回值类型 方法名() {
  6. }
  7. **静态方法**——**public static **返回值类型 方法名() {
  8. }
  9. Δ需要注意的是,想定义**默认方法必须在前面添加default关键字**,因为接口中的方法如果你什么都不写,默认是公有的抽象的方法。默认方法可以有方法体,且不需要实现类去实现,其实就是我们平时见到的普通的成员方法。但是默认方法是可以被实现类重写的。**default关键字只能在接口中使用**。就算实现类要重写默认方法,实现类中重写后的方法也不能添加default修饰符,不然IDEA报错。
  10. **③**JDK**9.0**以后,接口中可以有**私有方法 **:
  11. **private **返回值类型 方法名() {
  12. }
  1. **演示 : **
  2. 我们以Demo2接口为演示接口,以Imple类作为Demo2接口的实现类,最后以Test2类作为测试类,代码如下 :
  1. package knowledge.port.characters.methods;
  2. public interface Demo2 {
  3. //①在JDK7.0版本之前,接口中仅支持公有的抽象方法:
  4. public abstract void hello_world();
  5. //②从JDK8.0开始,接口中可以由默认方法和静态方法:
  6. //默认方法
  7. public default void what_time() {
  8. System.out.println("姥姥——姥姥——几点啦?");
  9. }
  10. //静态方法
  11. public static double Sum(double x, double y) {
  12. return x + y;
  13. }
  14. //③JDK9.0以后,接口中可以有私有方法 :
  15. private void own() {
  16. System.out.println("这是👴的私有方法。");
  17. }
  18. public default void invoke_own() {
  19. this.own();
  20. }
  21. }
  22. class Imple implements Demo2{
  23. @Override
  24. public void hello_world() {
  25. System.out.println("你好,世界!");
  26. }
  27. }
  28. class Test2 {
  29. public static void main(String[] args) {
  30. Demo2 d2 = new Imple();
  31. d2.hello_world();
  32. System.out.println("---------------------------------");
  33. d2.what_time();
  34. System.out.println("传入的x与y的和 = " + Demo2.Sum(141, 135));
  35. System.out.println("---------------------------------");
  36. d2.invoke_own();
  37. }
  38. }
  1. **运行结果** :

  1. 注意看我们在Demo2接口中定义的第一个抽象的方法, IDEA中,它是下面这样子的 :

  1. public abstract修饰符均为灰色,再一次说明接口中的方法默认情况为公有的抽象方法。如果想使用默认方法,一定不要忘记添加default关键字。

3.接口构造方法的特点 :

  1. 接口存在的目的是为了规范类,因此接口也不可以被实例化。接口中不允许存在代码块,也没有需要初始化的成员,因此**接口没有构造方法(构造器)**。在接口中定义构造器IDEA会直接报错,如下图所示:

4.接口创建对象的特点 :

  1. **①接口不能被实例化 :**
  2. 只能通过多态的方式实例化“子类”对象(这里的**“子类”指的是接口的实现类**)
  3. **②接口的子类(实现类) : **
  4. **可以是抽象类,也可以是普通类**。
  5. **对于抽象实现类**,可以不用实现接口的所有方法,因为抽象类本身容许存在抽象方法,语法上是通过的。
  6. **对于普通实现类**,要求实现接口的所有方法。
  1. **演示 : **
  2. 我们以Demo3接口为演示接口,在接口中定义三个抽象方法greet(), exercise(), study();以Imple1类和Imple2类作为Demo2接口的实现类,令Imple1类为抽象类,不实现Demo3接口中的抽象方法;令Imple2类为非抽象类,实现Demo3接口中的所有抽象方法。最后以Test3类作为测试类,**代码如下** :
  1. package knowledge.port.object;
  2. public interface Demo3 {
  3. public abstract void greet();
  4. public abstract void exercise();
  5. void study(); //默认隐含public abstract修饰符
  6. }
  7. abstract class Imple1 implements Demo3 {
  8. //实现类Imple1类是抽象类,允许拥有抽象方法,因此可以不实现接口中的方法。
  9. }
  10. class Imple2 implements Demo3 {
  11. @Override
  12. public void greet() {
  13. System.out.println("嗨,你好!");
  14. }
  15. @Override
  16. public void exercise() {
  17. System.out.println("文明其精神,野蛮其体魄!");
  18. }
  19. @Override
  20. public void study() {
  21. System.out.println("好好学习,天天向上!");
  22. }
  23. }
  24. class Test3 {
  25. public static void main(String[] args) {
  26. Demo3 d3 = new Imple2();
  27. d3.greet();
  28. d3.exercise();
  29. d3.study();
  30. }
  31. }
  1. **运行结果** :

  1. 还记得我们讲过的alt + enter快捷键吗?假如接口中有许多许多许多的抽象方法,如果你要一个一个实现的话麻烦的一批,这时候用我们的快捷键就会方便许多,快捷键演示如下GIF动图:

5.接口继承关系的特点 :

  1. **①类和接口之间的关系 : **
  2. 类与接口是实现关系,支持“多实现”,即**一个类可实现多个接口**。
  3. **②接口与接口之间的关系 : **
  4. 接口与接口是继承关系,**java 支持接口的多继承,即一个接口可以同时继承多个接口**,格式如下 :
  5. 接口 **extends **接口1,接口2,接口3...
  6. **③继承和实现的区别 **
  7. **继承体现的是“is a”的关系,父类中定义共性内容。**
  8. **实现体现的是“like a”的关系,父接口中定义扩展内容。**
  9. PS : 接口的“实现”可以看作是Java中对“单继承机制”的一个补充完善。接口可以在一定程度上实现代码解耦(接口规范性 + 动态绑定)。总的来看,**接口比继承更为灵活**。

三、应用 :

1.情景 :

  1. 实际开发中,为了更好地控制和管理项目,项目经理往往会定义一些接口,具体的实现细节由各位程序🐒实现。🐒儿这时就会根据需求,编写不同的类去实现项目👴给的接口。如下图所示 :

  1. 这时候可能就会有p小将(**personable小将,指风度翩翩的人**)出来问了,直接让🐒儿们去编写类不久完了吗,为啥还得项目👴亲自动手,这不纯纯脱裤子放屁?
  2. p小将您先别急,我给大家举个例子吧——
  3. 让三个程序🐒去编写程序,分别建立与MysqlOracle,以及DB2数据库的连接,这时,如果项目👴没有定义接口,而是直接让🐒儿编写实现连接的类。三个🐒对于连接的方法可能命名为了三种不同的形式,比方说1号🐒写得connect2号🐒写得join3号🐒写得link。如下所示 :
  1. package knowledge.port.application;
  2. public class ToDataBase {
  3. public static void main(String[] args) {
  4. SqlConnect mysql = new SqlConnect();
  5. mysql.connect();
  6. OracleConnect oracle = new OracleConnect();
  7. oracle.join();
  8. DB2Connect db2 = new DB2Connect();
  9. db2.link();
  10. }
  11. }
  12. class SqlConnect {
  13. public void connect() {
  14. System.out.println("连接到Mysql数据库。");
  15. }
  16. }
  17. class OracleConnect {
  18. public void join() {
  19. System.out.println("连接到Oracle数据库。");
  20. }
  21. }
  22. class DB2Connect {
  23. public void link() {
  24. System.out.println("连接到DB2数据库。");
  25. }
  26. }
  1. **运行结果** :

  1. 项目经理如果就这b样儿给上级交上去,要给喷烂😁。
  2. 由此,我们看到开发中使用接口的必要性 :
  1. 1.无法确定每个程序🐒写得类是否规范,是否符合要求,无法预测最终软件的质量和规范。也无法控制软件最终的功能。
  2. 2.接口涉及了统一调用的问题,即接口编程。
  1. 解决方案 :
  2. 我们可以定义ConnectInterface接口, 并在接口中定义抽象方法connect() ,并让🐒儿们去编写类实现这个接口,然后在调用类中**利用多态参数,使接口作为形参**。
  3. ** ConnectInterface接口代码如下 : **
  1. package knowledge.port.application;
  2. public interface ConnectInterface { //接口规定了连接方法必须是connect
  3. public abstract void connect();
  4. }
  1. **实现类,调用类代码如下 : **
  1. package knowledge.port.application;
  2. public class ToDataBase {
  3. public static void main(String[] args) {
  4. SqlConnect mysql = new SqlConnect();
  5. ToDataBase.connect(mysql);
  6. OracleConnect oracle = new OracleConnect();
  7. ToDataBase.connect(oracle);
  8. DB2Connect db2 = new DB2Connect();
  9. ToDataBase.connect(db2);
  10. }
  11. public static void connect(ConnectInterface connectInterface) {
  12. connectInterface.connect();
  13. }
  14. }
  15. class SqlConnect implements ConnectInterface{
  16. public void connect() {
  17. System.out.println("连接到Mysql数据库。");
  18. }
  19. }
  20. class OracleConnect implements ConnectInterface{
  21. public void connect() {
  22. System.out.println("连接到Oracle数据库。");
  23. }
  24. }
  25. class DB2Connect implements ConnectInterface{
  26. public void connect() {
  27. System.out.println("连接到DB2数据库。");
  28. }
  29. }

2.多态 :

  1. 在上文中我们提到,接口不能被实例化,而是通过多态的方法实例化子类对象。意思就是说,**接口引用指向子类对象也是多态的体现**。 实际上,接口的多态要从两方面说起。首先我们来说说接口多态的传递性。

①多态的传递性 :

  1. **多态的传递性**,指的是——**如果一个类通过implements关键字实现了某个接口,而这个接口此时又继承了另一个接口,那么就相当了这个类同时实现了这两个接口**。而且可以用父接口的引用指向实现类对象。
  2. 我们以FatherInterface为父接口,在父接口中定义一个公有抽象方法f(),SonInterface为子接口,**Achieve类为子接口的实现类**。以Test类为测试类。**代码如下** :
  1. package knowledge.port.application.deliver;
  2. public interface FatherInterface {
  3. public abstract void f();
  4. }
  5. interface SonInterface extends FatherInterface {
  6. //子接口中啥也没有,但是显然继承了父接口中的公有抽象方法。
  7. }
  8. class Achieve implements SonInterface{
  9. @Override
  10. public void f() {
  11. System.out.println("实现类Achieve实现了子接口中————继承自父接口的抽象方法。");
  12. }
  13. }
  14. class Test {
  15. public static void main(String[] args) {
  16. //可以使用子接口引用指向实现类的多态
  17. SonInterface sonInterface = new Achieve();
  18. sonInterface.f();
  19. //也可以使用父接口引用指向实现类的多态
  20. FatherInterface fatherInterface = new Achieve();
  21. fatherInterface.f();
  22. }
  23. }
  1. ** 运行结果 : **

  1. 注意,如果此时实现类中没有实现f() 方法,IDEA会报错,如下图所示 :

子接口中没有定义抽象方法,但是子接口继承了父接口,也就拥有了父接口的非私有方法。因此实现类必须实现父接口的抽象方法,而这相当于实现类也实现了父接口,即实现类同时实现了多个接口

②关于接口的多态参数和多态数组 :

  1. 其次,对于我们在多态篇讲到的多态的应用——多态参数和多态数组**,接口也同样适用**!喏,上面咱们举的项目经理的例子就是接口多态参数的体现。
  2. 对于接口的多态参数和多态数组,up将其**内容补充在了多态的应用——多态参数和多态数组详解一文中**,方便大家对比记忆和理解。博文链接如下: https://blog.csdn.net/TYRA9/article/details/128920758https://blog.csdn.net/TYRA9/article/details/128920758

四、总结 :

  1. 🆗,以上就是关于java 接口 详解的全部内容了。我们重点介绍了接口的特点,其中又分为了成员变量,成员方法,构造方法,创建对象,继承关系五部分。这五部分要求大家必须掌握,至此,我们的面向对象三大特性之多态篇正式结束😎!**感谢阅读**!
标签: java 开发语言 jvm

本文转载自: https://blog.csdn.net/TYRA9/article/details/129174384
版权归原作者 Cyan_RA9 所有, 如有侵权,请联系我们删除。

“java 接口 详解”的评论:

还没有评论