方法引用

Chengkai730發表於2024-09-28

方法引用

方法: 就是以前學過的方法.

引用: 就是把已有的方法拿過來用.

如何用: 當做函式式介面抽象方法的方法體.

總結: 方法引用就是把已經有的方法拿過來用, 當做函式式介面中抽象方法的方法體.

方法引用的條件:

  1. 引用處必須是函式式介面.

  2. 被引用的方法必須是已經存在的.

  3. 被引用方法的形參和返回值必須和抽象方法保持一致.

  4. 被引用的方法的功能要能滿足當前的要求.

:: 是方法引用符.

示例:

引用靜態方法

格式: 類名::靜態方法

範例: Integer::parseInt

程式示例:

import java.util.ArrayList;
import java.util.Collections;

public class FunctionDemo2 {
    public static void main(String[] args) {
       /*
        方法引用(引用靜態方法)
        格式
              類::方法名

        需求:
            集合中有以下數字,要求把他們都變成int型別
            "1","2","3","4","5"
       */

        // 1.建立集合並新增元素
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "1", "2", "3", "4", "5");

        // 2.把他們都變成int型別
       /* list.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                int i = Integer.parseInt(s);
                return i;
            }
        }).forEach(s -> System.out.println(s));*/

        // 1.方法需要已經存在
        // 2.方法的形參和返回值需要跟抽象方法的形參和返回值保持一致
        // 3.方法的功能需要把形參的字串轉換成整數

        list.stream()
                .map(Integer::parseInt)
                .forEach(s -> System.out.println(s));
    }
}

引用成員方法

格式: 物件::成員方法

其他類: 其他類物件::方法名

本類: this::方法名

父類: super::方法名

程式示例:

import java.util.ArrayList;
import java.util.Collections;

public class FunctionDemo3 {
    public static void main(String[] args) {
        /*
        方法引用(引用成員方法)
        格式
                其他類:其他類物件::方法名
                本類:this::方法名(引用處不能是靜態方法)
                父類:super::方法名(引用處不能是靜態方法)
        需求:
            集合中有一些名字,按照要求過濾資料
            資料:"張無忌","周芷若","趙敏","張強","張三丰"
            要求:只要以張開頭,而且名字是3個字的
       */

        // 1.建立集合
        ArrayList<String> list = new ArrayList<>();
        // 2.新增資料
        Collections.addAll(list, "張無忌", "周芷若", "趙敏", "張強", "張三丰");
        // 3.過濾資料(只要以張開頭,而且名字是3個字的)
        // list.stream().filter(s->s.startsWith("張")).filter(s->s.length() == 3).forEach(s-> System.out.println(s));

      /*  list.stream().filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("張") && s.length() == 3;
            }
        }).forEach(s-> System.out.println(s));*/

      /*  StringOperation so = new StringOperation();
        list.stream().filter(so::stringJudge)
                .forEach(s-> System.out.println(s));*/

        // 靜態方法中是沒有this的
        list.stream().filter(new FunctionDemo3()::stringJudge)
                .forEach(s -> System.out.println(s));
    }

    public boolean stringJudge(String s) {
        return s.startsWith("張") && s.length() == 3;
    }
}
public class StringOperation {
    public boolean stringJudge(String s){
        return s.startsWith("張") && s.length() == 3;
    }
}

程式示例:

public class App {
    public static void main(String[] args) {
        new LoginJFrame();
    }
}
import javax.swing.*;
import java.awt.*;

public class LoginJFrame extends MyJFrame {

    JButton go = new JButton("Go");

    public LoginJFrame() {
        // 設定圖示
        setIconImage(Toolkit.getDefaultToolkit().getImage("myfunction\\image\\logo.jpg"));

        // 設定介面
        initJframe();

        // 新增元件
        initView();

        // 介面顯示出來
        this.setVisible(true);
    }

    // 新增元件
    public void initView() {
        JLabel image = new JLabel(new ImageIcon("myfunction\\image\\kit.jpg"));
        image.setBounds(100, 50, 174, 174);
        this.getContentPane().add(image);

        go.setFont(new Font(null, 1, 20));
        go.setBounds(120, 274, 150, 50);
        go.setBackground(Color.WHITE);

        go.addActionListener(super::method1);

        this.getContentPane().add(go);
    }

    // 設定介面
    public void initJframe() {
        // 設定標題
        this.setTitle("隨機點名器");
        // 設定大小
        this.setSize(400, 500);
        // 設定關閉模式
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // 設定視窗無法進行調節
        this.setResizable(false);
        // 介面居中
        this.setLocationRelativeTo(null);
        // 取消內部預設居中放置
        this.setLayout(null);
        // 設定背景顏色
        this.getContentPane().setBackground(Color.white);
        this.setAlwaysOnTop(true);  // 置頂
    }
}
import javax.swing.*;
import java.awt.event.ActionEvent;

public class MyJFrame extends JFrame {
    public void method1(ActionEvent e) {
        System.out.println("go按鈕被點選了");
    }
}

引用構造方法

格式: 類名::new
範例: Student::new

程式示例:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

public class FunctionDemo4 {
    public static void main(String[] args) {
        /*
        方法引用(引用構造方法)
        格式
                類名::new

        目的:
                建立這個類的物件

        需求:
             集合裡面儲存姓名和年齡,要求封裝成Student物件並收集到List集合中

        方法引用的規則:
            1.需要有函式式介面
            2.被引用的方法必須已經存在
            3.被引用方法的形參和返回值,需要跟抽象方法的形參返回值保持一致
            4.被引用方法的功能需要滿足當前的需求
       */

        // 1.建立集合物件
        ArrayList<String> list = new ArrayList<>();
        // 2.新增資料
        Collections.addAll(list, "張無忌,15", "周芷若,14", "趙敏,13", "張強,20", "張三丰,100", "張翠山,40", "張良,35", "王二麻子,37", "謝廣坤,41");
        // 3.封裝成Student物件並收集到List集合中
        // String --> Student
      /*  List<Student> newList = list.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                String[] arr = s.split(",");
                String name = arr[0];
                int age = Integer.parseInt(arr[1]);
                return new Student(name, age);
            }
        }).collect(Collectors.toList());
        System.out.println(newList);*/

        List<Student> newList2 = list.stream().map(Student::new).collect(Collectors.toList());
        System.out.println(newList2);
    }
}
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String str) {
        String[] arr = str.split(",");
        this.name = arr[0];
        this.age = Integer.parseInt(arr[1]);
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    /**
     * 獲取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 設定
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 獲取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 設定
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + "}";
    }
}

使用類名引用成員方法

格式: 類名::成員方法

範例: String::substring

程式示例:

import java.util.ArrayList;
import java.util.Collections;

public class FunctionDemo5 {
    public static void main(String[] args) {
        /*
        方法引用(類名引用成員方法)
        格式
                類名::成員方法
        需求:
             集合裡面一些字串,要求變成大寫後進行輸出

        方法引用的規則:
        1.需要有函式式介面
        2.被引用的方法必須已經存在
        3.被引用方法的形參,需要跟抽象方法的第二個形參到最後一個形參保持一致,返回值需要保持一致。
        4.被引用方法的功能需要滿足當前的需求

        抽象方法形參的詳解:
        第一個引數:表示被引用方法的呼叫者,決定了可以引用哪些類中的方法
                    在Stream流當中,第一個引數一般都表示流裡面的每一個資料。
                    假設流裡面的資料是字串,那麼使用這種方式進行方法引用,只能引用String這個類中的方法

        第二個引數到最後一個引數:跟被引用方法的形參保持一致,如果沒有第二個引數,說明被引用的方法需要是無參的成員方法

        侷限性:
            不能引用所有類中的成員方法。
            是跟抽象方法的第一個引數有關,這個引數是什麼型別的,那麼就只能引用這個類中的方法。

       */

        // 1.建立集合物件
        ArrayList<String> list = new ArrayList<>();
        // 2.新增資料
        Collections.addAll(list, "aaa", "bbb", "ccc", "ddd");
        // 3.變成大寫後進行輸出
        // map(String::toUpperCase)
        // 拿著流裡面的每一個資料,去呼叫String類中的toUpperCase方法,方法的返回值就是轉換之後的結果。
        list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));
        
        // String --> String
       /* list.stream().map(new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s.toUpperCase();
            }
        }).forEach(s -> System.out.println(s));*/
    }
}

引用陣列的構造方法

格式: 資料型別[]:new

範例: int[]::new

程式示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;

public class FunctionDemo6 {
    public static void main(String[] args) {
        /*
        方法引用(陣列的構造方法)
        格式
                資料型別[]::new
        目的:
                建立一個指定型別的陣列
        需求:
             集合中儲存一些整數,收集到陣列當中

        細節:
            陣列的型別,需要跟流中資料的型別保持一致。

       */

        //1.建立集合並新增元素
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5);
        //2.收集到陣列當中

        Integer[] arr2 = list.stream().toArray(Integer[]::new);
        System.out.println(Arrays.toString(arr2));

        /*Integer[] arr = list.stream().toArray(new IntFunction<Integer[]>() {
            @Override
            public Integer[] apply(int value) {
                return new Integer[value];
            }
        });*/
        //3.列印
    }
}

相關文章