Reputation: 11559
I want to write the equivalent Java code of a 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>
{
}
Java equivalent of my code looks like this.
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 "new()" syntax in class declaration forces derived classes to write a default constructer which makes possible to call "new T()" from base class. In other words when i am wrting the base class i am sure that the derived class will have a default constructer, so that i can instantiate a derived class object from base class.
My problem in Java is, I cannot instantiate a derived class object from super class. I get "Cannot instantiate the type T"
error for "new T()"
call. Is there any C# similar way in Java or should I use something like prototype pattern and cloning?
Upvotes: 7
Views: 977
Reputation: 45443
Actually this is not a problem in Java. The idiom is passing the 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.
Upvotes: 0
Reputation: 3158
In addition to the other comments, I would suggest not using generics. They are not needed--they get stripped out at compile time anyway--and if you do not know them well you will try to make them do things they cannot.
Once you have your class working properly, then add them back in. Your IDE will, at that point, give you a lot of useful and intelligible advice, and the generics will warn you when you use objects of the wrong class.
It does look possible to me that this class will not need generics at all when finished. (I don't know what else this class may do, and I do not understand the use of the static methods--they will never have access to an individual instance's type information.)
Upvotes: 0
Reputation: 147154
Just use the bog standard Abstract Factory pattern. You then get the additional benefits that you are not tying down to a specific type, the implementation type need not have a specific constructor, the instance can have some parameterisation, instances can be cached, etc., etc.
For the love of god, don't use reflection.
Upvotes: 0
Reputation: 9505
You can find some explanation of the difference between generics in C# and Java from this li nk - comparing java and C# generics.
Java generics are a completely compile-time construct. You cannot do anything with generic type parameters that rely in any way on runtime information. This includes:
You can bypass this restriction with java.lang.reflect
namepsace. For example see this stackoverflow question: Genercs and Class.forName()
Upvotes: 2
Reputation: 4889
Also, beware of this if you are using generics.
T[] someArray = new T[];
This is one reason to prefer ArrayList
to arrays. The reason for the problem lies with reifiability and type erasure.
Upvotes: 0
Reputation: 2785
Java doesn't support reified generics, so there is no equivalent to "new T();
". The way I work around this is to use reflection against a type token. The type token indicates what the 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's ugly, but it gets the job done.
Upvotes: 5