java泛型extend使用_Java泛型-使泛型扩展2个接口

小编典典

Reimeus已经指出,您在编辑中要求的内容是不可能的。我只想扩展一下原因。

人们会认为您可以使用以下内容:

public void mapThis(

Class extends MyClass> key,

Class extends U> value

) { ... }

实际上,这就是我第一次看到这篇文章时想到的。但这实际上会导致编译器错误:

类型变量不能跟其他界限

为了帮助我解释原因,我想引用Victor Rudometov在OracleBlogs上发表的有关此错误的文章:

这个事实并不总是很清楚,但确实如此。以下代码不应编译:

interface I {}

class TestBounds {

}

因为JLS第4章类型,值和变量部分4.4类型变量规定:“ 结合的由 任一 类型变量,或者可能接着进一步接口类型的类或接口类型T I

1,…,I Ñ。 ” 。因此,可以使用 T扩展U,T扩展SomeClass&I ,但不可以 T扩展U&I

。该规则适用于所有情况,包括类型变量以及方法和构造函数中的界限。

总而言之,施加此限制是为了“避免某些尴尬的情况出现”(JLS§4.9)。

什么样的尴尬情况?克里斯·波维尔克(ChrisPovirk)的回答描述了一个:

[限制的原因是]指定非法类型的可能性。具体而言,使用不同的参数两次扩展通用接口。我无法提出一个非人为的示例,但是:

/** Contains a Comparator that also implements the given type T.

*/

class StringComparatorHolder> {

private final C comparator;

// …

}

void foo(StringComparatorHolder, ?> holder) { ... }

现在holder.comparator是Comparator和Comparator。

克里斯还指出了Sun bug4899305,它是与该语言限制相抗衡的bug。由于无法修复,已关闭,并带有以下注释:

如果类型变量后面可以跟着类型变量或(可能是参数化的)接口,则可能会有更多相互递归的类型变量,这很难处理。当边界仅仅是参数化类型(例如)时,事情已经很复杂>。因此,界限现在不会改变。javac和Eclipse都同意S&T并且 S&Comparable是非法的。

因此,这就是限制的背后原因。我要特别指出泛型方法(您的问题所涉及的问题),我还要进一步指出,类型推断理论上将导致此类界限毫无意义。

如果我们重新检查以上假设签名中声明的类型参数:

假设调用方未明确指定Tand U,则可以将其简化为以下内容:

或者只是这个(细微的差别,但这是另一个主题):

这是因为T没有界限,所以无论传入哪种类型的参数,T都Object至少可以始终解析为,然后可以U。

让我们回去说T有界:

可以用相同的方式减少它(Foo可以是类或接口):

基于这种推理,就将调用方限制为更特定的参数而言,您要尝试实现的语法毫无意义。

Java 8之前的附录:

在此之前的Java 8, 是 一个用例你想做什么。由于编译器如何推断通用方法类型参数的限制,我的上述推理是不合时宜的。采用以下通用方法:

class MyClass {

static void foo(T t1, T t2) { }

}

这是尝试制作一个采用两个“相同类型”参数的方法的常见初学者错误。当然,由于继承的方式,这毫无意义:

MyClass.foo("asdf", 42); // legal

在这里,T可以推断为Object-这与简化mapThis类型参数的早期推理相吻合。您必须手动指定类型参数才能实现预期的类型检查:

MyClass.foo("asdf", 42); // compiler error

但是, 这是您的用例开始出现的地方,带有交错边界的多个类型参数是另一回事:

class MyClass {

static void foo(T t, U u) { }

}

现在,此调用错误:

MyClass.foo("asdf", 42); // compiler error

表已经翻转了-我们必须手动放松类型参数才能进行编译:

MyClass.foo("asdf", 42); // legal

发生这种情况是因为编译器推断方法类型参数的方式有限。因此,您想要实现的目标实际上是在限制调用者参数的应用程序。

但是,此问题似乎已在Java 8中得到修复,MyClass.foo("asdf",42)现在可以编译而没有任何错误(感谢Regent指出了这一点)。

2020-09-15

你可能感兴趣的:(java泛型extend使用)