07.5 Subtype Question

advertisement
Generics and Subtyping
• What is wrong with the following:
List<Integer>[] arrayList1 =
new ArrayList<Integer>[10];
ArrayList<Integer>[] arrayList2 =
new ArrayList<Integer>[10];
– both cause a compile-time "generic array
creation" error. Why?
– my examples are in SubTypingTests.java
ADSA: Subtypes/7
1
Superclass Variables
• A superclass variable can be assigned a
subclass object:
• Number num = new Integer(0);
– Number is a superclass of Integer
ADSA: Subtypes/7
// ok
2
Type Constructors
• Types come in two sorts:
– basic types: int, char, Integer, String, etc.
– type constructors: these are ways to build more
complex types from the basic ones
•
e.g. arrays and collections
– Integer[], ArrayList<String>
ADSA: Subtypes/7
3
Covariance
• A type constructor is covariant if it
preserves the super/subclass ordering of its
component types.
• Example using []:
– Animal is a superclass of Cat
– Animal[] is a superclass of Cat[]
ADSA: Subtypes/7
4
Array Subtyping is Covariant
• type S[] is a subtype of T[] when S is a
subtype of T
• e.g.
Number[] nums = new Integer[] {1,2,3};
// ok
nums[0] = 3.14;
// compiles, but raises an
// ArrayStoreException at run-time
ADSA: Subtypes/7
5
• The array element type (Integer) is
remembered by Java at run time
– called a reified type
ADSA: Subtypes/7
6
Invariance
• A type constructor is invariant if it does not
support the super/subclass ordering of its
componenet types.
• Generics are invariant for their parameterized
types
– List< Integer> is a superclass of ArrayList<Integer> ✔
– List<Number> is invariant for ArrayList<Integer> ✘
– ArrayList<Number> is invariant for ArrayList<Integer>
✘
• invariance triggers compile-time errors
ADSA: Subtypes/7
7
Superclass vars and Generics
• If a collection variable and collection object
have the same parameterized type, then
superclass variables are still allowed:
• List<Integer> iList =
new ArrayList<Integer>();
// ok
– List is a superclass of ArrayList
– compare to the first slide!
ADSA: Subtypes/7
8
Subtyping for Generics is Invariant
• List<S> is not a subtype of List<T>
– except where S and T are the same
• This means that superclass variables are not
allowed if S and T are different, even if the
collection (List) is the same.
• e.g.
ArrayList<Number> nums = new ArrayList<Integer>();
// causes a compile-time error
nums.put(0, 3.14);
ADSA: Subtypes/7
// Java never gets here
9
Type Erasure
• Parameterized type information is discarded
after compilation has finished.
• e.g. at run-time, the JRE only knows:
List<String> ==> List
ArrayList<Fruit> ==> ArrayList
• Why? For binary compatibility with
collections code written before Java 5
ADSA: Subtypes/7
10
Problems with Type Erasure
• If generic subtype covariance was allowed,
then the following code would incorrectly
work:
ArrayList<Number> nums = new ArrayList<Integer>();
nums.put(0, 3.14);
// no run-time error, but there should be!!
• The reason is that the JRE only knows
about ArrayList, not ArrayList<Integer> at
run-time.
ADSA: Subtypes/7
11
Back to the Question
• List<Integer>[] arrLists =
new ArrayList<Integer>[10];
causes a compile time error. Why?
• If the code was allowed to compile then
type erasure would store ArrayList[] as the
type of the object.
ADSA: Subtypes/7
12
• Then the following could happen:
List<Double> doubleList = new ArrayList<Double>();
doubleList.add(Double.valueOf(1.23));
arrLists[0] = doubleList;
// no error occurs, but should!!
• The last assignment would work because
both objects (doubleList and arrLists[0]) are
of type ArrayList at run-time.
ADSA: Subtypes/7
13
Wildcards add covariant subtyping
to generics
• List<S> is a subtype of List<? extends T>
when S is a subtype of T
• e.g.
List<Integer> ints = Arrays.asList(1,2,3);
List<? extends Number> numsExt = ints;
numsExt.put(2, 3.14);
// compile-time error, not run-time
// as happens with arrays
ADSA: Subtypes/7
14
Contravariant Subtyping for Generics
• List<S> is a subtype of List<? super T>
when S is a supertype of T
• Arrays do not support contravariant
subtyping
ADSA: Subtypes/7
15
Download