gpt4 book ai didi

java - 为什么在这种情况下,单参数实例方法对 BiConsumer 的类型推断不同?

转载 作者:搜寻专家 更新时间:2023-11-01 03:00:18 41 4
gpt4 key购买 nike

我正在尝试编译这段代码:

import java.util.Collection;
import java.util.function.BiConsumer;
import de.hybris.platform.servicelayer.exceptions.ModelSavingException;
import de.hybris.platform.servicelayer.model.ModelService;

public class Foo {

public static interface ModelService2 {
public abstract void saveAll(Object[] paramArrayOfObject) throws ModelSavingException;
public abstract void saveAll(Collection<? extends Object> paramCollection) throws ModelSavingException;
public abstract void saveAll() throws ModelSavingException;
}

public void bar() {
final BiConsumer<ModelService2, Collection<? extends Object>> consumer1 = ModelService2::saveAll;
final BiConsumer<ModelService, Collection<? extends Object>> consumer2 = ModelService::saveAll;
}
}

界面ModelService由 SAP hybris 平台定义。 ModelService2 只是复制了在 hybris 平台的接口(interface)中定义的名称为 saveAll 的重载方法。

编译上面的代码时出现以下编译器错误:

1. ERROR in src\Foo.java (at line 17)
final BiConsumer<ModelService, Collection<? extends Object>> consumer2 = ModelService::saveAll;
^^^^^^^^^^^^^^^^^^^^^
Cannot make a static reference to the non-static method saveAll(Object[]) from the type ModelService

当我能够发现的唯一区别是每个接口(interface)所在的位置时,为什么编译器会对 ModelService 进行不同的类型推断?

在这种情况下,我使用 javac 1.8.0_77 进行编译。例如,Eclipse 不会报告上述代码的任何错误。

编辑:

相对类似的错误也发生在以下变量声明中:

final Consumer<ModelService2> consumer3 = ModelService2::saveAll;
final Consumer<ModelService> consumer4 = ModelService::saveAll;

这种情况下的编译错误是:

1. ERROR in src\Foo.java (at line 19)
final Consumer<ModelService> consumer4 = ModelService::saveAll;
^^^^^^^^^^^^^^^^^^^^^
Cannot make a static reference to the non-static method saveAll(Object[]) from the type ModelService

编辑2:

编译参数是:

'-noExit'
'-classpath'
'<classpath>'
'-sourcepath'
'<source path>'
'-d'
'<path>\classes'
'-encoding'
'UTF8'

编辑 3:
这些是 Eclipse 类文件查看器显示的 3 个方法的定义:

  // Method descriptor #43 (Ljava/util/Collection;)V
// Signature: (Ljava/util/Collection<+Ljava/lang/Object;>;)V
public abstract void saveAll(java.util.Collection arg0) throws de.hybris.platform.servicelayer.exceptions.ModelSavingException;

// Method descriptor #45 ([Ljava/lang/Object;)V
public abstract void saveAll(java.lang.Object... arg0) throws de.hybris.platform.servicelayer.exceptions.ModelSavingException;

// Method descriptor #10 ()V
public abstract void saveAll() throws de.hybris.platform.servicelayer.exceptions.ModelSavingException;

解决方案:

问题是由java v4.4.1 的eclipse 编译器引起的。它至少从 v4.5.1 开始是固定的。最初从命令行构建时,我没有注意到hybris平台使用eclipse编译器编译代码。

最佳答案

方法重载、可变参数和类型推断之间的交互可能是 Java 类型检查中最复杂和最棘手的部分。这是一个错误经常出现的领域,不同编译器之间经常存在差异。

我的猜测是:

ModelService有一个可变参数 saveAll .因为这个saveAll带有两个对象参数的方法是对此类对象的有效方法调用。如果该方法是静态的,那么用一个 ModelService 调用它是有效的和一个Collection , 因此方法引用表达式对于 BiConsumer<ModelService2, Collection<? extends Object>> 是有效的类型。

由于编译器错误,编译器注意到该方法不是静态的,因此推断方法引用表达式在这里无效。这会产生编译错误。

ModelService2.saveAll另一方面不是可变参数,不能用 ModelService 调用和一个Collection .因此,编译器在尝试这种可能性时不会陷入此错误。

当我尝试使用 Eclipse 4.5.2 和 javac 1.8.0_77 编写此代码时,您为我编译了所有示例。我不知道为什么你会得到不同的结果。

关于java - 为什么在这种情况下,单参数实例方法对 BiConsumer 的类型推断不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36689305/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com