1

Is it possible to obtain an instance of Class<SomeGenericClass<SomeType>>?

For example an instance of Class<ArrayList<String>> without instantiating an instance of ArrayList<String>.

 

@SuppressWarnings("unchecked")
public static <T> T castToGeneric(Object objectToCast, T typeInferrenceClass) {
    return (T)objectToCast;
}

// usage

Object someObject = null /* initialised elsewhere */;
List<String> listOfStrings = castToGeneric(someObject, new ArrayList<String>());

// I want to avoid having to create - new ArrayList<String>();

I know this code is ugly and I shouldn't be doing this. But we are where we are...

auser
  • 6,307
  • 13
  • 41
  • 63

4 Answers4

1

If want to instantiating Class<SomeGenericClass<SomeType>>

Class<List<Object>> list = (Class<List<Object>>)(Class<?>)List.class;

Type genericclass = new ArrayList<Object>() {}.getClass().getGenericSuperclass();
Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
  • Please illustrate how do you create "theClass" parameter passed into your method. When T is List? – auser May 16 '12 at 09:56
  • OP specifically asked for a solution **without instantiating** and your first line emits unchecked cast warnings. I kind of think OP is already aware of half-assed solutions and wants a clean one. – Marko Topolnik May 16 '12 at 10:38
  • 2
    There can *never* be a clean solution, due to type erasure. There is not really any such thing as a `Class>`; the best thing you can do is cast a `Class` to it. – Louis Wasserman May 16 '12 at 11:15
  • @LouisWasserman What does this have to do with type erasure? `Class>` is a legitimate type and, for example, the return type of `newInstance` for such a var is `List`. The only issue is how to cast the `List.class` literal to it. – Marko Topolnik May 16 '12 at 16:04
  • 2
    A `Class` is a runtime representation of a type, and at runtime, there are no generic types. Any `Class>` *must* satisfy `listStringClass.equals(List.class)`. See e.g. http://stackoverflow.com/questions/71585/how-to-get-parametrized-class-instance – Louis Wasserman May 16 '12 at 18:25
1

I found this workaround to your problem:

@SuppressWarnings("unchecked")
public static <T> T castToGeneric(Object objectToCast) {
    return (T)objectToCast;
}

// usage

Object someObject = null /* initialised elsewhere */;
Class<ArrayList<String>> listOfStrings = <Class<ArrayList<String>>>castToGeneric(someObject);

so instead of passing type as a parameter, you're passing it as a type-parameter.

dhblah
  • 9,751
  • 12
  • 56
  • 92
0

Since type erasure in Java generic, result of call "getClass" on instance of "List<String>", would lose type argument "String", in another word, it might be impossible to get "Class<List<String>>". But you can do it in Scala:

scala> List("foo", "bar").getClass
res0: java.lang.Class[_ <: List[java.lang.String]] = class scala.collection.immutable.$colon$colon
xnnyygn
  • 731
  • 1
  • 5
  • 7
0

This satisfies your "no-instance" criterion, compiles and runs OK:

Class<ArrayList<String>> c =
    (Class<ArrayList<String>>) Class.forName("java.util.ArrayList");

This works due to type erasure: At runtime, ArrayList<String> is just ArrayList, and further Class<ArrayList<String>> is just Class.

Bohemian
  • 412,405
  • 93
  • 575
  • 722