程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • Java8新特性

    • Java8新特性简介
    • Lambda 表达式
    • 函数式接口
    • 方法的引用
    • 构造器和数组的引用
    • Stream 流式编程
    • 并行流与串行流
    • Optional 类的使用
    • 对反射的支持增强
    • 接口中的默认方法与静态方法
      • 1. 接口中的默认方法
      • 2. 接口中的静态方法
      • 3. 实际开发中的应用场景
      • 4. 常见问题与注意事项
      • 5. 完整代码示例与总结
    • 新时间日期API
    • Try-with-Resources 升级
    • 重复注解与类型注解
  • Java9新特性

  • Java10新特性

  • Java11新特性

  • Java12新特性

  • Java13新特性

  • Java14新特性

  • Java15新特性

  • Java新特性
  • Java8新特性
scholar
2024-08-24
目录

接口中的默认方法与静态方法

# 接口中的默认方法与静态方法

前言

Java 8 之前,接口中的方法只能是抽象方法,所有实现接口的类必须提供方法实现。而在 Java 8 中,接口引入了两种新类型的方法:默认方法(default 方法)和静态方法。默认方法可以在接口中定义具体实现,而静态方法则允许在接口中直接定义类相关的实用方法。

  • 1. 接口中的默认方法
  • 2. 接口中的静态方法
  • 3. 实际开发中的应用场景
  • 4. 常见问题与注意事项
  • 5. 完整代码示例与总结

# 1. 接口中的默认方法

默认方法使用 default 关键字修饰,它使得接口可以在不破坏现有实现的情况下向后兼容,即便在接口中添加新方法,实现类也不必强制实现这些新方法。

语法格式:

public interface MyInterface {
    default String getName() {
        return "默认名称";
    }
}
1
2
3
4
5

主要特点:

  • 默认方法有具体实现:在接口中定义一个方法时,可以使用 default 关键字提供具体实现。
  • 可以被实现类继承或重写:如果实现类没有重写这个默认方法,则默认方法的实现会被继承;如果实现类重写了该方法,则使用重写后的实现。
  • 避免破坏已有代码:在不影响现有接口实现的前提下,可以在接口中添加新方法,这对于扩展接口非常有用。

代码示例:

// 定义接口 MyFun,包含一个默认方法
public interface MyFun {
    default String getName() {
        return "接口默认方法:哈哈哈";
    }
}

// 定义类 MyClass,包含一个同名方法
public class MyClass {
    public String getName() {
        return "类中的方法:嘿嘿嘿";
    }
}

// 定义子类,同时继承 MyClass 和实现 MyFun 接口
public class SubClass extends MyClass implements MyFun {
    // 没有重写 getName() 方法,因此调用时优先使用父类的实现
}

public class TestDefaultMethod {
    public static void main(String[] args) {
        SubClass sc = new SubClass();
        // 输出:嘿嘿嘿 (优先调用父类 MyClass 的方法)
        System.out.println(sc.getName());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

类优先原则:

当类和接口中都有相同签名的方法时,优先选择类中的方法。如果类和接口中的方法冲突,类的方法会覆盖接口中的默认方法。

接口冲突示例:

// 定义另一个接口 MyInterface,包含一个默认方法
public interface MyInterface {
    default String getName() {
        return "另一个接口默认方法:呵呵呵";
    }
}

// 定义子类,同时实现 MyFun 和 MyInterface 接口
public class SubClass implements MyFun, MyInterface {
    @Override
    public String getName() {
        // 需要手动指定调用哪个接口的默认方法,否则编译报错
        return MyInterface.super.getName();
    }
}

public class TestDefaultMethod {
    public static void main(String[] args) {
        SubClass sc = new SubClass();
        // 输出:呵呵呵 (指定使用 MyInterface 的默认方法)
        System.out.println(sc.getName());
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

总结:

  • 如果父类提供了具体实现,优先使用父类的方法。
  • 如果接口之间方法冲突,需要在实现类中明确指定使用哪个接口的默认方法。

# 2. 接口中的静态方法

Java 8 中,接口允许定义静态方法。这使得接口可以像类一样包含静态方法,这些静态方法只能通过接口名调用,而不能通过实现类或对象调用。

语法格式:

public interface MyInterface {
    static void show() {
        System.out.println("接口中的静态方法");
    }
}
1
2
3
4
5

主要特点:

  • 只能通过接口名调用:接口中的静态方法不能被实现类继承或重写,必须通过接口名调用。
  • 适用于工具方法:静态方法通常用于提供与接口相关的工具方法。

代码示例:

public interface MyInterface {
    // 定义一个静态方法
    static void show() {
        System.out.println("接口中的静态方法");
    }
}

public class TestStaticMethod {
    public static void main(String[] args) {
        // 通过接口名调用静态方法
        MyInterface.show(); // 输出:接口中的静态方法
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3. 实际开发中的应用场景

  • 默认方法的使用场景:

    • 扩展已有接口:当需要向已有接口添加新功能时,可以通过默认方法避免破坏已有实现。
    • 多继承冲突的解决:在实现多个接口时,如果接口中存在相同方法签名的默认方法,需要手动解决冲突。
  • 静态方法的使用场景:

    • 提供工具类方法:可以在接口中定义与接口相关的实用工具方法,避免在实现类中重复实现这些方法。
    • 实现工厂方法:可以通过静态方法提供接口的默认实现或工厂方法。

# 4. 常见问题与注意事项

  • 默认方法与抽象方法的冲突:如果接口中定义了一个默认方法,而实现类又定义了相同签名的抽象方法,那么实现类必须提供该方法的实现。
  • 接口静态方法与类静态方法的区分:接口静态方法只能通过接口名调用,不能通过实现类或接口实例调用。

# 5. 完整代码示例与总结

完整代码示例:

// 定义接口 MyFun,包含默认方法和静态方法
public interface MyFun {
    default String getName() {
        return "接口 MyFun 的默认方法";
    }

    static void staticMethod() {
        System.out.println("接口 MyFun 的静态方法");
    }
}

// 定义另一个接口 MyInterface,包含默认方法和静态方法
public interface MyInterface {
    default String getName() {
        return "接口 MyInterface 的默认方法";
    }

    static void staticMethod() {
        System.out.println("接口 MyInterface 的静态方法");
    }
}

// 定义实现类,解决多接口默认方法的冲突
public class SubClass implements MyFun, MyInterface {
    @Override
    public String getName() {
        return MyFun.super.getName(); // 指定使用 MyFun 接口的默认方法
    }
}

// 测试类
public class TestInterfaceMethods {
    public static void main(String[] args) {
        SubClass sc = new SubClass();
        System.out.println(sc.getName()); // 输出:接口 MyFun 的默认方法

        // 调用接口静态方法
        MyFun.staticMethod(); // 输出:接口 MyFun 的静态方法
        MyInterface.staticMethod(); // 输出:接口 MyInterface 的静态方法
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

总结:

  • 默认方法使得接口可以演化和扩展而不破坏已有实现,特别适用于在框架或库中添加新特性。
  • 静态方法使得接口可以直接提供工具类方法或工厂方法,从而避免了在实现类中重复实现相同逻辑。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
对反射的支持增强
新时间日期API

← 对反射的支持增强 新时间日期API→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式