CSCE 314 Lecture 31

From Notes
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:

  1. Type parameters replaced with bounds
  2. Parameterized types throw aay parameters
  3. 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.