Monday, April 26, 2010

Raw types make my head hurt

This compiles:

public static void main(final String... args) {
    final Fred fred = new Fred();
    final Integer i = fred.get(Integer.class);
}

public interface Bob {
    <T> T get(final Class<T> type);
}

public static class Fred implements Bob {
    @Override
    public <T> T get(final Class<T> type) {
        return type.cast(null);
    }
}

This does not:

public static void main(final String... args) {
    final Fred fred = new Fred();
    final Integer i = fred.get(Integer.class);
}

public interface Bob {
    <T> T get(final Class<T> type);
}

public static class Fred<Q> implements Bob {
    @Override
    public <T> T get(final Class<T> type) {
        return type.cast(null);
    }
}

But this does:

public static void main(final String... args) {
    final Fred<?> fred = new Fred();
    final Integer i = fred.get(Integer.class);
}

public interface Bob {
    <T> T get(final Class<T> type);
}

public static class Fred<Q> implements Bob {
    @Override
    public <T> T get(final Class<T> type) {
        return type.cast(null);
    }
}

And this does:

public static void main(final String... args) {
    final Fred fred = new Fred();
    final Integer i = ((Bob) fred).get(Integer.class);
}

public interface Bob {
    <T> T get(final Class<T> type);
}

public static class Fred<Q> implements Bob {
    @Override
    public <T> T get(final Class<T> type) {
        return type.cast(null);
    }
}

What is going on here?

UPDATE: Thanks to Bob Lee in the comments, I see what is going on. Using a class-level raw type results in the methods of that class also being treated as raw types, even though the type parameters of the class and method are separate. (NB — this does not apply to static methods, only instance methods.)

Post a Comment