11

I stumbled upon a function looking like this:

public void function(Class<?> clazz) {...}

What are the pros/cons of changing the method to:

public <T> void function(Class<T> clazz) {...}

edit: what are the compile time / runtime diff.

Schildmeijer
  • 19,921
  • 11
  • 59
  • 79

4 Answers4

13

Using "?" is the same as "any", whereas "T" means "a specific type". So, compare these interfaces:

public interface StrictClass<T> {
 public T doFunction(Class<T> class);
}

public interface EasyClass<T> {
 public > doFunction(Class<?> class);
}

Now, we can create classes:

public class MyStrictClass implements StrictClass<String> {
  public String doFunction(Class<String> stringClass) {
    //do something here that returns String
  }
}

public class MyEasyClass implements EasyClass<String> {
  public String doFunction(Class<?> anyClass) {
    //do something here that returns String
  }
}

Hope that helps!

hhafez
  • 36,343
  • 33
  • 109
  • 143
Todd R
  • 17,208
  • 8
  • 27
  • 35
11

todd.run is totally right on, but that's only half the answer. There are also use cases for choosing <T> over <?> (or vice versa) that apply when you don't add type parameter to the class that encloses the method. For example, consider the difference between

public <E extends JLabel> boolean add(List<E> j) {
    boolean t = true;
    for (JLabel b : j) {
        if (b instanceof JLabel) {
            t = t && labels.add(b);
        }
    }
    return t;
}

and

public boolean add(List<? extends JLabel> j) {
    boolean t = true;
    for (JLabel b : j) {
        if (b instanceof JLabel) {
            t = t && labels.add(b);
        }
    }
    return t;
}

The first method will actually not compile UNLESS you add an appropriate type parameter to the enclosing class, whereas the second method WILL compile regardless of whether the enclosing class has a type parameter. If you do not use <?>, then you are locally responsible for telling the compiler how to acquire the type that will be filled in by the letter used in its place. You frequently encounter this problem - needing to use ? rather than T - when attempting to write generic methods that use or need "extends" and "super." A better but more elaborate treatment of this issue is on page 18 of Gilad Bracha's Generics Tutorial (PDF). Also see this stack overflow question whose answer illuminates these issues.

Check out this stack overflow link for information about your second question: Java generics - type erasure - when and what happens. While I don't know the answer to your question about the compile time difference between <?> and <T>, I'm pretty sure the answer can be found at this FAQ that erickson mentioned in that post.

Community
  • 1
  • 1
Myer
  • 3,434
  • 1
  • 34
  • 46
  • You can capture the wildcard type in this case: boolean add(List extends JLabel> list) { return addImpl(list); } boolean addImpl(List list) { ... – Tom Hawtin - tackline Mar 30 '09 at 12:03
  • (The example code is a bit odd. You could return after labels.add returns false. – Tom Hawtin - tackline Mar 30 '09 at 12:05
  • This answer doesn't make sense and is not correct. I put the first method in a class without a type parameter (`public class test { List labels = new ArrayList(); // add method here }`) and it compiles fine. – user102008 Aug 31 '11 at 03:38
2

Basically, they are equivalent. You can use the first syntax where you don't need to declare anything of type T.

UPDATE: oh, and T can be used to bind types together: if Class<T> is used in different parts of the function it will refer to the same class, but not Class<?>.

Maurice Perry
  • 31,563
  • 8
  • 67
  • 95
0

A good resource might be this: http://sites.google.com/site/io/effective-java-reloaded The interesting part related to your question starts around the 5th minute. Just in addiction to what previous users said.

Hope that helps :]

Alberto Zaccagni
  • 28,473
  • 10
  • 71
  • 102