In Java 6

Class<? extends ArrayList<?>> a = ArrayList.class;

gives and error, but

Class<? extends ArrayList<?>> b = (Class<? extends ArrayList<?>>)ArrayList.class;

gives a warning.

Why is (a) an error? What is it, that Java needs to do in the assignment, if not the cast shown in (b)?

And why isn't ArrayList compatible with ArrayList<?> I know one is "raw" and the other is "generic", but what is it you can do with an ArrayList<?> and not with an ArrayList, or the other way around?

  • and ArrayList<?>.class? Commented May 26, 2014 at 21:47
  • ArrayList<?>.class doesn't compile.
    – Florian F
    Commented May 26, 2014 at 21:50

2 Answers 2


Well, a generic class is by definition not equal to a raw class. What you're trying there hides the issue of instantiation of ArrayLists (the actual lists, not their types).

ArrayList raw = new ArrayList();

will work and will allow any kind of element, objects, primitives, anything. On the other hand,

ArrayList<?> generic = new ArrayList<?>();

won't work since it's unclear, at compile time, what actual elements the list will hold. So, in order to make the list (almost) as broadly usable as the raw one, you could instantiate it like this:

ArrayList<?> generic = new ArrayList<Object>();

(That will only hold actual objects, though, no primitives.)

generic and raw will never be equal type-wise and it won't make sense for them to be equal.

What you can do with generic types instead of raw ones? Well, be safe at compile time. :) The other way around? Use primitives (generic types must inherit from Object which primitives do not).

  • That makes sense, you can add a String to an ArrayList, but not to an ArrayList<?>, because <?> doesn't mean "anything", but means "something you don't know", i.e. potentially a type not compatible with String.
    – Florian F
    Commented May 28, 2014 at 19:05
  • @FlorianF Exactly. In fact, ArrayList<?> a = new ArrayList<String>(); a.add(""); won't even compile. And the problem is not instantiating the list but adding a String to a list of unknown elements. (ArrayList<? super String> a = new ArrayList<String>(); a.add(""); will but that's another matter...)
    – jhr
    Commented May 29, 2014 at 17:49
  • ArrayList<?> generic = new ArrayList<Object>(); What's the purpose of putting Object on the right side? Does it make a difference compared to ArrayList<?> generic = new ArrayList<>();? And can you really add elements to a list like this? generics.add(new Object()) wouldn't compile.
    – parsecer
    Commented May 14, 2019 at 1:31

While it's true that Java's type erasure means that generics are compiled into raw classes, they still mean something at compilation. The whole point of generics is to apply consistent casting at compile time, so it should be no wonder that you can't implicitly cast from Class<ArrayList> to Class<? extends ArrayList<?>> even though they are exactly the same type at runtime.

In other words - you get a compilation error because the whole point of generics in Java is to provide safe implicit "casting" in such cases, and raise a compilation error when there is a generic type mismatch.

  • Yes, but an ArrayList<?> is an ArrayList of anything you like, which is the same as a raw ArrayList. I can't think of any operation that is possible with a Class<ArrayList> but not a Class<ArrayList<?>>.
    – Florian F
    Commented May 27, 2014 at 19:59
  • 1
    Well ya, but the compiler takes it much more literally.
    – sea-rob
    Commented May 27, 2014 at 20:15
  • The whole point of the <?> syntax is to make a distinction between the old collection classes where you need to cast manually to any-type generic collections. If you could cast directly between them you wouldn't need the <?> syntax. This is kind of syntactic salt
    – Idan Arye
    Commented May 27, 2014 at 23:06
  • I will accept the answer that the compiler takes it too literally. I changed my mind on <?>, but I still feel ArrayList<Object> SHOULD be equivalent and exchangeable with ArrayList, since they fill the same contract.
    – Florian F
    Commented May 28, 2014 at 19:01
  • The generic parameter modifies the signature of the methods, so it's not the same contract.
    – Idan Arye
    Commented May 28, 2014 at 19:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.