Java8 函数式接口、方法引用、构造器引用详解

本文详细介绍了Java8的函数式接口,包括消费型、供给型、函数型和断言型接口,并给出了各自的核心接口示例。接着,探讨了方法引用的概念,作为Lambda表达式的替代形式,列举了不同类型的语法格式。此外,还讨论了构造器引用的使用,强调了参数列表的一致性要求。最后,提到了数组引用的格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Functional接口

  • 函数式接口,有且仅有一个抽象方法,Object的public方法除外。
  • 函数式接口的一大特性就是可以被lambda表达式和函数引用表达式代替。也就是说声明这样的接口,是可以灵活的以方法来传参。
  • 以下是Java8内置四大核心函数式接口:
1) 消费型接口
//Represents an operation that accepts a single input argument and returns no result. 
@FunctionalInterface
public interface Consumer<T> { void accept(T t); }

Consumer简单例子:

public class MethodReferenceTest {
    @Test
    public void testConsumer(){
        age(18, a -> System.out.println("my age is: " + a));
    }
	
    public void age(int x, Consumer consumer){
        consumer.accept(x);
    }
}
2) 供给型接口
//There is no requirement that a new or distinct result be returned each time the supplier is invoked.
@FunctionalInterface 
public interface Supplier<T> { T get(); }

Supplier简单例子:

public class MethodReferenceTest {
    @Test
    public void testSupplier(){
        List<Double> list = supplierMethod(10, ()-> Math.random());
        for (Double i: list){
            System.out.println(i);
        }
    }

    //产生指定个数的整数并放入集合中
    public List<Double> supplierMethod(int num, Supplier<Double> supplier){
        List<Double> list = new ArrayList<>();
        for (int i=0; i<num; i++){
            list.add(supplier.get());
        }
        return list;
    }
}
3) 函数型接口
//Represents a function that accepts one argument and produces a result.
@FunctionalInterface 
public interface Function<T, R> { R apply(T t); }

Function简单例子:

public class MethodReferenceTest {
    //函数型接口测试
    @Test
    public void testFunction(){
        String resStr = strHandler("\t \t Hello Function    ", str->str.trim());
        System.out.println(resStr);
    }

    public String strHandler(String s, Function<String, String> function){
        return function.apply(s);
    }
}
4) 断言型型接口
//Represents a predicate (boolean-valued function) of one argument.
@FunctionalInterface 
public interface Predicate<T> { boolean test(T t); }

Predicate简单例子:

public class MethodReferenceTest {
    //断言型接口测试
    @Test
    public void testPercidate(){
        List<Integer> numList = Arrays.asList(12,130,123,32,45,612,95,100,139);
        List<Integer> l = filterNum(numList,num->num>100);
        for(Integer i : l){
            System.out.println(i);
        }
    }

    public List<Integer> filterNum(List<Integer> numList, Predicate<Integer> predicate){
        List<Integer> resList = new ArrayList<>();
        for (Integer num : numList){
            if(predicate.test(num)){
                resList.add(num);
            }
        }
        return resList;
    }
}

二、方法引用

  • 若Lambda体的内容有方法已经实现了,就可以使用方法引用。可以理解为方法引用是Lambda表达式的另外一种表现形式。
  • Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致。
    例如:public void println(Object x) {} 与void accept(T t); 返回值和参数一致
    主要有三种语法格式:
    对象::实例方法名
public class MethodReferenceTest {

    //对象::实例方法名(非静态方法)
    //public void println(Object x) {} 和void accept(T t); 返回值和参数一致
    @Test
    public void object_method_reference_Test() {
        PrintStream printStream = System.out; //PrintStream 对象
        Consumer cs1 = x -> printStream.println(x); //lambda表达式写法
        cs1.accept("test cs1");

        Consumer cs2 = printStream::println; //当lambda表达式时对象调用实例方法时可用方法引用(对象::实例方法名)
        cs2.accept("test cs2");

        Consumer cs3 = System.out::println; //合并写法
        cs3.accept("test cs3");
    }
}

类::静态方法名

public class MethodReferenceTest {
    @Test
    public void class_referenct_static_method() {
    	//Integer中的compare方法为static的 public static int compare(int x, int y) {
        Comparator<Integer> comparator = (x, y) -> Integer.compare(x, y);
        /**Compares its two arguments for order. Returns a negative integer,zero,
         or a positive integer as the first argument is less than, equal to, or greater than the second.
         **/
        int res = comparator.compare(3, 3);
        System.out.println(res);

        Comparator<Integer> comparator1 = Integer::compare;
        int res1 = comparator1.compare(10, 3);
        System.out.println(res1);
    }
}

类::实例方法名
使用条件:Lambda参数列表中的第一个参数是实例方法的调用者,第二个参数是实例方法的参数时
在这里插入图片描述

public class MethodReferenceTest {
    @Test
    public void class_reference_method(){
        BiPredicate<String, String> biPredicate = (x,y)->x.equals(y);
        System.out.println(biPredicate.test("abc", "abc"));

        BiPredicate<String, String> biPredicate1 = String::equals;
        System.out.println(biPredicate1.test("ert", "ert"));

    }
}

三、构造器引用

  • 格式:ClassName::new
  • 需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!
public class ConstructorReferenceTest {

    @Test
    public void constructor_referent_test(){

        Function<String,Account> supplier = (x)->new Account(x);
        Account account = supplier.apply("vivi");
        System.out.println(account);

        Function<String,Account> supplier1 = Account::new;
        Account account1 = supplier1.apply("Vivi");
        System.out.println(account1);
    }
}

public class Account {
    private String name;
    private double money;

    public Account(String name) {
        this.name = name;
    }
    ...set/get...
}

四、数组引用

  • 格式:Type[]::new
public class ArrayReferenceTest {

    @Test
    public void array_referenct_test(){
        Function<Integer,String[]> function = x->new String[x];
        String[] strings = function.apply(10);
        System.out.println(strings.length);

        Function<Integer, String[]> function1 = String[]::new;
        String[] strings1 = function1.apply(12);
        System.out.println(strings1.length);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值