国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JDK8新特性-上部

這篇具有很好參考價(jià)值的文章主要介紹了JDK8新特性-上部。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

??博客x主頁(yè):己不由心王道長(zhǎng)??!
??文章說(shuō)明:JDK8新特性??
?系列專欄:Java基礎(chǔ)
??本篇內(nèi)容:對(duì)JDK8的新特性進(jìn)行學(xué)習(xí)和講解??
??每日一語(yǔ):這個(gè)世界本來(lái)就不完美,如果我們?cè)俨唤邮懿煌昝赖淖约?,那我們要怎么活??
?? 交流社區(qū):己不由心王道長(zhǎng)(優(yōu)質(zhì)編程社區(qū))

一、Java發(fā)展史

1.1 發(fā)展史

Sun公司在1991年成立了一個(gè)稱為綠色計(jì)劃( Green Project )的項(xiàng)目,由James Gosling(高斯林)博土領(lǐng)導(dǎo),綠色計(jì)劃的目的是開發(fā)一種能夠在各種消費(fèi)性電子產(chǎn)品(機(jī)頂盒、冰箱、收音機(jī)等)上運(yùn)行的程序架構(gòu)。這個(gè)項(xiàng)目的產(chǎn)品就是Java語(yǔ)言的前身: Oak(橡樹)。Oak當(dāng)時(shí)在消費(fèi)品市場(chǎng)上并不算成功,但隨著1995年互聯(lián)網(wǎng)潮流的興起,Oak迅速找到了最適合自己發(fā)展的市場(chǎng)定位。

- JDK Beta - 1995v
- JDK 1.0 - 1996年1月 (真正第一個(gè)穩(wěn)定的版本JDK 1.0.2,被稱作 Java 1 )
- JDK 1.1 - 1997年2月
- J2SE 1.2 - 1998年12月
- J2ME(Java 2 Micro Edition,Java 2平臺(tái)的微型版),應(yīng)用于移動(dòng)、無(wú)線及有限- 資源的環(huán)境。
- J2SE(Java 2 Standard Edition,Java 2平臺(tái)的標(biāo)準(zhǔn)版),應(yīng)用于桌面環(huán)境。
- J2EE(Java 2 Enterprise Edition,Java 2平臺(tái)的企業(yè)版),應(yīng)用于基于Java的應(yīng)用服務(wù)器。
- J2SE 1.3 - 2000年5月
- J2SE 1.4 - 2002年2月
- J2SE 5.0 - 2004年9月
- Java SE 6 - 2006年12月
- Java SE 7 - 2011年7月
- Java SE 8(LTS) - 2014年3月
- Java SE 9 - 2017年9月
- Java SE 10(18.3) - 2018年3月
- Java SE 11(18.9 LTS) - 2018年9月
- Java SE 12(19.3) - 2019年3月
- Java SE 13(19.9) - 2019年9月
- Java SE 14(20.3) - 2020年3月
- Java SE 15(20.9) - 2020年9月

我們可以看到Java SE的主要版本大約每?jī)赡臧l(fā)布一次,直到Java SE 6到Java SE 7開始花了五年時(shí)間,之后又花了三年時(shí)間到達(dá)Java SE 8。

1.2 OpenJDK和OracleJDK

1.2.1 Open JDK來(lái)源:

Java 由 Sun 公司發(fā)明,Open JDK是Sun在2006年末把Java開源而形成的項(xiàng)目。也就是說(shuō)Open JDK是Java SE平臺(tái)版的開源和免費(fèi)實(shí)現(xiàn),它由 SUN 和 Java 社區(qū)提供支持,2009年 Oracle 收購(gòu)了 Sun 公司,自此 Java 的維護(hù)方之一的SUN 也變成了 Oracle

1.2.2 Open JDK 和 Oracle JDK的關(guān)系:

大多數(shù) JDK 都是在 Open JDK 的基礎(chǔ)上進(jìn)一步編寫實(shí)現(xiàn)的,比如 IBM J9, Oracle JDK 和 Azul Zulu,Azul Zing。

Oracle JDK完全由 Oracle 公司開發(fā),Oracle JDK是基于Open JDK源代碼的商業(yè)版本。此外,它包含閉源組件。Oracle JDK根據(jù)二進(jìn)制代碼許可協(xié)議獲得許可,在沒(méi)有商業(yè)許可的情況下,在2019年1月之后發(fā)布的Oracle Java SE 8的公開更新將無(wú)法用于商業(yè)或生產(chǎn)用途。但是 Open JDK是完全開源的,可以自由使用。

1.3 Open JDK 官網(wǎng)介紹

Open JDK 官網(wǎng): http://openjdk.java.net/ 。
JDK Enhancement Proposals(JDK增強(qiáng)建議)。通俗的講JEP就是JDK的新特性.

小結(jié):

Oracle JDK是基于Open JDK源代碼的商業(yè)版本。我們要學(xué)習(xí)Java新技術(shù)可以去Open JDK 官網(wǎng)學(xué)習(xí)。

JDK8新特性-上部

二、Lambda表達(dá)式

在最開始我們先創(chuàng)建一個(gè)maven工程,很多東西需要添加依賴

2.1 需求分析

創(chuàng)建一個(gè)新的線程,指定線程要執(zhí)行的任務(wù):

package com.daozhang;

/**
 * @Author Administrator
 * @Date 2023/6/24 20:19
 * @description
 * @Version 1.0
 */
public class application {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("測(cè)試線程執(zhí)行代碼:"+Thread.currentThread().getName());
            }
        }).start();
        System.out.println("主線程執(zhí)行的代碼:"+Thread.currentThread().getName());
    }
}

代碼分析:

  1. Thread類需要一個(gè)Runnable接口作為參數(shù)(線程的實(shí)現(xiàn)有三種實(shí)現(xiàn)方式),其中的抽象方法run方法是用來(lái)指定線程任務(wù)內(nèi)容的核心。
  2. 為了指定run方法體,不得不需要Runnable的實(shí)現(xiàn)類。
  3. 為了省去定義一個(gè)Runnable 的實(shí)現(xiàn)類,不得不使用匿名內(nèi)部類。
  4. 必須覆蓋重寫抽象的run方法,所有的方法名稱,方法參數(shù),方法返回值不得不都重寫一遍,而且不能出錯(cuò)。
  5. 而實(shí)際上,我們只在乎方法體中的代碼。

2.2 Lamada表達(dá)式的體驗(yàn)

Lambda表達(dá)式是一個(gè)匿名函數(shù),可以理解為一段可以傳遞的代碼。

new Thread(() -> { System.out.println("新線程Lambda表達(dá)式..."
+Thread.currentThread().getName()); })
.start();

Lambda表達(dá)式的優(yōu)點(diǎn):簡(jiǎn)化了匿名內(nèi)部類的使用,語(yǔ)法更加簡(jiǎn)單。匿名內(nèi)部類語(yǔ)法冗余,體驗(yàn)了Lambda表達(dá)式后,發(fā)現(xiàn)Lambda表達(dá)式是簡(jiǎn)化匿名內(nèi)部類的一種方式。

2.3 Lambda表達(dá)式的語(yǔ)法規(guī)則

實(shí)際上Lambda省去了面向?qū)ο蟮臈l條框框,Lambda的標(biāo)準(zhǔn)格式由3個(gè)部分組成:

(參數(shù)類型 參數(shù)名稱) -> {
代碼體;
}

格式說(shuō)明:

  • (參數(shù)類型 參數(shù)名稱):參數(shù)列表
  • {代碼體;} :方法體
  • -> : 箭頭,分割參數(shù)列表和方法體
2.3.1 Lambda表達(dá)式練習(xí)

一、練習(xí)無(wú)參無(wú)返回值的Lambda:

1.1 首先定義一個(gè)接口:

package com.daozhang.student;

/**
 * @Author Administrator
 * @Date 2023/6/24 20:31
 * @description 定義一個(gè)Lambda表達(dá)式學(xué)生接口
 * @Version 1.0
 */
public interface Student {
    void gotoSchool();//大學(xué)生,主打一個(gè)喜歡上學(xué)
}

1.2 然后我們?cè)谥鞣椒▌?chuàng)建使用:

 //在這里我們調(diào)用loveComeToSchool,首先接口肯定是不能new的,這時(shí)候肯定是匿名方式
        //1、傳統(tǒng)方式(匿名內(nèi)部類方式)
        loveComeToSchool(new Student() {
            @Override
            public void gotoSchool() {
                System.out.println("匿名內(nèi)部類方式上學(xué):"+Thread.currentThread().getName());
            }
        });

        //2、Lambda表達(dá)式方式
        loveComeToSchool(()->{
            System.out.println("Lambda表達(dá)式方式,同樣上學(xué)");
        });

1.3 結(jié)果展示:

匿名內(nèi)部類方式上學(xué):main
Lambda表達(dá)式方式,同樣上學(xué)

1.4小結(jié):可以看到,Lambda表達(dá)式十分簡(jiǎn)潔

2.3.2 Lambda表達(dá)式練習(xí)

二、練習(xí)有參無(wú)返回值的Lambda:

Java有兩種方法,有參和無(wú)參,無(wú)參說(shuō)了,聊聊有參!

2.1、創(chuàng)建對(duì)象

2.1.1這里使用到了Lombok,先導(dǎo)入依賴:

<dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.16.10</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

2.1.2、person類:

package com.daozhang.pojos;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @Author Administrator
 * @Date 2023/6/24 20:47
 * @description
 * @Version 1.0
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
    private Integer high;
}

2.1.3、然后我們?cè)贚ist集合中保存多個(gè)Person對(duì)象,然后對(duì)這些對(duì)象做根據(jù)age排序操作

package com.daozhang;

import com.daozhang.pojos.Person;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @Author Administrator
 * @Date 2023/6/24 20:47
 * @description
 * @Version 1.0
 */
public class test02 {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person("王道長(zhǎng)",18,185));//男神!??!
        list.add(new Person("諸葛青",20,183));//不聽(tīng)八卦
        list.add(new Person("不要碧蓮",19,182));//月下光觀鳥
        list.add(new Person("寶兒姐",18,168)); //阿威十八式
        //使用Collections對(duì)list進(jìn)行排序
        //1、傳統(tǒng)方式
        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                //按照年齡排序
                return o1.getAge()-o2.getAge();
            }
        });
        System.out.println("傳統(tǒng):");
        for(Person person:list){
            System.out.println(person);
        }
        //2、Lambda方式
        Collections.sort(list,(Person o1,Person o2)->{
            return o1.getAge()-o2.getAge();
        });

        System.out.println("Lambda:");
        for(Person person:list){
            System.out.println(person);
        }
    }
}

結(jié)果:

"C:\Program Files\Java\jdk1.8.0_102\bin\java.exe" "-javaagent:D:\idea\IntelliJ IDEA 2021.3.2\lib\idea_rt.jar=7588:D:\idea\IntelliJ IDEA 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_102\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_102\jre\lib\rt.jar;D:\JDK8\JDK8\target\classes" com.daozhang.test02
傳統(tǒng):
Person(name=王道長(zhǎng), age=18, high=185)
Person(name=寶兒姐, age=18, high=168)
Person(name=不要碧蓮, age=19, high=182)
Person(name=諸葛青, age=20, high=183)
Lambda:
Person(name=王道長(zhǎng), age=18, high=185)
Person(name=寶兒姐, age=18, high=168)
Person(name=不要碧蓮, age=19, high=182)
Person(name=諸葛青, age=20, high=183)

Process finished with exit code 0

2.4 Lambda表達(dá)式的使用前提

可以看出,Lambda表達(dá)式的語(yǔ)法十分簡(jiǎn)潔,但是Lambda表達(dá)式不是隨便使用的,使用的使用有幾個(gè)條件我們需要特別注意:

一、方法的參數(shù)或局部變量類型必須為接口才能使用Lambda。
二、接口中有且只有一個(gè)抽象方法(在第五小段會(huì)提及一個(gè)注解@FunctionalInterfa)

2.5 @FunctionalInterface注解

我們?cè)谏厦嫣峒埃琇ambda表達(dá)式接口中有且只有一個(gè)抽象方法,那么我們?cè)趺醋龅竭@一點(diǎn)呢?就是使用FunctionalInterface注解修飾

package com.daozhang.student;

/**
 * @Author Administrator
 * @Date 2023/6/24 20:31
 * @description 定義一個(gè)Lambda表達(dá)式學(xué)生接口
 * @Version 1.0
 */
@FunctionalInterface
public interface Student {
    /**
     * @FunctionalInterface:一個(gè)標(biāo)準(zhǔn)注解,被該注解修飾的接口只能聲明一個(gè)抽象方法
     */
    void gotoSchool();
}

2.6 Lambda表達(dá)式的原理

匿名內(nèi)部類的原理:匿名內(nèi)部類的本質(zhì)是在編譯時(shí)生成一個(gè)Class 文件。XXXXX$1.class

package com.daozhang;

import com.daozhang.student.Student;

/**
 * @Author Administrator
 * @Date 2023/6/24 20:19
 * @description
 * @Version 1.0
 */
public class test01 {
    public static void main(String[] args) {
//        new Thread(new Runnable() {
//            @Override
//            public void run() {
//                System.out.println("測(cè)試線程執(zhí)行代碼:"+Thread.currentThread().getName());
//            }
//        }).start();
//        System.out.println("主線程執(zhí)行的代碼:"+Thread.currentThread().getName());

        //在這里我們調(diào)用loveComeToSchool,首先接口肯定是不能new的,這時(shí)候肯定是匿名方式
        //1、傳統(tǒng)方式(匿名內(nèi)部類方式)
        loveComeToSchool(new Student() {
            @Override
            public void gotoSchool() {
                System.out.println("匿名內(nèi)部類方式上學(xué):"+Thread.currentThread().getName());
            }
        });

        //2、Lambda表達(dá)式方式
        loveComeToSchool(()->{
            System.out.println("Lambda表達(dá)式方式,同樣上學(xué)");
        });
    }


    public static void loveComeToSchool(Student student){
        student.gotoSchool();
    }
}

JDK8新特性-上部
還可以通過(guò)反編譯工具來(lái)查看生成的代碼 XJad 工具來(lái)查看:

// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   test01.java

package com.daozhang;

import com.daozhang.student.Student;
import java.io.PrintStream;

// Referenced classes of package com.daozhang:
//			test01

static class test01$1
	implements Student
{

	public void gotoSchool()
	{
		System.out.println((new StringBuilder()).append("匿名內(nèi)部類方式上學(xué):").append(Thread.currentThread().getName()).toString());
	}

	test01$1()
	{
	}
}

那么Lambda表達(dá)式的原理是什么呢?我們也通過(guò)反編譯工具來(lái)查看:不僅看不了,還關(guān)不了!??!JDK8新特性-上部
解決辦法:ctrl+alt+'.'打開任務(wù)管理器,找到對(duì)應(yīng)位置選擇結(jié)束任務(wù)

那我們?cè)趺捶淳幾gLambda表達(dá)式的字節(jié)碼文件呢?,使用JDK自帶的javap命令

  • javap -c -p 文件名.class
    -c:表示對(duì)代碼進(jìn)行反匯編
    -p:顯示所有的類和成員

反匯編結(jié)果:

final class com.daozhang.test02$1 implements java.util.Comparator<com.daozhang.pojos.Person> {
  com.daozhang.test02$1();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public int compare(com.daozhang.pojos.Person, com.daozhang.pojos.Person);
    Code:
       0: aload_1
       1: invokevirtual #2                  // Method com/daozhang/pojos/Person.getAge:()Ljava/lang/Integer;
       4: invokevirtual #3                  // Method java/lang/Integer.intValue:()I
       7: aload_2
       8: invokevirtual #2                  // Method com/daozhang/pojos/Person.getAge:()Ljava/lang/Integer;
      11: invokevirtual #3                  // Method java/lang/Integer.intValue:()I
      14: isub
      15: ireturn

  public int compare(java.lang.Object, java.lang.Object);
    Code:
       0: aload_0
       1: aload_1
       2: checkcast     #4                  // class com/daozhang/pojos/Person
       5: aload_2
       6: checkcast     #4                  // class com/daozhang/pojos/Person
       9: invokevirtual #5                  // Method compare:(Lcom/daozhang/pojos/Person;Lcom/daozhang/pojos/Person;)I
      12: ireturn
}

小結(jié):
匿名內(nèi)部類在編譯的時(shí)候會(huì)產(chǎn)生一個(gè)class文件。
Lambda表達(dá)式在程序運(yùn)行的時(shí)候會(huì)形成一個(gè)類。

  1. 在類中新增了一個(gè)方法,這個(gè)方法的方法體就是Lambda表達(dá)式中的代碼。
  2. 還會(huì)形成一個(gè)匿名內(nèi)部類,實(shí)現(xiàn)接口,重寫抽象方法。
  3. 在接口中重寫方法會(huì)調(diào)用新生成的方法。

2.7 Lambda表達(dá)式的省略寫法

在lambda表達(dá)式的標(biāo)準(zhǔn)寫法基礎(chǔ)上,可以使用省略寫法的規(guī)則為:

  1. 小括號(hào)內(nèi)的參數(shù)類型可以省略
  2. 如果小括號(hào)內(nèi)有且僅有一個(gè)參數(shù),則小括號(hào)可以省略
  3. 如果大括號(hào)內(nèi)有且僅有一個(gè)語(yǔ)句,可以同時(shí)省略大括號(hào),return 關(guān)鍵字及語(yǔ)句分號(hào)。
package com.daozhang;

import com.daozhang.student.Student;

/**
 * @Author Administrator
 * @Date 2023/6/25 18:52
 * @description
 * @Version 1.0
 */
public class test03 {
    public static void main(String[] args) {
        //省略寫法一:省略參數(shù)、大括號(hào)
       gotos(()->System.out.println("上學(xué)去了"));
    }
    public static void gotos(Student student){
        student.gotoSchool();
    }
}

結(jié)果:

上學(xué)去了

2.8 Lambda表達(dá)式和內(nèi)部類的區(qū)別

Lambda和匿名內(nèi)部類的對(duì)比

  1. 所需類型不一樣
    匿名內(nèi)部類的類型可以是 類,抽象類,接口
    Lambda表達(dá)式需要的類型必須是接口
  2. 抽象方法的數(shù)量不一樣
    匿名內(nèi)部類所需的接口中的抽象方法的數(shù)量是隨意的
    Lambda表達(dá)式所需的接口中只能有一個(gè)抽象方法
  3. 實(shí)現(xiàn)原理不一樣
    匿名內(nèi)部類是在編譯后形成一個(gè)class
    Lambda表達(dá)式是在程序運(yùn)行的時(shí)候動(dòng)態(tài)生成class

三、接口的增強(qiáng)

3.1 JDK8接口新增

一、JDK8之前:

interface 接口名{
    1、靜態(tài)常量
    2、抽象方法
};

二、JDK8之后: 可以有默認(rèn)方法和靜態(tài)方法

interface 接口名{
   1、靜態(tài)常量;
   2、抽象方法;
   3、默認(rèn)方法;
   4、靜態(tài)方法;
}

3.2 默認(rèn)方法

一、為什么要有默認(rèn)方法?
在JDK8以前接口中只能有抽象方法和靜態(tài)常量,會(huì)存在以下的問(wèn)題:
如果接口中新增抽象方法,那么實(shí)現(xiàn)類都必須要抽象這個(gè)抽象方法,非常不利于接口的擴(kuò)展的:
當(dāng)接口只有一個(gè)方法時(shí),實(shí)現(xiàn)類去重寫:

package com.daozhang;

/**
 * @Author Administrator
 * @Date 2023/6/25 19:33
 * @description
 * @Version 1.0
 */
public class test04 {
    public static void main(String[] args) {

    }
}
interface animal{
    void eat();
}
class cat implements animal{

    @Override
    public void eat() {

    }
}
class dog implements animal{

    @Override
    public void eat() {
    }
}

當(dāng)接口有很多方法時(shí),實(shí)現(xiàn)類也可以重寫,但是每一個(gè)實(shí)現(xiàn)類都去重寫它不需要的方法,這合理嗎?:

package com.daozhang;

/**
 * @Author Administrator
 * @Date 2023/6/25 19:33
 * @description
 * @Version 1.0
 */
public class test04 {
    public static void main(String[] args) {

    }
}
interface animal{
    void run();
    void sing();
    void eat();
}
class cat implements animal{
     //必須重寫,不然報(bào)錯(cuò)
    @Override
    public void eat() {

    }
}
class dog implements animal{
   //必須重寫,不然報(bào)錯(cuò)

    @Override
    public void eat() {
    }
}

可以看出,上面接口顯然不符合我們的要求,所以在JDK8之后,就引入(增加)了默認(rèn)方法。

二、默認(rèn)方法的格式
以下是默認(rèn)方法的格式:

interface 接口名{
修飾符 default 返回值類型 方法名{
方法體;
}
}

默認(rèn)方法就是你想重寫就重寫,不重寫也不會(huì)強(qiáng)制你實(shí)現(xiàn)

package com.daozhang;

/**
 * @Author Administrator
 * @Date 2023/6/25 19:33
 * @description
 * @Version 1.0
 */
public class test04 {
    public static void main(String[] args) {
        animal cat = new cat();
        cat.gotoSchool();
    }
}
interface animal{
    void eat();
    public default String gotoSchool(){
        System.out.println("誰(shuí)說(shuō)動(dòng)物不用上學(xué)的?");
        return null;
    }
}
class cat implements animal{

    @Override
    public void eat() {

    }
}
class dog implements animal{

    @Override
    public void eat() {
    }
}

二、接口中默認(rèn)方法的使用:

  • 接口中的默認(rèn)方法有兩種使用方式
    1. 實(shí)現(xiàn)類直接調(diào)用接口的默認(rèn)方法
    1. 實(shí)現(xiàn)類重寫接口的默認(rèn)方法

3.3 靜態(tài)方法

一、在JDK8中在接口中增加了靜態(tài)方法,作用同樣是為了增加接口的擴(kuò)展性

二、語(yǔ)法規(guī)則:

interface 接口名{
修飾符 static 返回值類型 方法名{
方法體;
}
}
package com.daozhang;

/**
 * @Author Administrator
 * @Date 2023/6/25 19:33
 * @description
 * @Version 1.0
 */
public class test04 {
    public static void main(String[] args) {
        animal cat = new cat();
        cat.gotoSchool();
    }
}
interface animal{
    void eat();
    public default String gotoSchool(){
        System.out.println("誰(shuí)說(shuō)動(dòng)物不用上學(xué)的?");
        return null;
    }
    public static void makeFriend(){
        System.out.println("想找個(gè)女朋友");
    }
}
class cat implements animal{

    @Override
    public void eat() {

    }
}
class dog implements animal{

    @Override
    public void eat() {
    }
}

靜態(tài)方法的使用:
接口中的靜態(tài)方法在實(shí)現(xiàn)類中是不能被重寫的,調(diào)用的話只能通過(guò)接口類型來(lái)實(shí)現(xiàn): 接口名.靜態(tài)方法名();
注意:這里是不能重寫,而不是不需要

3.4 兩個(gè)方法之間的區(qū)別

  1. 默認(rèn)方法通過(guò)實(shí)例調(diào)用,靜態(tài)方法通過(guò)接口名調(diào)用
  2. 默認(rèn)方法可以被繼承,實(shí)現(xiàn)類可以直接調(diào)用接口默認(rèn)方法,也可以重寫接口默認(rèn)方法
  3. 靜態(tài)方法不能被繼承,實(shí)現(xiàn)類不能重寫接口的靜態(tài)方法,只能使用接口名調(diào)用

四、函數(shù)式接口

4.1 函數(shù)式接口的由來(lái)

我們知道使用Lambda表達(dá)式的前提是需要有函數(shù)式接口,而Lambda表達(dá)式使用時(shí)不關(guān)心接口名,抽象方法名。只關(guān)心抽象方法的參數(shù)列表和返回值類型。因此為了讓我們使用Lambda表達(dá)式更加的方法,在JDK中提供了大量常用的函數(shù)式接口。

/**
 * @Author Administrator
 * @Date 2023/6/25 21:01
 * @description
 * @Version 1.0
 */
public class functionTest01 {
    public static void main(String[] args) {
        funSum(arr->{
            int sum = 0;
            for(int i:arr){
                sum+=i;
            }
            return sum;
        });
    }
    public static void funSum(Operator operator){
        int[] arr ={5,6,7,8,9};
        int sum = operator.getArr(arr);
        System.out.println(sum);
    }
}
/*
* 函數(shù)式接口
*/
@FunctionalInterface
interface Operator{
    int getArr(int[] arr);
}

4.2 函數(shù)式接口的介紹

在JDK中幫我們提供的有函數(shù)式接口,主要是在 java.util.function 包中。

4.2.1 Supplier

一、無(wú)參有返回值的接口,對(duì)于的Lambda表達(dá)式需要提供一個(gè)返回?cái)?shù)據(jù)的類型。

/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

二、簡(jiǎn)單使用

/**
 * @Author Administrator
 * @Date 2023/6/25 21:17
 * @description
 * @Version 1.0
 */
public class Supplier {
    public static void main(String[] args) {
        fun(()->{
            int[] arr = {250,361,520};
            Arrays.sort(arr);
            return arr[arr.length-1];
        });
    }
    public static void fun(java.util.function.Supplier<Integer> supplier){
        Integer number = supplier.get();
        System.out.println(number);
    }
}

4.2.2 Consumer

一、有參無(wú)返回值得接口,前面介紹的Supplier接口是用來(lái)生產(chǎn)數(shù)據(jù)的,而Consumer接口是用來(lái)消費(fèi)數(shù)據(jù)的,使用的時(shí)候需要指定一個(gè)泛型來(lái)定義參數(shù)類型。

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);

二、簡(jiǎn)單使用

/**
 * @Author Administrator
 * @Date 2023/6/25 21:49
 * @description
 * @Version 1.0
 */
public class ConsumerTest {
    public static void main(String[] args) {
       fun2((t)->{
       //在方法體有動(dòng)作才會(huì)執(zhí)行方法,否則不會(huì)執(zhí)行方法
           System.out.println(t);
       });
    }
    public static  void fun2(Consumer<String> consumer){
        consumer.accept("唱跳rap");
    }
}

默認(rèn)方法:andThen
如果一個(gè)方法的參數(shù)和返回值全部是Consumer類型,那么就可以實(shí)現(xiàn)效果,消費(fèi)一個(gè)數(shù)據(jù)的時(shí)候,首先做一個(gè)操作,然后再做一個(gè)操作,實(shí)現(xiàn)組合,而這個(gè)方法就是Consumer接口中的default方法

andThen方法

    /**
    * Returns a composed {@code Consumer} that performs, in sequence, this
    * operation followed by the {@code after} operation. If performing either
    * operation throws an exception, it is relayed to the caller of the
    * composed operation.  If performing this operation throws an exception,
    * the {@code after} operation will not be performed.
    *
    * @param after the operation to perform after this operation
    * @return a composed {@code Consumer} that performs in sequence this
    * operation followed by the {@code after} operation
    * @throws NullPointerException if {@code after} is null
    */
   default Consumer<T> andThen(Consumer<? super T> after) {
       Objects.requireNonNull(after);
       return (T t) -> { accept(t); after.accept(t); };
   }

測(cè)試:

/**
 * @Author Administrator
 * @Date 2023/6/25 22:08
 * @description
 * @Version 1.0
 */
public class ConsumerAndThenTest {
    public static void main(String[] args) {
        Test2(msg1->{
            //轉(zhuǎn)大寫
            System.out.println(msg1.toUpperCase());
        },msg2->{
            //轉(zhuǎn)小寫
            System.out.println(msg2.toLowerCase());
        });
    }
    public static void Test2(Consumer<String> t1,Consumer<String> t2){
        String str = "Out of control";
        t2.andThen(t1).accept(str);
    }
}

結(jié)果:

out of control
OUT OF CONTROL

分析,觀察到與我們?cè)谡{(diào)用的時(shí)候?qū)懙捻樞虿灰粯樱瑸槭裁茨兀?/strong>
原理:

我們?cè)?span id="n5n3t3z"    class="token class-name">Test2方法里使用的是t2.andThen(t1),也就是在t2作為參數(shù)傳遞執(zhí)行對(duì)應(yīng)的方法之后執(zhí)行t1,andThen的意思就是什么之后做這件事情。
4.2.3 Function

有參有返回值的接口,F(xiàn)unction接口是根據(jù)一個(gè)類型的數(shù)據(jù)得到另一個(gè)類型的數(shù)據(jù),前者稱為前置條件,后者稱為后置條件。有參數(shù)有返回值。

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);


使用:輸入一個(gè)字符串,返回一個(gè)整數(shù)。


/**
 * @Author Administrator
 * @Date 2023/6/25 22:35
 * @description
 * @Version 1.0
 */
public class FunctionTest {
    public static void main(String[] args) {
        Test04((arg)->{
            Integer res = Integer.valueOf(arg);
            return res;
        });
    }
    public static void Test04(Function<String,Integer> function){
        int gif = function.apply("18");
        System.out.println(gif);
    }
}

結(jié)果:

18

默認(rèn)方法:andThen,也是用來(lái)進(jìn)行組合操作。

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     *
     * @see #compose(Function)
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

使用:

/**
 * @Author Administrator
 * @Date 2023/6/25 22:49
 * @description
 * @Version 1.0
 */
public class FunctionAndThenTest {
    public static void main(String[] args) {
        fun(arg1->{
            return Integer.valueOf(arg1);
        },arg2->{
            return arg2*10;
        });
    }
    public static void fun(Function<String,Integer> t1,Function<Integer,Integer> t2){
        int res = t1.andThen(t2).apply("18");
        System.out.println(res);
    }
}

注意,由于t1——》t2具有傳遞性,所有t2的 泛型要跟t1轉(zhuǎn)換后的泛型對(duì)應(yīng)

默認(rèn)的compose方法的作用順序和andThen方法剛好相反
而靜態(tài)方法identity則是,輸入什么參數(shù)就返回什么參數(shù)

4.2.4 Predicate

有參且返回值為Boolean的接口

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

使用:

/**
 * @Author Administrator
 * @Date 2023/6/25 23:00
 * @description
 * @Version 1.0
 */
public class PredicateTest {
    public static void main(String[] args) {
        fun((arg)->{
            boolean res = arg.equals("不需要嗎?");
            return res;
        });
    }
    public static void fun(Predicate<String> msg){
        boolean res = msg.test("愛(ài)一個(gè)人需要理由嗎?");
        System.out.println(res);
    }
}

其他擴(kuò)展方法:

    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * OR of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code true}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ORed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * OR of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * Returns a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}.
     *
     * @param <T> the type of arguments to the predicate
     * @param targetRef the object reference with which to compare for equality,
     *               which may be {@code null}
     * @return a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

在Predicate中的默認(rèn)方法提供了邏輯關(guān)系操作 and or negate isEquals方法:
使用:

/**
 * @Author Administrator
 * @Date 2023/6/25 23:09
 * @description
 * @Version 1.0
 */
public class PredicateDemoTest {
    public static void main(String[] args) {
        fun(arg1->{
            return arg1.contains("愛(ài)");
        },arg2->{
            return arg2.contains("pf");
        });
    }
    public static void fun(Predicate<String> arg1,Predicate<String> arg2){
        boolean And = arg1.and(arg2).test("不說(shuō)一句的愛(ài)有多好");
        boolean Or = arg1.or(arg2).test("不說(shuō)一句的愛(ài)有多好");
        boolean Negate = arg1.negate().test("不說(shuō)一句的愛(ài)有多好");
        System.out.println(And);
        System.out.println(Or);
        System.out.println(Negate);
    }
}

結(jié)果:

false
true
false

結(jié)語(yǔ)

寫到這里總字?jǐn)?shù)也有兩萬(wàn)+了,然后覺(jué)得文章太長(zhǎng),看的人恐怕不多,一般就看看就劃走了,故而分為上下兩部,上部就先到函數(shù)式接口。歸根結(jié)底,只有練習(xí)才能真正理解用法和體會(huì)這種思維,加油。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-500702.html

到了這里,關(guān)于JDK8新特性-上部的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • JDK8新特性(一)集合之 Stream 流式操作

    JDK8新特性(一)集合之 Stream 流式操作

    ?????? 首先我們應(yīng)該知道:Stream流的出現(xiàn),主要是用在集合的操作上。在我們?nèi)粘5墓ぷ髦?,?jīng)常需要對(duì)集合中的元素進(jìn)行相關(guān)操作。諸如:增加、刪除、獲取元素、遍歷。 ??????? 最典型的就是集合遍歷了。接下來(lái)我們先舉個(gè)例子來(lái)看看 JDK8 Stream流式操作出現(xiàn)之前,

    2024年01月23日
    瀏覽(22)
  • JDK8、JDK11、JDK17和JDK21這幾個(gè)版本更新的主要特性

    JDK8、JDK11、JDK17和JDK21這幾個(gè)版本更新的主要特性

    JDK8 是 Java 的一個(gè)重大更新版本,引入了一系列新特性和改進(jìn),主要包括: Lambda 表達(dá)式: Lambda 表達(dá)式允許我們以簡(jiǎn)潔、函數(shù)式的方式編寫代碼,使代碼更易于理解和維護(hù)。- Stream API : Stream API 提供了一套聲明式處理數(shù)據(jù)的方式,使得對(duì)集合和數(shù)組的操作更加直觀和高效。

    2024年04月29日
    瀏覽(23)
  • JDK8 新特性 Stream API 進(jìn)階 (結(jié)合案例詳解--通透--講清)

    JDK8 新特性 Stream API 進(jìn)階 (結(jié)合案例詳解--通透--講清)

    ??我親愛(ài)的各位大佬們好?????? ?? 本篇文章記錄的為 JDK8 新特性 Stream API 進(jìn)階 相關(guān)內(nèi)容,適合在學(xué)Java的小白,幫助新手快速上手,也適合復(fù)習(xí)中,面試中的大佬??????。 ?? 如果文章有什么需要改進(jìn)的地方還請(qǐng)大佬不吝賜教?????? ????? 個(gè)人主頁(yè) : 阿千弟 ??

    2024年02月06日
    瀏覽(20)
  • Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

    Java語(yǔ)法理論和面經(jīng)雜疑篇《十一. JDK8新特性》

    目錄 1. Java版本迭代概述 1.1 發(fā)布特點(diǎn)(小步快跑,快速迭代) 1.2 名詞解釋 1.3 各版本支持時(shí)間路線圖 1.4 各版本介紹 1.5 JDK各版本下載鏈接 1.6 如何學(xué)習(xí)新特性 2. Java8新特性:Lambda表達(dá)式 2.1 關(guān)于Java8新特性簡(jiǎn)介 2.2 冗余的匿名內(nèi)部類 2.3 好用的lambda表達(dá)式 2.4 Lambda 及其使用舉例

    2023年04月22日
    瀏覽(13)
  • Java—JDK8新特性—Lambda表達(dá)式【內(nèi)含思維導(dǎo)圖】

    Java—JDK8新特性—Lambda表達(dá)式【內(nèi)含思維導(dǎo)圖】

    目錄 JDK8新特性 2.Lambda表達(dá)式 思維導(dǎo)圖 2.1?什么是Lambda表達(dá)式 2.2 為什么使用Lamdba表達(dá)式 2.3 Lambda表達(dá)式基本語(yǔ)法 2.4 類型推斷 2.5 Lambda練習(xí) 2.6 Lambda常用場(chǎng)景 ????????官網(wǎng)提供網(wǎng)址:JDK 8 Features ????????Lamdba是一個(gè) 匿名函數(shù) ,可以把Lamdba表達(dá)式理解為是一段可以傳遞的

    2024年02月03日
    瀏覽(27)
  • JDK8中的新特性(Lambda、函數(shù)式接口、方法引用、Stream)

    JDK8中的新特性(Lambda、函數(shù)式接口、方法引用、Stream)

    1.1 關(guān)于Java8新特性簡(jiǎn)介 Java 8 (又稱為 JDK 8或JDK1.8) 是 Java 語(yǔ)言開發(fā)的一個(gè)主要版本。 Java 8 是oracle公司于2014年3月發(fā)布,可以看成是自Java 5 以來(lái) 最具革命性 的版本。Java 8為Java語(yǔ)言、編譯器、類庫(kù)、開發(fā)工具與JVM帶來(lái)了大量新特性。 特性: 速度更快 代碼更少(增加了新的語(yǔ)法

    2024年02月05日
    瀏覽(28)
  • JDK8-JDK17中的新特性(var類型推斷、模式匹配、Record、密封類)

    JDK8-JDK17中的新特性(var類型推斷、模式匹配、Record、密封類)

    新的語(yǔ)法結(jié)構(gòu),勾勒出了 Java 語(yǔ)法進(jìn)化的一個(gè)趨勢(shì),將開發(fā)者從 復(fù)雜、繁瑣 的低層次抽象中逐漸解放出來(lái),以更高層次、更優(yōu)雅的抽象,既 降低代碼量 ,又避免意外編程錯(cuò)誤的出現(xiàn),進(jìn)而提高代碼質(zhì)量和開發(fā)效率。 1.1 Java的REPL工具: jShell命令 JDK9的新特性 Java 終于擁有了

    2024年02月06日
    瀏覽(26)
  • 【從零開始學(xué)Java第64期】JDK8 關(guān)于日期時(shí)間的新特性

    【從零開始學(xué)Java第64期】JDK8 關(guān)于日期時(shí)間的新特性

    本系列為:從零開始學(xué)Java,為千鋒教育資深Java教學(xué)老師獨(dú)家創(chuàng)作 致力于為大家講解清晰Java相關(guān)知識(shí)點(diǎn),含有豐富的代碼案例及講解。如果感覺(jué)對(duì)大家有幫助的話,可以【點(diǎn)個(gè)關(guān)注】持續(xù)追更~ 有技術(shù)類問(wèn)題,也歡迎大家和我們交流討論! 在上一篇文章中本系列內(nèi)容給大家講

    2024年02月07日
    瀏覽(22)
  • JDK8 升級(jí)至JDK19

    JDK8 升級(jí)至JDK19

    優(yōu)質(zhì)博文IT-BLOG-CN 目前部分項(xiàng)目使用 JDK8 ,部分項(xiàng)目使用 JDK19 因此,環(huán)境變量中還是保持 JDK8 ,只需要下載 JDK19 免安裝版本,通過(guò)配置 IDEA 就可以完成本地開發(fā)。 【1】通過(guò)快捷鍵 CTRL + SHIFT + ALT + S 或者 File-Project Structure... 設(shè)置 SDK 和 Language level ,不存在 JDK19 時(shí)可通過(guò) Edit

    2024年02月19日
    瀏覽(16)
  • Mac卸載jdk8,安裝jdk17

    Mac卸載jdk8,安裝jdk17

    本次操作基于MacBook 因?yàn)楣ぷ餍枰?,需要將jdk版本由jdk8升級(jí)到j(luò)dk17,同一臺(tái)機(jī)器上是可以同時(shí)安裝多個(gè)版本的jdk的,但是為了避免一些沖突和未知問(wèn)題,這里直接卸載舊版本jdk,然后再重新安裝新版本。 先查看本機(jī)安裝的jdk: 刪除java運(yùn)行環(huán)境: 到j(luò)ava的目錄,用ls命令查看機(jī)

    2024年02月08日
    瀏覽(27)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包