当前位置: 首页 > 知识库问答 >
问题:

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

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

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

共有3个答案

秦跃
2023-03-14

这是因为向后和/或向前兼容(在源代码级别)。

想象一下在JDK 7中为Swing中的某些类引入泛型参数。方法也可能发生这种情况(即使有限制)。如果某个东西被证明是个坏主意,您可以删除它们,使用它的源代码仍然可以编译。在我看来,这就是为什么这是允许的,即使它没有被使用。

但灵活性有限。如果使用n类型引入了类型参数,则在m!=0m!=n

(我知道这可能无法回答您的问题,因为我不是Java的设计者,这只是我的想法/观点。)

甄胡非
2023-03-14

当类型推断无法工作时,您需要类型见证(菱形中的类型)(请参见http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html)

举个例子,菊花链调用如下:

processStringList(Collections.emptyList());

其中,过程StringList定义为:

void processStringList(List<String> stringList) 
{
    // process stringList
}

这将导致错误,因为它无法强制转换列表

秋光熙
2023-03-14

从JLS§15.2.12.1:

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

此子句意味着非泛型方法可能适用于提供显式类型参数的调用。事实上,它可能被证明是适用的。在这种情况下,类型参数将被忽略。

然后是辩护

这一规则源于兼容性问题和可替代性原则。由于接口或超类可以独立于其子类型进行泛型,因此我们可以用非泛型方法重写泛型方法。但是,重写(非泛型)方法必须适用于泛型方法的调用,包括显式传递类型参数的调用。否则,子类型将无法替换其泛化的超类型。

沿着这条推理路线,让我们构造一个示例。假设在Java1.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){ ... }
}

当Java1.5引入泛型时,Foo。检查被泛化为

    public <T> T check(T obj)

雄心勃勃的向后可比性目标要求MyFoo仍然在Java1.5编译而不修改;和MyFoo.check[Object-

现在,根据上述理由,由于这将编译:

    MyFoo myFoo = new MyFoo();

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

这也必须编译:

    myFoo.<String>check("");

即使MyFoo。检查不是通用的。

听起来有点牵强。但即使我们接受这一观点,解决方案仍然过于宽泛和过度。JLS可以把它收紧,这样myFoo。

 类似资料:
  • 问题内容: 说我们有以下两种方法: 在调用任何方法时,无论是否有任何要求,您都可以提供类型见证人: 但是,除非在无法推断出类型的情况下(通常表明存在更大的问题),否则我在Java中根本看不到任何实际用途。另外,当不适当使用它时将其简单忽略的事实似乎违反直觉。那么,在Java中完全有什么意义呢? 问题答案: 从JLS§15.2.12.1开始: 如果方法调用包括显式类型参数,并且成员是泛型方法,则类型

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

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

  • 问题内容: 可以有一个 实现所有方法 的抽象类-里面没有抽象方法。 例如。: 与拥有与具体类相同的类相比,拥有这样的抽象类(如果有)有什么优势? 我能想到的是,当我将其声明为抽象时,它将不会被实例化。但是,我可以通过将其具体化并将其构造函数设为私有来达到相同的效果。 TIA。 // ================== 编辑:我能想到的另一种用途: 它可能会扩展另一个抽象类或实现一个接口,而不实现

  • 问题内容: 我正在进行代码审查,并遇到了一个使用所有静态方法的类。入口方法接受几个参数,然后开始调用其他静态方法,并传递入口方法接收到的所有或某些参数。 它不像具有大量不相关的实用程序功能的Math类。在我自己的常规编程中,我很少编写Resharper弹出并说“这可能是静态方法”的方法,而当我这样做时,它们往往是无用的实用方法。 这种模式有什么问题吗?如果类的状态保存在字段和属性中或使用参数在静态

  • 问题内容: 我需要进行以下测试,以验证是否已调用Person类的所有getter。到目前为止,我已经使用了Mockito的verify()来确保每个getter都被调用。有没有办法通过反思做到这一点?可能是将新的吸气剂添加到Person类的情况,但是测试会错过这一点。 问题答案: 通常,不要嘲笑被测类。如果您的测试是针对Person的,则您永远都不会看到它,因为这很明显地表明您正在测试模拟框架而不