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

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

问题描述

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

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

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

 字符串s; 
s = Internet。< String> genericReturn(); //在返回类型中使用的类型见证,返回一个字符串
s = Internet。< Integer> stringReturn(); //类型目击被忽略,返回一个字符串

然而我没有看到任何实际的用法Java,除非无法推断出类型(这通常表示更大的问题)。另外,当它没有被恰当地使用时,它被简单地忽略的事实看起来是违反直觉的。那么,在Java中拥有这一点有什么意义呢? 解决方案

来自JLS§15.2.12.1

< blockquote>


  • 如果方法调用包含显式类型参数,且成员是泛型方法,则类型参数的数量等于方法的类型参数数。


该条意味着非泛型方法可能适用于提供显式类型参数的调用。事实上,它可能会变得适用。在这种情况下,类型参数将被忽略。


接下来是理由


这条规则源于兼容性问题和可替代性原则。由于接口或超类可以独立于它们的子类型进行基因化,我们可以用一个非泛型方法覆盖泛型方法。但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型参数的调用。否则,该亚型不会被它的generified超型替代。

沿着这条推理线,我们来构造一个exmaple。假设在Java1.4中,JDK有一个类

  public class Foo 
{
/ ** check obj并返回它* /
public Object check(Object obj){...}
}

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

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

当Java1.5引入泛型时, Foo.check 被泛化为

  public< T> T检查(T obj)

雄心勃勃的向后可比性目标要求 MyFoo 仍然在Java1.5中编译而不需要修改;和 MyFoo.check [Object-> Object] 仍然是一个重载方法 Foo.check [T-> T]



现在,根据上述理由,由于此编译

  MyFoo myFoo = new MyFoo(); 

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

这也必须编译

  myFoo。< String> check(); 

即使 MyFoo.check 不是通用的。






这听起来像是一段时间。但即使我们购买了这一论点,解决方案仍然过于宽泛和过度。 < code> myFoo。< String,String> check 和 obj。< Blah> toString()是非法的,因为类型参数arity不匹配。他们可能没有时间去解决问题,所以他们只是走了一条简单的路线。

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 a String
s = Internet.<Integer>stringReturn(); //Type witness ignored, returns a String

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?

解决方案

From the 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.

It's followed by justification

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.

Along this line of reasoning, let's construct an exmaple. Suppose in Java1.4, JDK has a class

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

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

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

When Java1.5 introduced generics, Foo.check is generified as

    public <T> T check(T obj)

The ambitious backward comparability goal requires that MyFoo still compiles in Java1.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("");

This must compile too

    myFoo.<String>check("");

even though MyFoo.check is not generic.


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 an simple route.

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

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