views:

78

answers:

1

Hi,

I have a class that needs to use a Class<T> parameter (see my previous semi-related question). It is:

public class BaseTable<T extends TableEntry>
{
    protected Class<T> mClass;
    ...

    public BaseTable(int rows, int cols, Class<T> clasz)
    {
        ...
        mClass = clasz;
    }

    public BaseTable(int rows, int cols)
    {
        this(rows, cols, StringTableEntry.class);
        //Does NOT compile:
        //expected [int, int, Class<T>], but got
        //[int, int, Class<blah.blah.StringTableEntry>]
    }
...
}

I am wondering why the constructor (with 2 parameters) does not work, but when I am invoking the exact same thing from an external class, like this:

    mSomeTable = new BaseTable<StringTableEntry>(2, 2, StringTableEntry.class);

It compiles and runs without complaining. Why so, and how to work around this?

Thanks!

+4  A: 

A constructor for a class that has generic type parameters can be used to construct that class with any types (that fit the bounds in the class declaration). So what happens if someone says:

new BaseTable<SomeTypeUnrelatedToStringTableEntry>(rows, cols)

?

As a workaround, use a static factory method:

public static BaseTable<StringTableEntry> newStringTableEntryBaseTable(
    int rows, int cols)
{
    return new BaseTable<StringTableEntry>(rows, cols, StringTableEntry.class);
}

Or you can create a subclass:

class StringTableEntryBaseTable extends BaseTable<StringTableEntry>
{
    StringTableEntryBaseTable(int rows, int cols)
    {
        super(rows, cols, StringTableEntry.class);
    }
}
Laurence Gonsalves
Using a static creation method also means you don't have to specify generic arguments (although you can with `MyType.<ArgType>fn()` syntax if you wish). And you can use a sensible name!
Tom Hawtin - tackline