Java 铸造通用<;T>;超泛型<;SuperT>;

Java 铸造通用<;T>;超泛型<;SuperT>;,java,generics,language-lawyer,Java,Generics,Language Lawyer,我试图找到一个参考,最好是从语言标准中,关于为什么在同一个语句中,将一个T容器强制转换为一个超类型的容器和一个超类型的T不起作用 我试着查找擦除、强制转换泛型和特定容器类的各种组合,但找不到确切的副本(大多数只找到地址t及其超类)。我特别感兴趣的是语言标准在这个问题上要说些什么,以及用于这个问题的术语 例如,编译器不接受以下内容: final WebappContext context = ...; final List<FilterRegistration> filters = L

我试图找到一个参考,最好是从语言标准中,关于为什么在同一个语句中,将一个T容器强制转换为一个超类型的容器和一个超类型的T不起作用

我试着查找擦除、强制转换泛型和特定容器类的各种组合,但找不到确切的副本(大多数只找到地址t及其超类)。我特别感兴趣的是语言标准在这个问题上要说些什么,以及用于这个问题的术语

例如,编译器不接受以下内容:

final WebappContext context = ...;
final List<FilterRegistration> filters = Lists.newArrayList(
    context.addFilter(...), ...
);
尽管
List
ArrayList
的超类,而
FilterRegistration
是Grizzly实现的超类,这一点仍然存在

如果我将其更改为:

final WebappContext context = ...;
final List<FilterRegistration> filters = Lists.<FilterRegistration>newArrayList(
    context.addFilter(...), ...
);
final WebappContext=。。。;
最终列表过滤器=Lists.newArrayList(
context.addFilter(…)。。。
);
然后一切都非常愉快,甚至没有一个未经检查的警告。我能找到的唯一变化是返回类型从
ArrrayList
变为
ArrrayList


<> P>我知道C++有一个规则,编译器在试图为特定调用解析最佳类型时只能执行单个强制转换。这看起来是以同样的方式进行的,但是Java称它为什么,规则是如何定义的?它与类型擦除有关吗?这是怎么回事?

我认为错误不在于将
泛型
转换为
超泛型
,而是事实上编译器在某些情况下无法正确推断类型:

static <T> List<T> emptyList() {...}
编译器应该推断T的
String
,但不能(因为这不是一门完美的科学,它取决于javac的版本;像这样的例子在我的JDK5项目中失败了,或者是JDT[Eclipse编译器]。尤其是Guava!)


我的示例很差,但如果太复杂,您将被迫使用
Class.method
语法指定类型。

我认为错误不在于将
泛型
转换为
超泛型
,但事实上编译器在某些情况下无法正确推断类型:

static <T> List<T> emptyList() {...}
编译器应该推断T的
String
,但不能(因为这不是一门完美的科学,它取决于javac的版本;像这样的例子在我的JDK5项目中失败了,或者是JDT[Eclipse编译器]。尤其是Guava!)


我的示例很差,但如果太复杂,您将被迫使用
Class.method
语法指定类型。

我认为错误不在于将
泛型
转换为
超泛型
,但事实上编译器在某些情况下无法正确推断类型:

static <T> List<T> emptyList() {...}
编译器应该推断T的
String
,但不能(因为这不是一门完美的科学,它取决于javac的版本;像这样的例子在我的JDK5项目中失败了,或者是JDT[Eclipse编译器]。尤其是Guava!)


我的示例很差,但如果太复杂,您将被迫使用
Class.method
语法指定类型。

我认为错误不在于将
泛型
转换为
超泛型
,但事实上编译器在某些情况下无法正确推断类型:

static <T> List<T> emptyList() {...}
编译器应该推断T的
String
,但不能(因为这不是一门完美的科学,它取决于javac的版本;像这样的例子在我的JDK5项目中失败了,或者是JDT[Eclipse编译器]。尤其是Guava!)


我的示例很糟糕,但是如果太复杂,您必须使用
Class.method
语法指定类型。

有两个问题。首先,

为什么我不能将
Generic
分配给
SuperGeneric

答案是:因为同样的原因,你不能。问题是由泛型类型引起的,而不是由自动向上转换
generic
SuperGeneric
引起的。还要检查,这可以提供一些解决方法

第二,

为什么
Lists.newArrayList()
不能按预期工作

让我们考虑以下层次:

                      class SuperT
                            |
              class MiddleT extends SuperT
                  /                  \
class SubT1 extends MiddleT    class SubT2 extends MiddleT
让我们来看一个简化版的
toList()
方法,它只需要两个参数:

<T> List<T> toList(T t1, T t2) { ... }
(不需要
SubT1
SubT2
类,explasample在
asList(new MiddleT(),new MiddleT())
中也可以正常工作,但我想说明如果不显式编写
T
,编译器是如何替换最接近的公共超类型的)

但不用担心,Java8是来拯救这一天的。使用JDK
1.8.0_11
可以很好地编译以下代码:

List<SuperT> list = Lists.asList(new SubT1(), new SubT2()); // OK in 1.8 version
List List=Lists.asList(new SubT1(),new SubT2());//1.8版本中的OK

我猜编译器现在会在决定
T
应该是什么时查看结果的用途。

有两个问题。首先,

为什么我不能将
Generic
分配给
SuperGeneric

答案是:因为同样的原因,你不能。问题是由泛型类型引起的,而不是由自动向上转换
generic
SuperGeneric
引起的。还要检查,这可以提供一些解决方法

第二,

为什么
Lists.newArrayList()
不能按预期工作

让我们考虑以下层次:

                      class SuperT
                            |
              class MiddleT extends SuperT
                  /                  \
class SubT1 extends MiddleT    class SubT2 extends MiddleT
让我们来看一个简化版的
toList()
方法,它只需要两个参数:

<T> List<T> toList(T t1, T t2) { ... }
(不需要
SubT1
SubT2
类,explasample在
asList(new MiddleT(),new MiddleT())
中也可以正常工作,但我想说明如果不显式编写
T
,编译器是如何替换最接近的公共超类型的)

但不用担心,Java8是来拯救这一天的。使用JDK
1.8.0_11