Java passing generic class with parameterzied enum as parameter to another generic object

1.6k views Asked by At

I am trying to implement parameterized class in Java with enum as a type parameter. Everything works fine, except, if you look at the code below, there is that anonymous class Car.Creator with parameter K. But of course, instead of K, there should be CarObject<T>, but it's not that easy. If I put CarObject<T> in K's place, then I got syntax error. Could someone explain if something like this is possible and maybe provide with some code sample.

public class CarObject<T extends Enum<T>>
{
  public Map<T, String> values;
  private Class<T> typeClass;

  public CarObject(Class<T> clazz)
  {
    typeClass = clazz;
    values = new EnumMap<T,String>(typeClass);
  }


  public static final Car.Creator<K> Creator = new Car.Creator<K>()
  {
    public K create()
    {
      return new K();
    }


    public K[] newArray(int size)
    {
      return new K[size];
    }
  }
}

I can give you an example from official Android documentation(look at the code in 'Class Overview') where this works perfectly fine. I think there is some magic going on under the hood in Android. I'm trying to do exactly the same thing - implement Parcelable interface. I just made up this example without implements Parcelable and other stuff, because I though maybe it's just a syntax sugar :).

3

There are 3 answers

3
Daniel Pryden On BEST ANSWER

I'm no Android expert, but I'm pretty sure there's nothing magic about how this is happening in Android. I think you're just confused about the relationship between generic type arguments and statics.

Generic type arguments (like T in your example) belong to the instances of the class, not to the class itself.

Static members (like Creator in your example) belong to the class itself, not to the instances of the class.

The fact that Creator is an anonymous inner class implementing a generic interface is a bit of a red herring here. The issue is simply that, regardless of what Creator is, as long as it is static, it can't access the type T.

8
user207421 On

Make the method non-static as per the compiler message, but you have several other major design problems anyway. create() needs a clazz from somewhere, and you can't return generic arrays.

EDIT I don't normally post code solutions but you seem pretty confused.

public class CarObject<T extends Enum<T>>
{

    public Map<T, String> values;
    private Class<T> typeClass;

    public CarObject(Class<T> clazz)
    {
        typeClass = clazz;
        values = new EnumMap<T, String>(typeClass);
    }
    public final Car.Creator<CarObject<T>> Creator = new Car.Creator<CarObject<T>>()
    {

        @Override
        public CarObject<T> create()
        {
            return new CarObject<T>(typeClass);
        }

        @Override
        public CarObject<T>[] newArray(int size)
        {
            return new CarObject[size];
        }
    };
}
3
Bhesh Gurung On

Look at the following statement -

public static final Car.Creator<K> Creator = new Car.Creator<K>() {
    public K create() {
        return new K();
    }
    public K[] newArray(int size) {
        return new K[size];
    }
}; // <------ missing a semicolon here

Looks like you have a generic class Creator defined as static inner class in the class Car. And, here your trying to use it and instantiate it, so can not use K here unless it's a class or an interface defined somewhere.

I think the following example explains what I mean -

// you are not defining a class here so no parameter instead use a real class
public static final List<K> list = new List<K>() { /*....*/ };