Java 为什么必须为方法引用显式指定类/对象名称?
当我想引用当前范围内的方法时,我仍然需要 在Java 为什么必须为方法引用显式指定类/对象名称?,java,java-8,method-reference,Java,Java 8,Method Reference,当我想引用当前范围内的方法时,我仍然需要 在之前指定类名(用于静态方法)或此: 操作人员例如,我需要写: import java.util.stream.Stream; public class StreamTest { public static int trimmedLength(String s) { return s.trim().length(); } public static void main(String[] args) {
之前指定类名(用于静态方法)或此
:
操作人员例如,我需要写:
import java.util.stream.Stream;
public class StreamTest {
public static int trimmedLength(String s) {
return s.trim().length();
}
public static void main(String[] args) {
System.out.println(Stream.of(" aaa ", " bb ", " c ")
.mapToInt(StreamTest::trimmedLength).sum());
}
}
对于这个
,这并不是什么大问题,但有时静态方法看起来过于拥挤,因为类名可能相当长。若编译器允许我只编写::trimmedLength
,那个就太好了:
public static void main(String[] args) {
System.out.println(Stream.of(" aaa ", " bb ", " c ")
.mapToInt(::trimmedLength).sum());
}
但是Java-8编译器不允许这样做。对我来说,如果类/对象名的解析方式与普通方法调用的解析方式相同,那么它似乎是相当一致的。这还将支持方法引用的静态导入,在某些情况下也很有用
所以问题是为什么在Java8中没有实现这样或类似的语法?这样的语法有什么问题吗?或者根本就没有考虑过它?我不能代表Java开发人员发言,但有一些事情需要考虑: 有若干:
ContainingClass::staticMethodName
containingObject::instanceMethodName
ContainingType::methodName
ClassName::new
::methodName
,编译器必须在三种不同的表单之间消除歧义,因为它可以是从1到3的三种表单中的任何一种
这就是说,允许表单::methodName
缩短表单1到3中的任何一个,仍然不意味着它等同于表达式simpleName(argopt)
所指的表单methodName(…)
- 当前类或其超类和接口范围内的实例方法
- 当前类或其超类范围内的
静态方法
- 外部类或其超类和接口范围内的实例方法
- 外部类或其超类范围内的
静态方法
- 通过
声明的import static
方法static
::name
这样的说法应该被允许引用任何方法name(…)
may-refered”意味着要结合这两个列表的可能性,在许下愿望之前,你应该三思而后行
最后一点,您仍然可以选择编写lambda表达式,如
args->name(args)
,这意味着解决name
,就像一个简单的方法调用name(args)
,同时解决歧义问题,因为它消除了方法引用类型的选项3,除非您明确地编写(arg1,otherargs)->arg1.name(otherargs)
,否则您是否查看了JCP中关于此语法的讨论?我打赌你可以找到很多关于这个和其他的想法。不,我没有。如果你能指出关于我的问题的确切信息/观点,那就太好了。谢谢你的详细回答。我希望Java开发人员会回答,但我的问题对他们来说可能不是很有趣。@Holger在使用方法引用3个月后,我也倾向于用Tagir的方式思考。很难理解,仅仅因为编译器需要执行更多的任务,就忽略了方法引用的预期形式。相反,编译器可以尽力解决这个问题。如果不能解决,它总是可以要求用完整的形式消除歧义。@Mrinal K.Samanta:不仅编译器必须这样做。人类读者也必须这样做。对方法目标的错误理解会造成比少打几个字母所能弥补的伤害更大的伤害