CSCE 314 Lecture 31
Jump to navigation
Jump to search
« previous | Monday, November 14, 2011 | next »
Wildcards
Variables and arrays support wildcard types, but the rest of the code does not know the type of the stored variable:
Set<?> aSet = new HashSet<String>();
// you couldn't do these since we are not allowed to access what the '?' is
String s = aSet.get();
addToSet(aSet, "string");
These are useful when we need to know that we're working with a Set, but we don't know what the Set will contain.
Type Erasure
Generics are used for type-checking, then erased according to translation rules:
- Type parameters replaced with bounds
- Parameterized types throw aay parameters
- Casts inserted where necessary (casts will exist at runtime, but they'll never throw errors)
Example
Generic code:
class A<T> { abstract T id(T x); }
class B extends A<Integer> {
Integer id(Integer x) { return x; }
}
Integer foo(A<Integer> a) {
return a.id(1);
}
Translated code:
class A { abstract Object id(Object x); }
class B extends A {
Integer id(Integer x) { return x; }
Object id(Object x) { return id((Integer) x); } // bridge function
}
Integer foo(A a) {
return (Integer) a.id(1);
}
Implications
- only one runtime representation of all instances of a generic class: List<String> has same class as List<Integer>
- "new", "instanceof", and "static" keywords that deal with type parameters will not work
- no copy constructor usage; must use Clonable (not recommended) to clone an object (has default protected clone function)
- Explicitly defining Object id(Object x) within a subtype of a generic class results in a duplicated method error
- classes cannot implement two interfaces with same parameterization
On a good note, primitive data types like int are automatically boxed into Integer and unboxed.