Java8接口:静态方法与默认方法

阅读原文: Java8接口:静态方法与默认方法

往期文章一览

  1. 为什么我要使用Optional ?

  2. 为什么数组下总是从0开始呢?

  3. 这种方式更优雅,秒表计时!

Java8 接口更改包括接口中的静态方法和默认方法。在 Java8 之前,接口中只能有方法声明,但是从 Java 8 开始,我们可以在接口中使用默认方法和静态方法。

Java 8 接口

设计接口一直是一项艰巨的工作,因为如果我们想在接口中添加其他方法,就需要在所有实现类中进行更改。随着接口的老化,实现它的类的数量可能会增长到无法扩展接口的程度。这就是为什么在设计应用程序时,大多数框架提供一个基本实现类,然后我们扩展它并重写适用于我们的应用程序的方法。

让我们看看默认接口方法和静态接口方法,以及它们在 Java8 接口更改中引入的原因。

Java 接口默认方法

为了在 java 接口中创建默认方法,我们需要在方法签名中使用“default”关键字。例如:

package com.journaldev.java8.defaultmethod;

public interface Interface1 {

    void method1(String str);

    default void log(String str){
        System.out.println("I1 logging::"+str);
    }
}

注意,log(String str)是 Interface1 中的默认方法。现在,当一个类将实现 Interface1 时,不必为接口的默认方法提供实现。这个特性将帮助我们用额外的方法扩展接口,我们只需要提供一个默认的实现。

假设我们有另一个具有以下方法的接口:

package com.journaldev.java8.defaultmethod;

public interface Interface2 {

    void method2();

    default void log(String str){
        System.out.println("I2 logging::"+str);
    }
}

我们知道 Java 不允许我们继承多个类,因为它会导致“菱形问题”,编译器无法决定使用哪个超类方法。使用默认方法时,接口也会出现菱形问题。因为如果一个类同时实现了 Interface1 和 Interface2 并且没有实现公共的默认方法,编译器就不能决定选择哪个方法。

扩展多个接口是 Java 不可或缺的一部分,您可以在核心 Java 类以及大多数企业应用程序和框架中找到它。因此,为了确保这个问题不会出现在接口中,必须为接口的常见默认方法提供实现。因此,如果一个类同时实现上述两个接口,则它必须为 log()方法提供实现,否则编译器将抛出编译时错误。

实现 Interface1 和 Interface2 的一个简单类是:

package com.journaldev.java8.defaultmethod;

public class MyClass implements Interface1, Interface2 {

    @Override
    public void method2() {
    }

    @Override
    public void method1(String str) {
    }

    @Override
    public void log(String str){
        System.out.println("MyClass logging::"+str);
        Interface1.print("abc");
    }
}

关于 java 接口默认方法的要点:

  1. Java 接口默认方法将帮助我们扩展接口,而不必担心破坏实现类。

  2. Java 接口默认方法弥补了接口和抽象类之间的差异。

  3. Java 8 接口默认方法将帮助我们避免使用工具类,例如所有 Collections 类方法都可以在接口本身中提供。

  4. Java 接口默认方法将帮助我们删除基本实现类,我们可以提供默认实现,实现类可以选择重写哪个。

  5. 在接口中引入默认方法的一个主要原因是为了增强 Java 8 中的 Collections API 以支持 lambda 表达式。

  6. 如果层次结构中的任何类具有具有相同签名的方法,则默认方法将变得不相关。默认方法不能重写 java.lang.Object 中的方法。推理非常简单,因为 Object 是所有 java 类的基类。因此,即使我们在接口中将 Object 类方法定义为默认方法,它也将是无用的,因为 Object 类方法将始终被使用。这就是为什么要避免混淆,我们不能有覆盖 Object 类方法的默认方法。

  7. Java 接口默认方法也称为 Defender 方法或虚拟扩展方法。

Java 接口静态方法

Java 接口静态方法与默认方法类似,只是我们不能在实现类中重写它们。这个特性有助于我们避免实现类中的糟糕实现带来的不希望的结果。让我们用一个简单的例子来研究这个问题。

package com.journaldev.java8.staticmethod;

public interface MyData {

    default void print(String str) {
        if (!isNull(str))
            System.out.println("MyData Print::" + str);
    }

    static boolean isNull(String str) {
        System.out.println("Interface Null Check");

        return str == null ? true : "".equals(str) ? true : false;
    }
}

现在让我们看看一个实现类,它的 isNull()方法的实现很差。

package com.journaldev.java8.staticmethod;

public class MyDataImpl implements MyData {

    public boolean isNull(String str) {
        System.out.println("Impl Null Check");
        return str == null ? true : false;
    }

    public static void main(String args[]){
        MyDataImpl obj = new MyDataImpl();
        obj.print("");
        obj.isNull("abc");
    }
}

注意,isNull(String str)是一个简单的类方法,它没有重写接口方法。例如,如果我们将@Override 注释添加到 isNull()方法中,将导致编译器错误。
现在,当我们运行应用程序时,会得到以下输出。

Interface Null Check
Impl Null Check

如果我们将接口方法从 static 设置为 default,我们将得到以下输出。

Impl Null Check
MyData Print::
Impl Null Check

Java 接口静态方法仅对接口方法可见,如果我们从 MyDataImpl 类中移除 isNull()方法,我们将无法将其用于 MyDataImpl 对象。但是和其他静态方法一样,我们可以使用类名来使用接口静态方法。例如,有效语句将是:

boolean result = MyData.isNull("abc");

java 接口静态方法要点:

  1. Java 接口静态方法是接口的一部分,不能用于实现类对象。
  2. Java 接口静态方法适合于提供实用方法,例如空检查、集合排序等。
  3. Java 接口静态方法通过不允许实现类重写它们来帮助我们提供安全性。
  4. 我们不能为 Object 类方法定义接口静态方法,我们将得到编译器错误为“这个静态方法不能从 Object 中隐藏实例方法”。这是因为在 java 中不允许这样做,因为 Object 是所有类的基类,我们不能有一个类级静态方法和另一个具有相同签名的实例方法。
  5. 我们可以使用 java 接口静态方法来移除诸如集合之类的实用工具类,并将其所有静态方法移动到相应的接口,这样就很容易找到和使用。

Java 函数式接口

在结束本文之前,我想简单介绍一下功能接口。只有一个抽象方法的接口称为函数式接口。

引入了一个新的注释@functionainterface 来将接口标记为 Functional 接口。@functionainterface 注释是一种避免在功能接口中意外添加抽象方法的工具。这是可选的,但使用它是很好的实践。

Java 8 的功能性接口是人们期待已久且备受关注的特性,因为它使我们能够使用 lambda 表达式来实例化它们。添加了一个新的包 java.util.function 和一堆函数接口,为 lambda 表达式和方法引用提供目标类型。我们将在以后的文章中研究函数接口和 lambda 表达式。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,629评论 0 11
  • 一、基础知识:1、JVM、JRE和JDK的区别:JVM(Java Virtual Machine):java虚拟机...
    杀小贼阅读 2,365评论 0 4
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 1,045评论 0 4
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,089评论 1 32
  • 第十八章 门开 权新禹低着头,看着这条只有五个字的短信。四周很寂静,来来往往的人走过他的身边。 权新禹抬起头来,看...
    宝弓阅读 142评论 0 0