Java: create an object whose type is a type parameter

I want to write equivalent Java code for C # code.

My C # code is as follows:

public abstract class A<T> where T : A<T>, new() { public static void Process() { Process(new T()); } public static void Process(T t) { // Do Something... } } public class B : A<B> { } public class C : A<C> { } 

The Java equivalent of my code is as follows.

 public abstract class A<T extends A<T>> { public static <T extends A<T>> void process() { process(new T()); // Error: Cannot instantiate the type T } public static <T extends A<T>> void process(T t) { // Do Something... } public class B extends A<B> { } public class C extends A<C> { } } 

Here, the syntax "new ()" in the class declaration causes derived classes to write a default constructor that allows you to call "new T ()" from the base class. In other words, when I use the base class, I am sure that the derived class will have a default constructor, so I can instantiate the derived class object from the base class.

My problem is in Java: I cannot create an instance of a derived class object from a superclass. I get the error "Cannot instantiate the type T" for calling "new T()" . Is there any C # similar way in Java or should I use something like a prototype and cloning pattern?

+7
source share
6 answers

Java does not support reified generics , so there is no equivalent to " new T(); ". The way I'm working on this is to use reflection against a type token. A type marker indicates what a generic type is.

 public abstract class A<T> { private Class<T> typeToken; // constructor public A() { typeToken = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; } } 

Then use reflection to instantiate the class. It is ugly, but it does its job.

+5
source

You can find some explanation of the difference between generics in C # and Java from this li nk - comparing java and C # generics .

Java generators are a fully compiled construct. You cannot do anything with parameters like generic, which in any case rely on runtime information. It includes:

  • Creating instances of the generic type Parameters.
  • Creating arrays of the general type Parameters.
  • A runtime class request is a generic type parameter.
  • Using instanceof with the generic type Parameters.

You can get around this limitation with java.lang.reflect namepace. For example, consider this stackoverflow question: Genercs and Class.forName ()

+2
source

Also, beware of this if you are using generics.

 T[] someArray = new T[]; 

This is one reason to prefer ArrayList for arrays. The cause of the problem is repeatability and type erasure.

0
source

Just use the standard bog Abstract Factory template. Then you get additional benefits that you do not bind to a specific type, the implementation type should not have a specific constructor, an instance can have some parameterization, instances can be cached, etc. Etc.

For love of God, do not use reflection.

0
source

In addition to other comments, I suggest not using generics. They are not needed - they are still deleted at compile time, and if you do not know them well, you will try to get them to do what they cannot.

Once your class is working correctly, add back. Your IDE at this point will give you a lot of useful and understandable tips, and generics will warn you when you use objects of the wrong class.

It seems to me, it seems to me that this class will not need generics at all. (I don’t know what else this class can do, and I don’t understand the use of static methods - they will never have access to information about a particular type of instance.)

0
source

This is actually not a problem in Java. Idiom goes class

  public static <T extends A<T>> T process(Class<T> clazz) { T o = clazz.newInstance(); process( o ); return o; } X x = process(X.class); // not too verbose 

I added a return value to illustrate the general case.

0
source

All Articles