【问题标题】:How is this method reference valid? [duplicate]此方法参考如何有效? [复制]
【发布时间】:2020-08-22 04:45:15
【问题描述】:
class Dish {
  public int getCalories() {
    return calories;
  }

public static final List<Dish> menu = Arrays.asList(
      new Dish("pork", false, 800, Dish.Type.MEAT),
      new Dish("beef", false, 700, Dish.Type.MEAT),
      new Dish("chicken", false, 400, Dish.Type.MEAT),
      new Dish("french fries", true, 530, Dish.Type.OTHER),
      new Dish("rice", true, 350, Dish.Type.OTHER),
      new Dish("season fruit", true, 120, Dish.Type.OTHER),
      new Dish("pizza", true, 550, Dish.Type.OTHER),
      new Dish("prawns", false, 400, Dish.Type.FISH),
      new Dish("salmon", false, 450, Dish.Type.FISH)
  );
}

summingInt 需要ToIntFunction 时,以下Dish::getCalories 方法引用如何有效?我问是因为getcalories 的签名与applyAsInt 抽象方法ToIntFunction 的签名不匹配

int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

【问题讨论】:

  • 它接受一个 Dish 并返回一个 int。等效的 lambda 为 d -&gt; d.getCalories();
  • 我明白这一点。但是getCalories的签名与ToIntFunctionapplyAsInt抽象方法的签名不匹配
  • @karanmirani 查看方法参考以了解在需要功能接口时它是如何工作的。

标签: java java-8 method-reference


【解决方案1】:

我问是因为getCalories 的签名与ToIntFunctionapplyAsInt 抽象方法的签名不匹配。

实际上,它确实匹配。

ToIntFunction&lt;T&gt; 是一个功能接口,因为它有注解@FunctionalInterface。这意味着applyAsInt 的签名匹配任何提供从&lt;T&gt; 映射到int 的方法的类1、方法引用或lambda。

在这种情况下,Dish::getCalories 通过调用Dish 实例的getCalories() 方法将Dish 映射到int

  • 映射的来源是Dish的实例
  • 映射的结果是在实例上调用getCalories()的结果2

(注:这是一个直观的解释,技术解释请参考JLS的相关部分。)


1 - 在提供类实例的情况下,类 API 中只能有一个方法满足 功能接口 要求。因此,假设,如果 Dish 使用 @ToIntFunction&lt;Dish&gt; 注释声明,则它不能公开两个不带参数并返回 int 的方法。

2 - 适用常规方法覆盖规则。如果实际对象是Dish 的子类型的实例,并且它覆盖了getCalories(),那么映射将调用那个 方法,而不是被覆盖的方法。

【讨论】:

  • > 这意味着签名匹配任何提供从 映射到 int 的(单一)方法的 、方法引用或 lambda。那么如果一个class 有其他方法,即如果Dish 有其他方法,那么方法引用 会无效吗?此外,getCalories 不接受任何参数并返回一个 Dish 实例,而 applyAsInt 接受一个 并返回一个 int
【解决方案2】:

对于任何想知道它为什么有效的人。它之所以有效,是因为this 是对象的每个方法的隐式第一个参数。因此,Dish::getCalories 的签名与ToIntFunctionapplyAsInt 相同。如果我错了,请纠正我。

【讨论】:

    【解决方案3】:

    Emmm,好吧,它在这里工作!我不确定这里是否还有什么隐藏的东西。

    导入 java.util.List; 导入静态 java.util.stream.Collectors.summingInt; 导入 java.util.Arrays; 类菜{ 公共 int getCalories() { 返回卡路里; } 公共静态最终列表菜单 = Arrays.asList( 新菜(“猪肉”,假,800,Dish.Type.MEAT), 新菜(“牛肉”,假,700,Dish.Type.MEAT), 新菜(“鸡”,假,400,Dish.Type.MEAT), new Dish("炸薯条", true, 530, Dish.Type.OTHER), new Dish("rice", true, 350, Dish.Type.OTHER), new Dish("时令水果", true, 120, Dish.Type.OTHER), new Dish("pizza", true, 550, Dish.Type.OTHER), 新菜(“虾”,假,400,Dish.Type.FISH), 新菜(“鲑鱼”,假,450,Dish.Type.FISH) ); 公共静态无效主要(字符串[]参数){ int totalCalories = menu.stream().collect(summingInt(Dish::getCalories)); System.out.println(总卡路里); } 字符串名称; 卡路里; Dish.Type 类型; 公共菜(字符串名称,布尔b,int卡路里,Dish.Type类型){ 极好的(); this.name = 名称; this.calories = 卡路里; this.type = 类型; } 枚举类型 { 肉、鱼、其他 } }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-13
      • 2014-07-17
      • 1970-01-01
      • 2021-08-14
      • 2016-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多