Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can Class<V> take multiple bounds on the generic type?

Tags:

java

generics

The following code compiles:

import java.util.ArrayList;

public class ClassTest
{
  private ArrayList<Class<? extends Interface1>> testClass = 
    new ArrayList<Class<? extends Interface1>>();

  private interface Interface1 {}
}

But the following code produces six errors:

import java.util.ArrayList;

public class ClassTest
{
  private ArrayList<Class<? extends Interface1 & Interface2>> testClass = 
    new ArrayList<Class<? extends Interface1 & Interface2>>();

  private interface Interface1 {}
  private interface Interface2 {}
}

Errors:

ClassTest.java:5: > expected
  private ArrayList<Class<? extends Interface1 & Interface2>> testClass = 
                                              ^
ClassTest.java:5: ';' expected
  private ArrayList<Class<? extends Interface1 & Interface2>> testClass = 
                                                           ^
ClassTest.java:5: <identifier> expected
  private ArrayList<Class<? extends Interface1 & Interface2>> testClass = 
                                                                       ^
ClassTest.java:6: > expected
    new ArrayList<Class<? extends Interface1 & Interface2>>();
                                            ^
ClassTest.java:6: '(' or '[' expected
    new ArrayList<Class<? extends Interface1 & Interface2>>();
                                               ^
ClassTest.java:6: illegal start of expression
    new ArrayList<Class<? extends Interface1 & Interface2>>();
                                                            ^

It's pretty clear that the compiler isn't recognizing the & being used for multiple generic bounds on Class. Are you not allowed multiple bounds on the type parameter for Class? What am I supposed to do if I want an ArrayList of Classes that implement both Interface1 and Interface2?

Motivation: The code I'm working on at the moment has a lot of declarations like this:

private static HashMap<String, Class<? extends ApproximativeMode>> approximativeMethod = 
new HashMap<String, Class<? extends ApproximativeMode>>();

They map a string to a class which contains a 'method' for doing a certain calculation. Each separate hashmap uses a different wildcard for the classes (so ApproximativeMode might be replaced with ExactMode for the hashmap containing all of the exact methods).

I've just gone through all of the methods, making them implement a new interface, NamedMethod, which has a method that gets their full, displayed name (e.g. "Linear hydroxyadenine method"). I now want to put all of the hashmaps into an ArrayList so that I can write an iterator that goes over the hashmaps and displays their full names. So I might end up with:

Approximative Methods

von Ahsen et al.

Owen et al.

etc.

Exact Methods

Santalucia et al.

LHM

etc.

etc.

So my declaration of the ArrayList holding all the hashmaps is:

private ArrayList<Hashmap<String, Class<? extends NamedMethod>>> namedMethods;

Of course, none of the hashmaps are actually of that type, but I was hoping that I could add NamedMethod to the wildcard in each one and get an ArrayList of them all. Clearly that isn't possible.

If this isn't clear, let me know and I'll fix it up.

like image 419
John Gowers Avatar asked Oct 02 '13 10:10

John Gowers


1 Answers

Wildcard bounds vs Type parameter bounds:

  • You can't have multiple bounds on wildcards. You can only have them for type parameters.
  • Another difference is, you can have upper and lower bounds for wildcards, but there is no lower bound for type parameter.

So, as per the 1st difference, if you want to have multiple bounds, then you have to use type parameter declared with your class. That means, you have to make the class generic itself. And then the interfaces should be declared separately as top-level interface:

public class ClassTest<T extends Interface1 & Interface2> {
    private ArrayList<Class<T>> testClass = new ArrayList<Class<T>>();    
}

interface Interface1 {}
interface Interface2 {}
like image 157
Rohit Jain Avatar answered Sep 21 '22 21:09

Rohit Jain