2

Now and then in my code I find that I can solve a problem by either using a naked generic class or one with wildcards.

I have a design where a class like this:

Class World<T, C> { .... }

definitely in general is making my code cleaner than it would have been without generics.

Yet, sometimes I use

World theWorld;

or sometimes I end up with

World<?, ?> theWorld;

I do this because it seems to be what it takes to make the compiler accept it and my attempts to avoid them lead me to more casting or inheriting complexity.

It looks ugly and smelly to me and yet I cannot justify the added complexity it looks like I need to introduce to avoid it.

What are some cases (if any) that you believe using a naked or wildcarded generic is acceptable idiomatic Java?

pitosalas
  • 10,286
  • 12
  • 72
  • 120

3 Answers3

4

There is a good example (use case) of using <?> in the Wildcards section of the Generics tutorial.

A sort summary: if you want to write a printCollection method which accepts all kinds of Collection you could use Collection<?> as a parameter type. You cannot use Collection<Object> as the parameter type for this purpose because it is not a supertype of all kinds of collections.

Using Collection<?> instead of "pure" Collection in this case is safer because you cannot add items to Collection<?> (except for null) in the printCollection method.

Csaba_H
  • 8,215
  • 1
  • 41
  • 42
  • Ok I think that makes sense... Except I don't follow "You cannot use Collection as the parameter type for this purpose because it is not a supertype of all kinds of collections." I thought it would be... I would have thought that the reason you cannot do that is that a Collection is specifically not the same as a Collection. Whereas, a Collection extends Object> would be logical but that is equivalent to Collection>. Can you confirm? – pitosalas Feb 20 '12 at 21:21
  • Collection> and Collection extends Object> are almost the same. See this answer for the minor differences: http://stackoverflow.com/a/2016382/122442 – Csaba_H Feb 20 '12 at 22:07
3

Any time you could use generics but don't need it in that specific situation. <?> tells the compiler roughly: "I know about generics, but I don't need the type now".

Maybe the type is needed in other situation. E.g. if you have a Set that just stores anything, like a cache, and you just don't care for the type of the elements at all. At other times you do, when you process specific elements.

It smells if you use too loosely bound type parameters (like <?> which is quite loose) but try to determine the type afterwards, e.g. with instanceof or some custom type discriminator. Then something was designed poorly.

Hauke Ingmar Schmidt
  • 11,559
  • 1
  • 42
  • 50
1

The Wildcard also proves as very useful, when you want to store multiple objects, that are a subclass of another class.

For example:

Collection<? extends Shape> myShapes

This Collection now could keep all the objects, that are a subclass of Shape. So you are type-safe when adding any object that is a subclass of Shape. For Example:

myShapes.add(new Rectangle())
myShapes.add(new Triangle())
devsnd
  • 7,382
  • 3
  • 42
  • 50
  • Interesting! I had tried "Collection a;" and found that this was invalid. So use the "?" instead! – pitosalas Feb 20 '12 at 21:18
  • T works only if the class you implemented it in is in itself generic, meaning that the T will be known to the VM as soon as an object of that class has been instanciated. – devsnd Feb 20 '12 at 21:53