java - 在所有方法调用上允许类型见证有什么意义?

标签 java generics

假设我们有如下两种方法:

public static <T> T genericReturn() { /*...*/ }
public static String stringReturn() { /*...*/ }

在调用任何方法时,无论是否有任何要求,都可以提供类型见证:

String s;
s = Internet.<String>genericReturn(); //Type witness used in return type, returns String
s = Internet.<Integer>stringReturn(); //Type witness ignored, returns String

但是,我在 Java 中根本没有看到任何实际用途,除非无法推断类型(这通常表明存在更大的问题)。此外,当使用不当时,它会被简单地忽略,这一事实似乎违反直觉。那么在 Java 中使用这个有什么意义呢?

最佳答案

来自 JLS §15.2.12.1 :

  • If the method invocation includes explicit type arguments, and the member is a generic method, then the number of type arguments is equal to the number of type parameters of the method.

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 1.4 中,JDK 有一个类

public class Foo
{
    /** check obj, and return it */
    public Object check(Object obj){ ... }
}

一些用户编写了一个扩展 Foo 的专有类并覆盖 check方法

public class MyFoo extends Foo
{
    public Object check(Object obj){ ... }
}

当 Java 1.5 引入泛型时,Foo.check被泛化为

    public <T> T check(T obj)

雄心勃勃的向后可比性目标要求 MyFoo仍然可以在 Java 1.5 中编译而无需修改;和 MyFoo.check[Object->Object]仍然是 Foo.check[T->T] 的覆盖方法.

现在,根据上述理由,因为这样编译:

    MyFoo myFoo = new MyFoo();

    ((Foo)myFoo).<String>check("");

这也必须编译:

    myFoo.<String>check("");

即使 MyFoo.check不是通用的。


这听起来有点牵强。但即使我们相信这个论点,解决方案仍然过于广泛和过度。 JLS 可以收紧它,以便 myFoo.<String,String>checkobj.<Blah>toString()是非法的,因为类型参数数量不匹配。他们可能没有时间解决它,所以他们只是采取了一条简单的路线。

关于java - 在所有方法调用上允许类型见证有什么意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28014853/

相关文章:

java - hibernate 保存实体

java - 数据库中多个表的审计历史

ios - 依赖项注入(inject)通用结构,而无需重新指定占位符类型或约束

c# - 这些方法线程安全吗?

java - 通用集合

Java泛型理解Type

java - 使用 java 将索引列添加到 apache Spark Dataset<Row>

java - 助手 : marven libraries can't be downloaded

java - 在类中使用共享服务

java - 你如何在 java 中处理 "super"泛型?