1. 程式人生 > >JAVA8介面中的default、static方法使用注意事項

JAVA8介面中的default、static方法使用注意事項

JAVA8中介面interface引入方法實現的猜想

在JAVA8之前java中的介面型別旨在定義型別的介面規約並不能擁有自己的方法實現,具體實現完全交由實現類自己完成

以普通人和中上階層為例,為各自的子女讀大學的目標:

  • 普通人大部分甚至可能全部都是告誡子女讀書畢業找份好工作;

  • 後者更多要求考TOEFL、GRE、出國留學回來做高管、出資給孩子創業;

介面規約的方法行為是寬泛的,無法具體實現; 
而現實中的實現則是 符合該規約的實體自己的實現。

但是在JAVA8中可以在介面中定義預設的行為、以及靜態方法的實現。 
你可以想象,人類文明發展到後面,大家都不需要工作了,完全交由機器人處理。這時候,人們的行為是一樣的: 出生 – 接受各種知識注入腦子裡–不工作–等待生命結束(或者永生)。 規約可以有一個稍微具體的實現。大家都可以使用該具體的行為。這就是JAVA8中的default、static方法。

default方法

在java.lang.Iterable介面中有一個預設的方法實現:

default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

default方法使用default關鍵字修飾,它是物件方法,需要使用物件來進行訪問。

以下的示例中,使用了JAVA8中的新註解 @FunctionalInterface

 表明該介面是一個函式式介面,只能擁有 一個抽象方法。

package com.byron4j.hightLevel.java8.lambda;


/**
 * 
 * <pre>
 *      介面型別 擁有自己的default、static方法實現
 *      @FunctionalInterface 表明該介面是一個函式式介面,只能擁有 一個抽象方法
 * </pre>
 * @author Byron.Y.Y
 */

@FunctionalInterface
public interface DefaultStaticMethodDemo {

    /*非default、static方法不能有實現
     * --否則編譯錯誤--Abstract methods do not specify a body
    void sayHello4CompilerError(){};
    */
void sayHello(); /*default、static方法必須有具體的實現 * --否則編譯錯誤--This method requires a body instead of a semicolon default void studyTarget(); */ default void studyTarget(){ System.out.println("出生"); System.out.println("\t--> 注入知識"); System.out.println("\t\t--> 生命消亡"); } //可以擁有多個default方法 default void studyTarget2(){ System.out.println("DefaultStaticMethodDemo#【default】studyTarget2 invok."); } //可以擁有多個static方法 static void info(){ System.out.println("DefaultStaticMethodDemo#【static】 info invok."); } public static void main(String[] args) { info(); new DefaultStaticMethodDemo() { //僅僅需要實現抽象方法 //default、static方法不需要強制自己新實現 @Override public void sayHello() { // TODO Auto-generated method stub } }; } }
  • 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
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

介面中方法使用的注意事項

  • 非default、static方法不能有實現,否則編譯錯誤:Abstract methods do not specify a body

  • default、static方法必須有具體的實現,否則編譯錯誤:This method requires a body instead of a semicolon

  • 可以擁有多個default方法

  • 可以擁有多個static方法

  • 使用介面中型別時,僅僅需要實現抽象方法,default、static方法不需要強制自己新實現

實現多個介面引發的問題

多個介面存在簽名一樣的default方法導致編譯錯誤

JAVA8中實現多個介面可能引發的問題:多個介面存在簽名一樣的default方法導致編譯錯誤。

又有一個介面DefaultStaticMethodDemo2 和DefaultStaticMethodDemo都擁有一樣的簽名的default studyTarget方法:

package com.byron4j.hightLevel.java8.lambda;


/**
 * 
 * <pre>
 *      介面型別 擁有自己的default、static方法實現
 *      @FunctionalInterface 表明該介面是一個函式式介面,只能擁有 一個抽象方法
 * </pre>
 * @author Byron.Y.Y
 */

public interface DefaultStaticMethodDemo2 {


    default void studyTarget(){
        System.out.println("出生");
        System.out.println("\t--> 注入知識");
        System.out.println("\t\t--> 生命消亡");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

因為可以實現多個介面,所以類SubClassDemo實現了DefaultStaticMethodDemo、DefaultStaticMethodDemo2,但是編譯不通過:

package com.byron4j.hightLevel.java8.lambda;


//編譯錯誤:Duplicate default methods named studyTarget 
//  with the parameters () and () are inherited from the
//types DefaultStaticMethodDemo2 and DefaultStaticMethodDemo
public class SubClassDemo implements 
        DefaultStaticMethodDemo, DefaultStaticMethodDemo2{

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

這就相當於你在類中定義了兩個同樣的簽名方法,從而引致編譯錯誤。

繼承抽象類同時實現介面引發的問題

如果一個類實現了某個擁有default方法的介面的話,在該類中則不需要自己再次實現該default方法了

但是如果該類實現介面時,還繼承了某個抽象類,該抽象類擁有一個和default簽名一樣的抽象方法,則在該類中必須重寫抽象方法(也是介面中的該default方法)

抽象類AbstractClassDemo 擁有和介面DefaultStaticMethodDemo同安用的簽名方法studyTarget

package com.byron4j.hightLevel.java8.lambda;

public abstract class AbstractClassDemo {
    abstract void studyTarget();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

類SubClassDemo2 必須重寫studyTarget方法

package com.byron4j.hightLevel.java8.lambda;


/**
 * 
 * <pre>
 *      繼承抽象類
 *      實現介面
 *      抽象類、介面存在同樣的簽名方法
 *      抽象類未有實現體;介面中default實現了方法。
 * </pre>
 * @author Byron.Y.Y
 */
public class SubClassDemo2 extends AbstractClassDemo implements 
        DefaultStaticMethodDemo {

    @Override
    public void sayHello() {
        // TODO Auto-generated method stub

    }

    @Override
    public void studyTarget() {
        // TODO Auto-generated method stub

    }

}
  • 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

其他注意事項

抽象類、介面存在同樣的簽名方法,抽象類有實現體但是不是public修飾的;—-> 編譯錯誤:抽象介面中的實現不能隱藏介面中的方法;—->解決辦法:將抽象類中的方法訪問控制符使用public修飾。

package com.byron4j.hightLevel.java8.lambda;

public abstract class AbstractClassDemo2 {
    void sayHello(){
        System.out.println("抽象類的sayHello!");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
package com.byron4j.hightLevel.java8.lambda;



/**
 * 
 * <pre>
 *      繼承抽象類
 *      實現介面
 *      抽象類、介面存在同樣的簽名方法
 *      抽象類有實現體但是不是public修飾的;
 *-------------編譯錯誤:抽象介面中的實現不能隱藏介面中的方法
 *-------------解決辦法:將抽象類中的方法訪問控制符使用public修飾
 * </pre>
 * @author Byron.Y.Y
 */
public class SubClassDemo3 extends AbstractClassDemo2 implements 
        DefaultStaticMethodDemo {



}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

抽象類AbstractClassDemo2 擁有和介面DefaultStaticMethodDemo相同簽名的方法sayHello,但是AbstractClassDemo2 的實現不是public的引發編譯錯誤。

相關推薦

JAVA8介面defaultstatic方法使用注意事項

JAVA8中介面interface引入方法實現的猜想在JAVA8之前java中的介面型別旨在定義型別的介面規約,並不能擁有自己的方法實現,具體實現完全交由實現類自己完成。以普通人和中上階層為例,為各自的子女讀大學的目標:普通人大部分甚至可能全部都是告誡子女讀書畢業找份好工作;

Java8 介面default方法帶來的問題

介面中預設方法中的問題:預設方法的出現,是為了方便 當所有實現類都需要新增某個方法時,在介面中能直接寫實現過程。但是,如果某個類,實現了兩個介面,並且這兩個介面有同名預設方法,那麼這個類就無法判斷是繼承的是誰的類。必須要在繼承方法體中,宣告繼承的是哪個實現類的方法。 例如:

jdk1.8的介面default修飾的方法

我用的的是jdk1.8,某次在編寫某個類實現listener介面的時候,發現ide沒有提示實現介面的方法,有點迷就去介面原始碼去看了一下,看到接口裡的方法竟然可以定義為default型別,加了一個def

js物件原型(prototype)的使用方法替換以及注意事項

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <t

Java8新特性-003-Java8介面default修飾符

Java 8新增了default方法,它可以在介面新增新功能特性,而且還不影響介面的實現類。 另外,新增的default方法不會影響函式式介面。 Default方法是非常有用的,通過在介面定義的方法的

Javathisstaticsuperfinal

this class Person { public String _name; public int _age; public Person() //無參構造 { System.out.println("Person()");

Calendar的get()set()和roll()方法注意事項

轉載:http://blog.sina.com.cn/s/blog_677873910102vcp7.html 示例程式碼: Calendar c = Calendar.getInstance();   c.set(2014, Ca

Javathisstatic關鍵字的記憶體圖解

  Java中的關鍵字有很多,abstract  default  goto*  null  switch  boolean  do  if  package  nchronzed  break&nb

Javathisstatic關鍵字的內存圖解

數據區 prot 屬性 volatile stat strong 發展 char ons Java中的關鍵字有很多,abstract default goto* null switch boolean do if package nchronzed

NIO bufferclearcompact方法的區別

呼叫clear()方法:position將被設回0,limit設定成capacity,換句話說,Buffer被清空了,其實Buffer中的資料並未被清除,只是這些標記告訴我們可以從哪裡開始往Buffer裡寫資料。如果Buffer中有一些未讀的資料,呼叫clear()方法,資料將“被遺忘”,意

接口裡的defaultstatic方法

我們都知道接口裡的變數預設隱含型別是public static final,也是就是說是常量。而方法預設型別是public abstract,所以介面的方法都是抽象方法,但是事實真的是這樣嗎? 我的PC上安裝的是jdk1.8,一次編寫介面程式碼的時候,看到接口裡的方法竟然可以定義為def

Java floatdouble使用注意問題

在java中執行一下程式碼 System.out.println(2.00-1.10); 輸出的結果是:0.8999999999999999 很奇怪,並不是我們想要的值0.9 再執行如下程式碼: System.out.println(2.00f-1.10f);

java--類繼承和實現的介面含有相同的方法

首先,說一下,當某一個類實現了兩個介面的時候,兩個介面中存在兩個相同的方法,在實現的類中只需實現一個方法的方法體。當一個類繼承一個類,並且實現一個或者多個介面的時候,其中,父類和父介面中存在相同的方法。  如果子類中存在該方法的實現體或者說是覆蓋,則使用該類的物件去掉用該方法

Jmeter HTTP介面案例開發除錯方法

HTTP介面案例案例開發的步驟為: 1.瞭解要開發案例的業務流程,比如新增案例,是否有其它前置條件,如果有,就需要先開發好前置條件的案例 2.手工開發案例或者通過jmeter錄製功能開發案例 3.對案例進行除錯,響應結果和預期結果一致,則案例開發完成 對於簡單

Hibernate的Session介面save/delete/update方法2個引數(entityName)的深入解析

Hibernate的Session介面中delete/update方法2個引數(entityName)的深入解析 2010-09-14 18:07 session.update(Object arg0); session.update(String arg0, Obje

ScannernextnextLinenextInt使用注意事項

next()和nextLine()區別 next()會自動過濾空格、tab、enter等結束符,直至遇到有效字元之後,空格、tab、enter等會視為結束符 nextLine()掃描整行即enter之前的所有字元(包括空格、tab等) 在nextInt()後使用nextLine()後ne

有關Java實體類getset方法和有參無參構造方法的個人見解。

結論:(總的來說,get和set方法就是為了能以得到和設定實體類中的私有屬性值,而一個類中至少要有一個構造方法,當沒有人為新增的時候,編譯器會自動加入一個隱式的無參構造方法,當有人為新增時,編譯器就不會自動添加了。無參構造方法的作用是為了比較方便的new出一個物

C/C++autostaticregisterextern關鍵字區別小結

1. 說明   以上四種都是變數儲存說明符,因為C/C++語言在變數定義時候的完整語法是:      [儲存說明符] [資料型別] [變數名稱] [=初始化];   因為大多我們宣告的變數都

Callable介面何時執行call方法

import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.

Tensorflow兩種資料讀取方法應用對比及注意事項

本文對比介紹了兩種Tensorflow針對大資料集的資料讀取方法,具體來說是:方法1:tf.train.slice_input_producer+流水線(這裡用這個API指代這一類,其實還有其他的API)。方法2:Dataset方法,據說是Tensorflow 1.3版本之後