I have the following generic class:
class Or<A,B>
{
Or (A a) {}
Or (B b) {}
}
Why do I get the following error when I try to compile it:
Or(A) is already defined in Or Or (B b) ^
It seems to me that the two constructors share the same signature although they have different generic type arguments. Why? And how to work around this problem?
Update
I understood the problem now. The compiler needs a way to distinguish the two types. Adding such a constrain would be ok for my use case. So I would like to add another question:
How to specify that the two types A and B may be anything but different?
It seems to me that the two constructors share the same signature although they have different generic type arguments.
They do. The signature is
Or(Object o);
Why?
Because of type erasure implementation of generics in Java: references to generic types are converted to System.Object
in all contexts where they are used; the generic type is known only to the compiler.
And how to work around this problem?
Unfortunately, you cannot easily work around this problem in a constructor. You can replace the overloaded constructors with factory methods, and give different names, say OrWithA
and OrWithB
:
// Hide the constructor
private Or(...) {
...
}
// Publish factory methods
public static <X> Or OrWithA(X a) {
return new Or(...);
}
public static <X> Or OrWithB(X a) {
return new Or(...);
}
This is because A or B can be anything, they can be same also as generics is just for compile time. At runtime, they are lost due to type erasure
They just do. That's the nature of generics; they provide syntatic sugar used only at compile time. There is no way round it.
(Acknowledge question comments) This is called type erasure: see http://en.wikipedia.org/wiki/Type_erasure
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With