【发布时间】:2015-08-28 00:46:36
【问题描述】:
Java 8 的 Java 语言规范在“示例 4.11-1. 类型的用法”中提供了一个带有类型参数的方法调用示例:
<S> void loop(S s) {
this.<S>loop(s); // <S> is the the type argument for the method call.
}
在该示例中,提供的类型参数是有意义的,但显然方法调用的类型参数也可能是多余的并且完全没有意义,甚至不需要涉及泛型。例如:
void m() { }
void test() {
m();
this.m();
this.<Integer>m(); // Compiles and runs OK!
this.<String, Byte, StringBuilder, Thread[], Throwable>m(); // Compiles and runs OK!
<Integer>m(); // Won't compile: "illegal start of expression"
}
我有几个问题:
谁能建议 Java 允许这些冗余类型参数的正当理由?接受它们没有害处,在我看来它仍然是编译器可以并且应该捕获的东西。
仅当使用类型参数的方法调用以“this.”为前缀时,该代码才会编译。否则你会得到“非法的表达式开始”错误。那是一个错误吗?不应该有任何与“this”一起使用的明确方法调用。没有“this”也可以工作。
(这些问题的催化剂是 Oracle's response 我为一个有趣的 Java 问题创建的错误报告,有人在 SO 上提出了 here。)
2015 年 9 月 18 日更新
- 我针对这个问题向 Oracle 提出了 bug JDK-8098556。以下是他们的回应:
这不是问题;使用与普通方法相同的规则检查方法引用 - 请注意,对于普通方法,您始终可以提供冗余类型参数:
void m() { }
this.<String>m(); //legal
方法(和构造函数)引用仅继承此行为,根据 15.13: ""如果方法引用表达式的格式为 ReferenceType :: [TypeArguments] Identifier,则可能适用的方法是要搜索的类型的成员方法,它们具有适当的名称(由 Identifier 给出)、可访问性、arity(n 或 n- 1) 和类型参数 arity(派生自 [TypeArguments]),如 §15.12.2.1 中所述。”
- 由于该回复确认了 TAsk 已在下面提供的信息(包括引用 JLS 的相关部分),因此我接受了该回复。
【问题讨论】:
-
不知道为什么它是允许的,但在 Eclipse 中你会得到一个警告“未使用类型参数的非泛型方法 m() 类型的测试;它不应该用参数
参数化”,这意味着不要这样做。 --- this.<Integer>m()在语法上 是有效的,并且在输入m时有意义,但<Integer>m()是完全无效的语法。 -
第二个问题一定是因为一些解析/语法困难。例如,
x<<Integer>m() -
@bayou.io 您的链接非常相关。 Gábor Bakos 给出的关于为什么允许“无效”使用类型参数的答案有些说服力,尽管它解决了一种非常罕见的情况。
-
@skomisa - 我认为 Bakos 的回答完全没有根据。从未有过与非泛化进行可比性的目标。