Java拓展接口-default关键词

本文讲解Java接口的基本规定,探讨接口拓展难题,并介绍Java8引入的Default方法如何解决接口拓展问题,允许接口拥有默认实现,简化接口升级。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  Java接口在使用过程中有两点规定:

  1、接口中只能有定义方法名、方法返回类型,不能有方法的实现。

  2、实现接口的类,必须实现接口中所有的方法。

例如下面的例子:

//定义接口
public interface Action {
  //接口中的方法定义,只能定义返回类型、方法名称
  String say();
}

//接口的实现
public class ActionImpl implements Action {
  @Override
  public String say() {
    return "Hello world!";
  }
}  

如果在接口中增加一个方法,会出现什么情况?这里增加一个sleep方法。

public interface Action {
  String say();
  String sleep();
}

 我使用的是idea,在编辑器中已经提示出错了:必须要实现sleep方法。

基于接口使用规定中的第二点,一般是不能拓展接口的,拓展接口,则所有实现该接口的类都要实现新增加的接口。而实际工作中,根本不可能知道有哪些类实现了该接口,改动将是灾难性的。

如果确实要拓展接口呢?

Java 8中引入了一个新的概念,叫做default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods)。

default方法是指,在接口中可以定义包含具体实现的方法,这打破了Java之前版本对接口的语法限制。其他实现该接口的类不需要实现新增的default方法,默认就继承了该方法,同时也可以覆盖该方法。这样既拓展了接口,也不影响接口的实现类。

例如:

public interface Action {
  String say();
  //使用default关键词,使得接口中可以包含方法体
  public default String sleep() {
    return "I will go to sleep.";
  }
}

其实现类不报错了,且已经继承了该方法,可以直接使用该方法。

public class TestAction {
  public static void main(String[] args) {
    Action action = new ActionImpl();
    System.out.println(action.sleep());
  }
}

在实现类中也可以覆盖该方法。

public class ActionImpl implements Action {
  @Override
  public String say() {
    return "Hello world!";
  }

  @Override
  public String sleep() {
    return "sleeping";
  }
}

总之,default使得接口可以有定义方法体,子类可以继承和覆盖default方法。可以用于拓展接口。

更详细的说明见:

更多详细说明

 

转载于:https://www.cnblogs.com/leanfish/p/9767773.html

### Java 接口中的 `default` 方法 #### 背景与作用 在 JDK 8 中,为了增强接口的功能并解决向后兼容性问题,引入了 `default` 关键字用于定义接口中的默认方法。这种设计允许开发者在不破坏现有实现类的情况下对接口进行扩展[^1]。 通过 `default` 方法,可以在接口中提供具体的实现逻辑而无需强制要求所有的实现类都重新实现这些新增的方法。这极大地提高了代码的灵活性和可维护性[^2]。 --- #### 如何声明 `default` 方法 `default` 方法是在接口中以 `default` 关键字修饰的具体方法。其语法如下: ```java public interface MyInterface { default void myDefaultMethod() { System.out.println("这是接口中的默认方法!"); } } ``` 上述代码展示了如何在一个接口中定义一个带有具体实现的默认方法。 --- #### 实现类的行为分析 当某个类实现了该接口时,可以选择继承接口中的默认方法或者覆盖它来提供自己的实现方式。 ##### 场景一:未重写默认方法 如果实现类没有对该默认方法进行任何修改,则直接调用的是接口已有的实现版本。 示例代码: ```java class MyClass implements MyInterface {} public class Test { public static void main(String[] args) { MyInterface obj = new MyClass(); obj.myDefaultMethod(); // 输出:“这是接口中的默认方法!” } } ``` 此处展示了一个简单的例子,在其中创建的对象能够正常访问来自父级接口所提供的功能而不需额外编码工作量。 ##### 场景二:覆写默认方法 当然也可以让子类根据实际需求自定义行为模式而不是沿用原样设定好的操作流程。 实例演示: ```java class AnotherClass implements MyInterface { @Override public void myDefaultMethod() { System.out.println("这是另一个类对默认方法的新解释"); } } // 测试部分保持不变... ``` 运行结果将会打印出自定义的消息字符串而非原始定义的内容。 --- #### 处理冲突情况——多继承下的歧义处理机制 假设存在多个被继承下来的同名且签名完全一致的 `default` 函数怎么办呢? 这种情况下编译器不会自动决定哪一个应该被执行,而是抛给程序员手动指定解决方案. 例如下面这种情况: ```java interface A { default void hello(){ System.out.println("A says Hello!"); } } interface B{ default void hello(){ System.out.println("B says Hi!"); } } class C implements A,B{ public void hello(){ A.super.hello(); B.super.hello(); } } ``` 在这我们看到C同时实现了两个不同源处来的同样名称函数hello(). 若要消除可能产生的混淆状况就必须明确指出到底要调用谁家的东西才行. --- #### 应用案例 —— JDK 自身的应用 实际上官方库面已经大量运用到了这一特性比如Collections框架下很多实用工具都是基于此构建起来的像forEach(), sort()等等均属于此类范畴内的成员之一. --- ### 总结 综上所述,默认方法为Java语言带来了显著的好处,既保留了原有结构又增强了表达能力;同时也需要注意潜在的风险即多重继承引发的选择困难症候群等问题必须妥善加以规避才能真正发挥出它们的优势所在。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值