java - 与 Java 方法调用中的类型参数相关的问题

标签 java java-8

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"
}

我有几个问题:

  1. 谁能提出 Java 允许这些冗余类型参数的正当理由?承认它们没有害处,但在我看来,它仍然像是编译器可以而且应该捕获的东西。

  2. 只有当带有类型参数的方法调用以“this.”为前缀时,该代码才能编译。否则你会得到“表达式的非法开始”错误。那是一个错误吗?不应该有任何与“this”一起工作的明确方法调用。没有“this.”也能工作?

(这些问题的催化剂是我为一个有趣的 Java 问题创建的错误报告 Oracle's response,有人在 SO 上提出了 here。)

2015 年 9 月 18 日更新

  1. 我提出了 bug JDK-8098556对于 Oracle 的这个问题。这是他们的回复:

这不是问题;使用与普通方法相同的规则检查方法引用 - 请注意,对于普通方法,您始终可以提供冗余类型参数:

void m() { }
this.<String>m(); //legal

根据 15.13,方法(和构造函数)引用仅继承此行为: “”如果方法引用表达式的形式为 ReferenceType::[TypeArguments] Identifier,则可能适用的方法是要搜索的类型的成员方法,这些方法具有适当的名称(由标识符给出)、可访问性、元数(n 或 n- 1), 和类型参数元数(派生自 [TypeArguments]),如 §15.12.2.1 中所指定。”

  1. 由于该回复确认了 TAsk 已在下方提供的信息(包括引用 JLS 的相关部分),我已接受该回复。

最佳答案

以下是方法调用的方式:

JLS 15.12 lists following ways for invocation of method,

  • MethodName ( [ArgumentList] ) (Note : This does not have type argument)
  • TypeName.[TypeArguments] Identifier ( [ArgumentList] )
  • ExpressionName.[TypeArguments] Identifier ( [ArgumentList] )
  • Primary.[TypeArguments] Identifier ( [ArgumentList] )
  • super.[TypeArguments] Identifier ( [ArgumentList] )
  • TypeName.super.[TypeArguments] Identifier ( [ArgumentList] )

因此,在 Java 语言规范中,带有表达式或类型名称的方法可以有类型参数,但请注意,在第一个方法调用中,您不能指定类型参数,因为它是非法的。

请注意,只有 this 不允许这样做,但 static 调用和 super 方法调用也可以有类型参数,这些是完全合法的.

static void m() { }

void test() {
   ClassName.<Integer>m();//Also compiles
}

除此之外,您还会收到以下警告,

Unused type arguments for the non generic method m() ...

代表以下JLS 15.12.2.1的语句,

This clause implies that a non-generic method may be potentially applicable to an invocation that supplies explicit type arguments. Indeed, it may turn out to be applicable. In such a case, the type arguments will simply be ignored.

它说的确,它可能结果是适用的(在运行时)

此外,

This rule stems from issues of compatibility and principles of substitutability. Since interfaces or superclasses may be generified independently of their subtypes, we may override a generic method with a non-generic one. However, the overriding (non-generic) method must be applicable to calls to the generic method, including calls that explicitly pass type arguments. Otherwise the subtype would not be substitutable for its generified supertype.

关于java - 与 Java 方法调用中的类型参数相关的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32261650/

相关文章:

java - 如何在 Java Swing 中使用 double 值设置 JTextpane 中文本的字体大小

java - 程序中面临以下错误

java - 如何从 Java 8 流的中间删除一个收集到新流中?

lambda 表达式的 Java 堆转储分析

java - 沿元素将列表拆分为子列表

java - Java中日期到整数的转换

java - Jpanel布局问题,显示两列按钮和标签,怎么办?

java - 使用 Thymeleaf 的动态模板解析器

Java - Mac 应用程序需要安装 JDK 才能运行

java - 如何在 Java 8 中使用子类进行方法链接