Summary on some java generics presentations/postings

Gilad Bracha, Generics in the Java Programming Language

1. Wildcard is a supertype of all kinds of collections.

void print Collection(Collection<?> c) {
  for (Object e: c) // Wildcard is an object
    System.out.println(e);
}

2. You can not add anything into the container of ?.

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Impossible, because ? is unknown type. Null is an exception.

3. Use ? extends SuperClass for reading

public void drawAll(List<? extends Shape> shapes) { ... }

4. To add something to generic collection, use generic methods

static <T> void fromArrayToCollection(T[ ] a, Collection<T> c) {
  for(T o: a) c.add(o);
}

Why? Because the following does not work:

static void fromArrayToCollection(Object[ ] a, Collection<?> c) {
  for (Object o: a) c.add(o); // No, you can't add something to the collection of ?.
}

6. Generic Methods vs Wildcard
Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn’t such a dependency, use wildcard. Consider:

interface Collection<E> { 
  // reading from c. So, it's okay to use ?.
  public boolean containsAll(Collection<?> c);

  // also for reading.
  public boolean addAll(Collection<? extends E> c);
}

interface Collection<E> { 
  public <T> boolean containsAll(Collection<T> c);
  public <T extends E> boolean addAll(Collection<T> c);
}

Using wildcard is short and efficient. Moreover, wildcards can be used by local variables/fields/etc, e.g., List<?> aList = …;

7. Generic classes are shared.

List<String> l1 = new ArrayList();
List<Integer> l2 = new ArrayList();
System.out.println(l1.getClass() == l2.getClass()); // prints true

8. Type variables do not exist at run time

// Unchecked warning
Collections<String> cstr = (Collection<String>) new ArrayList<String>();

// Unchecked warning
<T> T badCast(T t, Object o) { return (T) o; }

9. Class Literals as Run-time Type Tokens

Collection<EmpInfo< emps = sqlUtility.select(EmpInfo.class, ...);
public static Collection select(Class<T> c, String sqlStatement) {
  ...
  T item = c.newInstance();
  ...
}

10. More fun with Wildcards

// Let me write T into Sink which accepts parents of T.
public static <T> T writeAll(Collection<T> coll, Sink<? super T> snk) { ... }

// Comparable
TreeSet(Comparator<? super E> c)

// max
public static <T extends Comparable<? super T>>
T max(Collection<T> coll)

Joshua Bloch, Effective Java Reloaded, JavaOne, 2006

1. Prefer Wildcards To Type Parameters
The rule: If a type variable appears only once in a method signature, use wildcard instead
The exception: conjunctive type

<E, T extends Serializable & List<E>> void f(T list) { ... }

2. Bounded wildard to the Rescue
Use extends when parameterized instance is producer(“for read”)
Use super when parameterized instance is consumer(“for write”)

public interface Shop<T> {
  T buy();
  void sell(Collection<? extends T> lot);
  void buy(int numItems, Collection<? super T> myStuff);
}

3. Avoid Bounded Wildcards in Return Types
They force client to deal with wildcards directly. Rarely, you do need it.

4. Typesafe Heterogeneous Container(THC) Example

public class Favorites {

  private Map<Class<?>, Object> favorites =
      new HashMap<Class<?>, Object> (); // Heterogeneous Map

  public <T> void setFavorite(Class<T> klass, T thing) {
    favorites.put(klass, thing);
  }

  public <T> T getFavorite(Class<T> klass) {
    return klass.cast(favorites.get(klass));
  }

  public static void main(String[] args) {
    Favorites f = new Favorites();
    f.setFavorite(String.class, "Java");
    f.setFavorite(Integer.class, 0xcafebabe);
    String s = f.getFavorite(String.class);
    int i = f.getFavorite(Integer.class);
  }
}

Neal Gafter, Super Type Token

1. Type Token
Type token refers to a way to refer to the Class instance of a specific class. For example, Class<String>. This enables THC(Typesafe Heterogeneous Container). But the problem is that referring to the class of a generic class, say, List<String>.class is not possible.

2. Super Type Token
THC does not support f.setFavorite(List<String>.class, collections.emptyList()), because of Erasure. How can we do that?

Basic idea is as follows:

public abstract class TypeReference<T> {}
TypeReference<List<String>> x = new TypeReference<List<String>>() {}; // Now I have type information stored somewhere

Concrete implementation of this idea:

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * References a generic type.
 *
 * @author crazybob@google.com (Bob Lee)
 */
public abstract class TypeReference<T> {

    private final Type type;
    private volatile Constructor<?> constructor;

    protected TypeReference() {
        Type superclass = getClass().getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
    }

    /**
     * Instantiates a new instance of {@code T} using the default, no-arg
     * constructor.
     */
    @SuppressWarnings("unchecked")
    public T newInstance()
            throws NoSuchMethodException, IllegalAccessException,
                   InvocationTargetException, InstantiationException {
        if (constructor == null) {
            Class<?> rawType = type instanceof Class<?>
                ? (Class<?>) type
                : (Class<?>) ((ParameterizedType) type).getRawType();
            constructor = rawType.getConstructor();
        }
        return (T) constructor.newInstance();
    }

    /**
     * Gets the referenced type.
     */
    public Type getType() {
        return this.type;
    }

    public static void main(String[] args) throws Exception {
        List<String> l1 = new TypeReference<ArrayList<String>>() {}.newInstance();
        List l2 = new TypeReference<ArrayList>() {}.newInstance();
    }
}

Similar Posts:

Comments 3

  1. myrmy wrote:

    방명록이 폭파되었다니. OTL
    돌아온 블로그, 반가워요. ^^

    Posted 03 Jun 2007 at 1:11 am
  2. Gilad Bracha wrote:

    Nice summary of a very complex topic. Well done.

    Posted 03 Jun 2007 at 1:50 am
  3. MKSeo wrote:

    @myrmy: 감사 ^^. 방명록은 도무지 관리할 수가 없어요…
    @Gilad: Hey, I’m very happy to see you, the author of the primal article on Java Generics and the Java Spec., at my blog!! Thank you for the nice document that introduced Java Generics to me.

    Posted 03 Jun 2007 at 3:30 am

Trackbacks & Pingbacks 1

  1. From IT's Lives. :: Enum class 과 Generic method 그리고 Prefer Wildcard on 31 Jan 2009 at 9:22 pm

    Kramer auto Pingback[…] 하니동시에 두가지 형태를 지원하는 것에 대한 자료를 찾아보았다.한글 블로그 이지만 영어로 정리가 잘 되어 있다.결론적으로 해결책은public static <T extends Enum<T> & CodeEnum> T getEnum( […]

Post a Comment

Your email is never published nor shared.