Bad return type in method reference:cannot convert java.util.function.Predicate<XXX> to boolean

6 篇文章 0 订阅

环境

Java:1.8
Inteijj IDEA:2019.2

前言

今天在优化代码时,遇到了如题的错误,一下没有反应过来,磋磨了2、3个小时,才悟了过来。
特意做个笔记。


那晚觉没睡好,因为有些细节没想明白~

代码

// 本质上,这个方法就是封装了lambda表达式
public static Predicate<ProductDTO> excludeByMinorCategoryId() {
   return productDTO -> {
       boolean isConsumable = true;
       String hisCategoryName = productDTO.getCategoryName();
       Integer minorCategoryId = productDTO.getMinorCategoryId();
       if (StringUtils.isNotEmpty(hisCategoryName)) {
           if (minorCategoryId == CONSUMABLE_CATEGORY
                   && hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
               isConsumable = false;
           } else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
                   && !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
               isConsumable = false;
           }
       }
       return isConsumable;
   };
}
// 本质上,这个方法就是封装了lambda表达式
public static Predicate<ProductDTO> excludeByMinorCategoryId2(String hisCategoryName, Integer minorCategoryId) {
    return productDTO -> {
        boolean isConsumable = true;
        if (StringUtils.isNotEmpty(hisCategoryName)) {
            if (minorCategoryId == CONSUMABLE_CATEGORY
                    && hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
                isConsumable = false;
            } else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
                    && !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
                isConsumable = false;
            }
        }
        return isConsumable;
    };
}

// lambda表达式中具体的实现
// 在使用时,得写上完整的lambda表达式或者使用方法引用
public static boolean excludeByMinorCategoryId3(String hisCategoryName, Integer minorCategoryId) {
    boolean isConsumable = true;
    if (StringUtils.isNotEmpty(hisCategoryName)) {
        if (minorCategoryId == CONSUMABLE_CATEGORY
                && hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
            isConsumable = false;
        } else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
                && !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
            isConsumable = false;
        }
    }
    return isConsumable;
}

我的调用方式如下:
在这里插入图片描述

具体使用:

public List<ProductDTO> findExcludeProcess(Integer channelId,
										List<Integer> categories,
										List<Integer> skuIds,
										String keyword) {
    return findProduct(channelId, categories, skuIds).stream()
            .filter(excludeByMinorCategoryId())
            // 错误的写法
            .filter(f -> excludeByMinorCategoryId2(f.getCategoryName(), f.getMinorCategoryId()))
            .filter(ProductRemoteService::excludeByMinorCategoryId3)
            .filter(mixedKeyword(keyword)).collect(Collectors.toList());
}

错误提示如下:
在这里插入图片描述

我一直在纠结,为啥:excludeByMinorCategoryId()调用编译器不报错,
excludeByMinorCategoryId2()方法就报错了。

后来,我又再次翻阅《Java8实战》,才明白:

.filter(excludeByMinorCategoryId())

我这种写法使用的是静态辅助方法 的方式来调用的。

我自己写的excludeByMinorCategoryId()这个方法是个静态方法,会返回Predicate<>对象。

这个我大概总结下,filter()中的参数即:代码行为参数化

① 如下

public class AppleComparator implements Comparator<Apple> {
	public int compare(Apple a1, Apple a2){
    	return a1.getWeight().compareTo(a2.getWeight());
 	}
}
inventory.sort(new AppleComparator());

② 使用匿名类

inventory.sort(new Comparator<Apple>() {
public int compare(Apple a1, Apple a2){
    return a1.getWeight().compareTo(a2.getWeight());
}
});

③ 使用Lambda 表达式

inventory.sort((Apple a1, Apple a2)
-> a1.getWeight().compareTo(a2.getWeight())
);

④ 静态辅助方法

调用静态辅助方法让其返回一个Predicate<T>

.filter(excludeByMinorCategoryId())

⑤ 使用方法引用

如下 excludeByMinorCategoryId3方法
在这里插入图片描述

excludeByMinorCategoryId3 代码如下:

// 返回的Boolean
public static boolean excludeByMinorCategoryId3(ProductDTO productDTO) {
    boolean isConsumable = true;
    String hisCategoryName = productDTO.getCategoryName();
    Integer minorCategoryId = productDTO.getMinorCategoryId();
    if (StringUtils.isNotEmpty(hisCategoryName)) {
            if (minorCategoryId == CONSUMABLE_CATEGORY
                    && hisCategoryName.equals(EXCLUDE_CATEGORY_NAME)) {
                isConsumable = false;
            } else if (minorCategoryId == CONSUMABLE_EYE_CATEGORY
                    && !hisCategoryName.equals(INCLUDE_CATEGORY_NAME)) {
                isConsumable = false;
            }
      }
      return isConsumable;
}

现在回过头来看:

// 写法1
.filter(excludeByMinorCategoryId())
// 写法2 错误写法
.filter(f -> excludeByMinorCategoryId2(
f.getCategoryName(), f.getMinorCategoryId()))

写法2:f -> excludeByMinorCategoryId2(f.getCategoryName(), f.getMinorCategoryId())本身就是lambda表达式的写法,写完整来,就是:

// 错误写法
.filter(f -> {
  return excludeByMinorCategoryId2(
  f.getCategoryName(), f.getMinorCategoryId());
})

也就是其必须返回true或者false


那到底
什么时候使用返回值为truefalse的,
什么时候使用Predicate<T>的呢?

1、返回值为Predicate<T>的,说明该方法封装的就是一个lambda表达式,在filter()方法中使用,就是普通的方法调用(类似直接传代码的方式,写成静态的就是静态辅助方法)。
2、返回值为Boolean的,说明该方法得使用方法引用或者补全完整的lambda表达式才能使用。

总结

行为参数化:

以前:
① 直接传代码
② 匿名类

Java8
③ lambda表达式
④ 静态辅助类
⑤ 方法引用

什么是静态辅助方法

以我的例子来说:

静态方法返回的是:

Predicate<ProductDTO>

即为静态辅助方法

使用时,即为普通的方法调用。

而当返回的是布尔时:

Boolean

即为具体实现。(用lambda来说的话,就是不包括lambda参数,只有实现部分)

使用时可能需要配合lambda表达式来使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值