- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
好的,所以方法重载是一件坏事™。现在这个问题已经解决了,让我们假设我实际上想要重载这样的方法:
static void run(Consumer<Integer> consumer) {
System.out.println("consumer");
}
static void run(Function<Integer, Integer> function) {
System.out.println("function");
}
在 Java 7 中,我可以使用明确的匿名类作为参数轻松调用它们:
run(new Consumer<Integer>() {
public void accept(Integer integer) {}
});
run(new Function<Integer, Integer>() {
public Integer apply(Integer o) { return 1; }
});
现在在 Java 8 中,我当然想用 lambda 表达式调用这些方法,而且我可以!
// Consumer
run((Integer i) -> {});
// Function
run((Integer i) -> 1);
既然编译器应该能够推断Integer
,那么为什么我不离开Integer
呢?
// Consumer
run(i -> {});
// Function
run(i -> 1);
但这不能编译。编译器(javac、jdk1.8.0_05)不喜欢这样:
Test.java:63: error: reference to run is ambiguous
run(i -> {});
^
both method run(Consumer<Integer>) in Test and
method run(Function<Integer,Integer>) in Test match
对我来说,直觉上,这没有意义。产生返回值(“值兼容”)的 lambda 表达式与产生 void(“void 兼容”)的 lambda 表达式之间绝对没有歧义,如 JLS §15.27 中所述。
但是,当然,JLS 是深刻而复杂的,我们继承了 20 年的向后兼容性历史,并且还有一些新的东西,例如:
Certain argument expressions that contain implicitly typed lambda expressions (§15.27.1) or inexact method references (§15.13.1) are ignored by the applicability tests, because their meaning cannot be determined until a target type is selected.
上述限制可能与 JEP 101 没有完全实现有关,如 here 和 here 所示。
谁能准确地告诉我 JLS 的哪些部分指定了这种编译时歧义(或者是编译器错误)?
奖励:为什么事情会这样决定?
使用jdk1.8.0_40,上面的编译和工作正常
最佳答案
我想你找到了this bug in the compiler: JDK-8029718 (or this similar one in Eclipse: 434642)。
与JLS §15.12.2.1. Identify Potentially Applicable Methods相比:
…
A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:
The arity of the target type's function type is the same as the arity of the lambda expression.
If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
请注意“void
兼容 block ”和“值兼容 block ”之间的明显区别。虽然在某些情况下 block 可能两者兼而有之,但 §15.27.2. Lambda Body 部分明确指出像 () -> {}
这样的表达式是“void
兼容 block ”,因为它正常完成而不返回值。显然,i -> {}
也是一个“void
兼容 block ”。
根据上面引用的部分,lambda 与值不兼容的 block 以及具有(非void
)返回类型的目标类型的组合不是潜在的候选者方法重载决策。所以你的直觉是对的,这里不应该有任何歧义。
不明确 block 的示例是
() -> { throw new RuntimeException(); }
() -> { while (true); }
因为它们没有正常完成,但您的问题并非如此。
关于java - Lambda表达式和方法重载疑惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26091682/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!