Michael
Michael

Reputation: 33297

How can I convert a method into a generic method?

I have the following method:

public Push getPush() {
    Push plugin;
    String pluginName = PGPluginNames.PUSH;
    if (!isPluginInitialized(pluginName)) {
        plugin = (Push) GWT.create(Push.class);
        plugin.initialize();
        phoneGap.loadPlugin(pluginName, plugin);
        initializedPlugins.add(pluginName);
    }
    else {
        plugin = (Push) phoneGap.getPluginById(pluginName);
    }
    return plugin;
}

I want to transfer this method into a generic method. I tried the following:

public <T extends PhoneGapPlugin> T getType(T t, String pluginName) {
    T plugin = null;
    if (!isPluginInitialized(pluginName)) {
        plugin = (T) GWT.create(t.getClass());
        plugin.initialize();
        phoneGap.loadPlugin(pluginName, plugin);
        initializedPlugins.add(pluginName);
    }
    else {
        plugin = (T) phoneGap.getPluginById(pluginName);
    }
    return plugin;
}

This gives a compiler error.

Only class literals may be used as arguments to GWT.create()

I do not see how I get the class literal of T because I cannot do T.class GWT.create() will throw an error.

Is there any way to fix that?

Edit:

I also tried the following code:

public <T extends PhoneGapPlugin> T getType(Class<T> classLiteral, String pluginName) {
    T plugin = null;
    if (!isPluginInitialized(pluginName)) {
        plugin = (T) GWT.create(classLiteral);
        plugin.initialize();
        phoneGap.loadPlugin(pluginName, plugin);
        initializedPlugins.add(pluginName);
    }
    else {
        plugin = (T) phoneGap.getPluginById(pluginName);
    }
    return plugin;
}

It gives the error:

Only class literals may be used as arguments to GWT.create()

And also the Warning to the cast:

Type safety: Unchecked cast from Object.

Is there a way to prevent this?

Upvotes: 1

Views: 457

Answers (1)

aioobe
aioobe

Reputation: 420991

Constraints of the Java language

You can't get the class literal of T. You need to pass a Class<T> along as argument to your method.

You can compare it with the EnumMap constructor for instance, it needs the class literal, and since it can't deduce it from the type parameter, the constructor looks as follots:

public EnumMap(Class<K> keyType)

Constraints of GWT and the create method

This method is special in the sense that the compiler must be able to determine the requested type at compile time. Had it been a parameter to the method, the compiler can't tell what that argument will be passed to your generic method at runtime. The Javadoc for the method says this explicitly:

The argument to create(Class) must be a class literal because the Production Mode compiler must be able to statically determine the requested type at compile-time. This can be tricky because using a Class variable may appear to work correctly in Development Mode.

In other words, you're out of luck. You can't put anything but class literals, i.e. Push.class as argument to GWT.create.

Upvotes: 4

Related Questions