[英]Why super classes generic type not erased/casted
Consider the following piece of code: 考虑以下代码:
class A<T>{
T t;
public T getValue(){
return t;
}
class B<S extends Number> extends A<String>{
//some code here..
}
B b = new B<Integer>();
String name = b.getValue() // This throws compilation error
whereas the following works: 而以下作品:
B<Integer> b = new B<Integer>();
String name = b.getValue() // This works...!
So my questions are: 所以我的问题是:
Do I have to give declare all the generics type involved? 我是否必须声明所有涉及的泛型类型? (Even though Class A's generic type was declared in Class B.)
(即使在B类中声明了A类的泛型类型。)
Or, am I missing something basically? 或者,我基本上是缺少什么吗?
See JLS 4.8 Raw Types : 请参阅JLS 4.8原始类型 :
a raw type is defined to be [...] the reference type that is formed by taking the name of a generic type declaration without an accompanying type argument list.
原始类型被定义为通过采用通用类型声明的名称而没有附带的类型参数列表而形成的引用类型。
The superclasses (respectively, superinterfaces) of a raw type are the erasures of the superclasses (superinterfaces) of any of its parameterized invocations.
原始类型的超类(分别是超接口)是其任何参数化调用的超类(超接口)的擦除。
In other words, when you use B
without <>
, it becomes a raw type, basically erasing all generics, all the way up all base classes and interfaces, ie is becomes as if A
and B
weren't generic: 换句话说,当您使用不带
<>
B
时,它将成为原始类型,基本上擦除所有泛型,直至所有基类和接口,即好像A
和B
不是泛型的:
class A {
Object t;
public Object getValue() {
return t;
}
}
class B extends A {
//some code here..
}
Which is why String name = b.getValue()
fails, because getValue()
is now returning an Object
. 这就是
String name = b.getValue()
失败的原因,因为getValue()
现在返回一个Object
。
Note the following comment in the JLS: 请注意JLS中的以下注释:
The use of raw types is allowed only as a concession to compatibility of legacy code.
仅允许使用原始类型作为对遗留代码兼容性的让步。 The use of raw types in code written after the introduction of generics into the Java programming language is strongly discouraged .
强烈建议不要在将泛型引入Java编程语言后在代码中使用原始类型 。 It is possible that future versions of the Java programming language will disallow the use of raw types.
Java编程语言的未来版本可能会禁止使用原始类型。
In short, DON'T . 简而言之, 不要 。 Fix your code to not use raw types.
修复您的代码以不使用原始类型。
You can however shorten the right-hand side as follows: 但是,您可以按如下所示缩短右侧:
B<Integer> b = new B<>();
The generic value of class B simply has no link with the one from class A. B类的通用值与A类的值没有任何链接。
The method T getValue() of a A(Long) will be Long getValue(), disregarding any genericity on the wrapping class. A(Long)的方法T getValue()将是Long getValue(),而不考虑包装类上的任何泛型。
If you want an Integer getValue() then simply go for 如果您想要一个整数getValue(),那么只需
class B extends A<Integer> {}
EDIT : you change your question, lets change the response :) 编辑:您更改您的问题,让我们更改响应:)
B is considered as B (S extends Number, T) (because it extends A). B被认为是B(S扩展Number,T)(因为它扩展了A)。 If you store a variable as a raw type B, then its is implicitly B(Object, Object), even if declared properly.
如果将变量存储为原始类型B,则即使声明正确,其隐式也是B(Object,Object)。
Make test with a List 用清单进行测试
List l = new ArrayList<String>();
String s = l.get(0);
You will end with the same issue. 您将遇到同样的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.