-1

There's already too many post here suggesting doing:

class Foo<T>{
    Class<T> type;
    public Foo(Class<T> type){
        this.type = type;
    }
    // then using newInstance method creating the instance
}

The problem with this approach is that this is not the java that is creating the instance, this is the developer that is forced to pass type into the constructor of the Foo class. So let's say I need a parameterless constructor, is Java still capable of creating the instance?

For example in C# we got the Activator type which we can use like this:

Object obj = Activator.CreateInstance<T>();

so if I have the below class in Java and I can't follow the first solution, what is an alternative approach that is also similar to the C# solution:

class Foo<T>(){
   public Foo(){
      if T is of Type X Then Do Y
   }
}
Ricky
  • 11
  • 3
  • 2
    Your question suggests you already know the answer. Dima is right. Due to type erasure it is impossible in Java to do anything based on the type of `T` at runtime. The only way to get around this is to pass a `Class` object to the constructor, but this is incompatible with having a parameterless constructor. Java generics are nowhere near as powerful as C# generics. That's just the way it is. – Paul Boddington Jan 04 '15 at 19:09
  • @pbabcdefp: I thought it was impossible to create types at runtime in C# too, but a couple of years back I felt like I had to do it and I found a solution (have the project in my website) so it means that there must a be way for creating the instance of T like that in Java too. I can't accept impossible as an answer I take it as we don't know the answer yet. – Ricky Jan 04 '15 at 19:17
  • possible duplicate of [Create instance of generic type in Java?](http://stackoverflow.com/questions/75175/create-instance-of-generic-type-in-java) – Radiodef Jan 04 '15 at 19:41
  • @Ricky "I can't accept impossible as an answer I take it as we don't know the answer yet." You must be a physicist :) – Dima Jan 04 '15 at 19:51
  • @Radiodef: You are pretty smart (no offence though) – Ricky Jan 04 '15 at 19:56
  • 1
    @Ricky Java Generics were added to the language (they weren't included in Java before 1.5) and at run-time they are [erased](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html). They are a compile time type safety check. From the linked Type Erasure documentation *Type erasure ensures that no new classes are created for parameterized types; consequently, generics incur no runtime overhead.* – Elliott Frisch Jan 05 '15 at 07:00

3 Answers3

1

No, you cannot do this. Generic parameters are compile-time only, they are completely erased and become unavailable at runtime. Also note, that whether you do Activator.CreateInstance<Foo>() (if it was possible) or Activator.CreateInstance(Foo.class), you are actually passing the same exact information to your CreateInstance method, the difference is purely syntactical.

Dima
  • 33,157
  • 5
  • 34
  • 54
  • Not exactly Dima, we are not passing the exact same info as the CreateInstance is not the same as the CreateInstance(T args) – Ricky Jan 04 '15 at 19:01
  • Yes, it is, and yes, you are. (I guess, you might have some reason to believe otherwise, but until you bother to actually state it, this is the only answer I can give you). – Dima Jan 04 '15 at 19:02
  • Actually T represent the type and in your example it actually has to be Foo.GetType() (T does not have GetType method) so we use typeof(Foo), so to be very exact generic CreateInstance is not exactly the same as the one which is not generic. but these don't exist in Java, so I'm looking for a solution – Ricky Jan 04 '15 at 19:07
  • `Foo.class` **is** `Foo.GetType`, it's just called differently in java. Once again, semantically, there is no difference between `create()` and `create(T.class)`, it is just different syntax for expressing the same thing. – Dima Jan 04 '15 at 19:49
0

It is possible, if you really need to do this.

For example, some dependency injection frameworks use Instance<T> fields for resolve and/or create dependencies in runtime.

You can get Class<T> object by classic reflection call:

Class<T> cls = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

Check this answer for code snippet https://stackoverflow.com/a/3942033/2892277

But (as also mentioned by that answer), it is not a good practice.

Community
  • 1
  • 1
Nikolay
  • 1,885
  • 16
  • 23
0

If the developer creates a subclass of Foo, then you can recover T using something like TypeTools. Ex:

public class StringFoo extends Foo<String>{}

Class<?> t = TypeResolver.resolveRawArgument(Foo.class, StringFoo.class);
assert t == String.class;

If the user does not subclass Foo and merely instantiates it, the value of T cannot be recovered at runtime.

Jonathan
  • 5,298
  • 33
  • 46