我试图从根本上理解Java中的类型转换,但无法理解JLS的某些部分。
特别是(从S类到类或接口类型T的转换):
此外,如果存在T的超型X和S的超型Y,使得X和Y都是明显不同的参数化类型(§4.5),并且X和Y的擦除是相同的,则会发生编译时错误。
这(从界面类型S到最终类型T)的意思是:
否则,S要么是参数化类型,它是对某些泛型类型声明G的调用,要么是对应于泛型类型声明G的原始类型。然后,必须存在T的超级类型X,这样X就是G的调用,或者出现编译时错误。此外,如果S和X是明显不同的参数化类型,则会发生编译时错误.
也许有人能举出一些简单的例子来澄清这些摘录?
经过@ErickGHagstrom的一些考虑和指导,我想我可以澄清这两个棘手的JLS摘要。
萃取物1。
JLS说:
如果下列任何一种类型是正确的,则两个参数化类型可以证明是不同的:
以及:
如果下列其中一个参数为真,则两个类型参数可以证明是不同的:
因此,List<Integer>和List<Number>是明显不同的,但是List<? extends Integer>和List<? extends Number>不是(所有列出的类型都有相同的擦除)。
关键是,两个明显不同的参数化类型与相同的擦除之间的子类型之间的关系是不可能的。
两个明显不同的参数化类型之间的子类型之间的关系与相同的擦除也是不可能的。如果S <: List<Integer>和T <: List<Number>的话,那么(T)S和(S)T在理论上都是不可能的。所以编译器抱怨。
萃取物2。
下面是我提出的示例(编译和运行没有错误):
static final class T extends ArrayList<Number>{
}
static T t;
static List<?> l1 = new T();
static List<? extends Number> l2 = new T();
static List<String> l3;
public static void main(String[] args) {
t = (T)l1;
t = (T)l2;
// t = (T)l3; //error
}您可以看到,List<?>和List<? extends Number>可以转换为最终的T,而T没有(也不能)实现任何这些接口。
T <: List<Number>。List<Number>是对List<E>的调用,如List<?>和List<? extends Number>。List<Number>和List<?>与List<? extends Number>并没有明显的区别(见上文)。
如果我们想将参数化接口类型S转换为最终类类型T,则T 不需要显式或隐式地实现S。但是这个T 必须来实现另一个参数化接口类型,该接口类型是与S的子类型关系。关键是参数化类型之间的子类型关系不仅是通过扩展或实现来定义的,而且也是通过包含类型参数的类型来定义的。
发布于 2016-01-10 11:46:05
第一种情况:
ArrayList<String>和ArrayList<Integer>具有相同的擦除功能,ArrayList,但是可以证明它们是不同的,因为没有String可以转换为Integer,也没有Integer可以转换为String。
第二种情况:
设G为List<T>,S为List<String>。假设我有一个类似于这样的类MyFinalArrayList:
public final class MyFinalIntArrayList extends ArrayList<Integer> {
...
}另一个类似的
public final class MyFinalStrArrayList extends ArrayList<String> {
...
}我可以将第一个转换为List<Integer,第二个可以转换为List<String,但反之亦然。
https://stackoverflow.com/questions/34704768
复制相似问题