views:

221

answers:

3

There are methods like these which require Class literals as argument.

Collection<EmpInfo> emps =  
  SomeSqlUtil.select(  
  EmpInfo.class,  
  "select * from emps");

or

GWT.create(Razmataz.class);

The problem presents itself when I need to supply generic specific classes like

EmpInfo<String>
Razmataz<Integer>

The following would be wrong syntax

Collection<EmpInfo<String>> emps =  
  SomeSqlUtil.select(  
  EmpInfo<String>.class,  
  "select * from emps");

or

GWT.create(Razmataz<Integer>.class);

Because you cannot do syntax like

Razmataz<Integer>.class

So, how would I be able to squeeze a class literal out of

EmpInfo<String>
Razmataz<Integer>

so that I could feed them as arguments to methods requiring Class literals?

Further info

Okay, I confess that I am asking this primarily for GWT.

I have a pair of GWT RPC interface Razmataz. (FYI, GWT RPC interface has to be defined in server-client pairs). I plan to use the same interface pair for communicating whether it be String, Integer, Boolean, etc.

GWT.create(Razmataz) for Razmataz<T> complains that, since I did not specify T, GWT compiler treated it as Object. Then GWT compiler would not accept Object class. It needs to be more specific than being an Object.

So, it seems there is no way for me to tell GWT.create what T is because a Class literal is a runtime concept while generics is a compile time concept, Right?

+2  A: 

You can't.

Use an unsafe cast:

Collection<EmpInfo<String>> emps = 
     (Collection<EmpInfo<String>>) someMethod(EmpInfo.class);
Bozho
+5  A: 

Quote from Java Generics and Collections, section 7.2:

Class literals are also restricted; it is not even syntactically valid to supply a type parameter to the type in a class literal. Thus, the following fragment is illegal:

class ClassLiteral {
  public Class<?> k = List<Integer>.class;  // syntax error
}

Indeed, Java's grammar makes a phrase such as the preceding one difficult to parse, and it may trigger a cascade of syntax errors [...]

This syntax problem leads to an irregularity. Everywhere else that a reifiable type is required, you may supply either a raw type (such as List) or a parameterized type with unbounded wildcards (such as List<?>). However, for class tokens, you must supply a raw type; not even unbounded wildcards may appear. Replacing List<Integer> with List<?> in the preceding code leads to a similar error cascade.

So, you have no choice but use only raw types in class tokens, like

GWT.create(Razmataz.class);
Péter Török
+1  A: 

Someone left a short but concise answer here, which I was about to choose as the answer. Unfortunately, that person deleted that answer. If that person would be so kind to re-post that answer for me to select. In the mean time, let me state that answer and how I made use of it.

This is what I should have thought of,


Interface RazmatazString extends Razmataz<String>{}

GWT.create(RazmatazString.class);

Basing on the answer that was deleted,

I would have a basic Razmataz interface pair the does a lot of stuffs, which I am too lazy to repeat.

Abstract class Razmatazer{
.....

  Interface Razmataz<T>{
  // does a lot of RPC stuffs
  }

  Interface RazmatazAsync<T>{
  // does a lot of RPC stuffs
  }

  RazmatazAsync<?> razmatazAsyncRPC;
}

The concept is not to instantiate razmatazAsyncRPC handle at the base class but at the derived class.

For T = String

StringRazmatazer extends Razmatazer{

  Interface RazmatazStringAsync extends RazmatazAsync<String>{}
  Interface RazmatazString extends Razmataz<String>{}

  razmatazAsyncRPC = GWT.create(RazmatazString.class);
}

Otherwise I would have to repeat ~100 lines of code, ~50 each for Razmataz and RazmatazAsync, over various T parametric values of String, Map, Boolean, Integer, etc.

The basic premise for overcoming this hurdle was - I am lazy to repeat those lines.

Blessed Geek