I try to understand more fundamentally type casting in Java but can not understand some parts of JLS.
In particular this (in the meaning of casting of class type S to class or interface type T):
Furthermore, if there exists a supertype X of T, and a supertype Y of S, such that both X and Y are provably distinct parameterized types (§4.5), and that the erasures of X and Y are the same, a compile-time error occurs.
and this (in the meaning of casting of interface type S to final class type T):
Otherwise, S is either a parameterized type that is an invocation of some generic type declaration G, or a raw type corresponding to a generic type declaration G. Then there must exist a supertype X of T, such that X is an invocation of G, or a compile-time error occurs. Furthermore, if S and X are provably distinct parameterized types then a compile-time error occurs.
Maybe someone can give some brief examples to clarify these extracts?
PS After a some consideration and guidance from @ErickGHagstrom I think I can give a clarification of these two tricky JLS extracts.
JLS says:
Two parameterized types are provably distinct if either of the following is true:
They are parameterizations of distinct generic type declarations.
Any of their type arguments are provably distinct.
and:
Two type arguments are provably distinct if one of the following is true:
Neither argument is a type variable or wildcard, and the two arguments are not the same type.
One type argument is a type variable or wildcard, with an upper bound (from capture conversion (§5.1.10), if necessary) of S; and the other type argument T is not a type variable or wildcard; and neither |S| <: |T| nor |T| <: |S| (§4.8, §4.10).
Each type argument is a type variable or wildcard, with upper bounds (from capture conversion, if necessary) of S and T; and neither |S| <: |T| nor |T| <: |S|.
Therefore List<Integer>
and List<Number>
are provably distinct but List<? extends Integer>
List<? extends Integer>
and List<? extends Number>
List<? extends Number>
are not (all listed types have the same erasure).
The key point is that sub-typing relationship between two provably distinct parametrized types with the same erasure is not possible in any way.
Sub-typing relationship between sub-types of two provably distinct parametrized types with the same erasure is also not possible in any way. If S <: List<Integer>
and T <: List<Number>
then castings (T)S
and (S)T
both are not possible even theoretically. So compiler complains.
Here is the example I came up with (compiles and runs without errors):
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
}
You can see that List<?>
and List<? extends Number>
List<? extends Number>
can be cast to final T
while T
does not (and can not) implement any of these interfaces.
T <: List<Number>
. List<Number>
is invocation of List<E>
like List<?>
and List<? extends Number>
List<? extends Number>
. List<Number>
and List<?>
and List<? extends Number>
List<? extends Number>
are not provably distinct (see above).
If we want to cast something of parametrized interface type S
to final class type T
this T
need not explicitly or implicitly to implement S
. But this T
must to implement some another parametrized interface type which is in sub-type relationship with S
. The key point is that sub-type relationship between parametrized types is defined not only by extending or implementing but also by type argument containing .
ArrayList<String>
vs. ArrayList<Integer>
have the same erasure, ArrayList
, but are provably distinct because no String
can ever be cast to an Integer
and no Integer
can ever be cast to a String
.
Let G be List<T>
and S be List<String>
. Suppose I have a class MyFinalArrayList
like so:
public final class MyFinalIntArrayList extends ArrayList<Integer> {
...
}
and another like
public final class MyFinalStrArrayList extends ArrayList<String> {
...
}
I can cast the first to List<Integer
and the second to List<String
, but not vice versa.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.