在所有方法调用中允许类型见证有什么意义? [英] What is the point of allowing type witnesses on all method calls?

查看:23
本文介绍了在所有方法调用中允许类型见证有什么意义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Say we have two methods like the following:

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

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

In calling any method, you can supply the type witness regardless of whether or not there is any requirement:

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 中使用它有什么意义呢?

However I'm not seeing any realistic use for this in Java at all, unless the type cannot be inferred (which is usually indicative of a bigger issue). Additionally the fact that it is simply ignored when it is not appropriately used seems counterintuitive. So what's the point of having this in Java at all?

推荐答案

来自 JLS §15.2.12.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 1.4 中,JDK 有一个类

Along this line of reasoning, let's construct an example. Suppose in Java 1.4, JDK has a class

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

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

Some user wrote a proprietary class that extends Foo and overrides the check method

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

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

When Java 1.5 introduced generics, Foo.check is generified as

    public <T> T check(T obj)

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

The ambitious backward comparability goal requires that MyFoo still compiles in Java 1.5 without modification; and MyFoo.check[Object->Object] is still an overriding method of Foo.check[T->T].

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

Now, according to aforementioned justification, since this compiles:

    MyFoo myFoo = new MyFoo();

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

这也必须编译:

    myFoo.<String>check("");

即使 MyFoo.check 不是通用的.

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

That sounds like a stretch. But even if we buy that argument, the solution is still too broad and overreaching. JLS could've tighten it up so that myFoo.<String,String>check and obj.<Blah>toString() are illegal, because type parameter arity doesn't match. They probably didn't have time to iron it out so they just took a simple route.

这篇关于在所有方法调用中允许类型见证有什么意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆