当前位置: 首页 > 面试题库 >

在所有方法调用中允许类型见证人有什么意义?

牛智志
2023-03-14
问题内容

说我们有以下两种方法:

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

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

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

但是,除非在无法推断出类型的情况下(通常表明存在更大的问题),否则我在Java中根本看不到任何实际用途。另外,当不适当使用它时将其简单忽略的事实似乎违反直觉。那么,在Java中完全有什么意义呢?


问题答案:

从JLS§15.2.12.1开始:

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

此子句暗示非泛型方法可能潜在地适用于提供显式类型参数的调用。确实,这可能是适用的。在这种情况下,类型参数将被简单地忽略。

其次是理由

该规则源于兼容性和可替代性原则。由于接口或超类的生成可以独立于其子类型,因此我们可以用非泛型方法覆盖泛型方法。但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型实参的调用。否则,该亚型将无法替代其生成的超型。

按照这一推理,让我们构造一个示例。假设在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中有任何实际的用途,除非无法推断类型(这通常表明存在更大的问题)。此外,如果不恰当地使用它,它就会被忽略,这一事实似乎违反了直觉。那么,在Java中使用它有什么意义呢?

  • 问题内容: 这是我的代码,但是我没有得到方法如何接受类型作为返回值。如何运作?谁能解释一下这种方法的工作原理? 提前致谢 :) 问题答案: 好的,所以首先要做的是: 这是一个不断扩大的原始类型转换,因此这是合法的。您可以: 但是您不能: 第二:它返回的根本不是ASCII码。Java执行Unicode。 碰巧的是,当创建Java时,Unicode仅定义了适合16位的代码点。因此,它被创建为2字节的无

  • 问题内容: 为什么在Java 8中允许接口具有方法? 如下面的代码所述,它可以正常工作并正确产生输出。 目前它的行为就像一个类,我已经用main方法执行了。 我们为什么需要这个? 问题答案: 从Java 8开始,接口中允许使用静态方法。 main()是静态方法。 因此,在接口中允许main()。 我们 不需要 它,因为以前不允许这样做,但是我们幸存了下来。但是,根据定义,由于静态方法不是绑定到类的

  • 为什么我们不能降低能见度,但可以提高能见度? 此外,我需要实现模板模式,其中可见的公共方法只能是基类。

  • 我在教条文档中读到了对我来说意义不大的以下内容: 使用选项时,假设实体是私有的,不会被其他实体重用。

  • 问题内容: 使用“抽象方法”有什么意义?抽象类不能实例化,但是抽象方法呢?他们只是在这里说“您必须实现我”,如果我们忘记了它们,编译器会抛出错误? 这还意味着其他吗?我还阅读了有关“我们不必重写相同的代码”的内容,但是在抽象类中,我们仅“声明”了抽象方法,因此我们将不得不在子类中重写代码。 您能帮我多了解一点吗?我检查了有关“抽象类/方法”的其他主题,但没有找到答案。 问题答案: 除了提醒您必须实