Java: nested recursive generics
I have a set of classes that extend some basic entities Classes in this collection can also extend each other to create a nested hierarchy
My goal is to make all classes have access to the methods that create their own new instances I want to implement this method in my base entity so that all extension classes inherit this method
Here are three sample classes defined for my schema:
BaseEntity. java
public abstract class BaseEntity<E extends BaseEntity> { Class<E> clazz; public BaseEntity(Class<E> clazz) { this.clazz = clazz; } public E getNewInstance() throws illegalaccessexception,InstantiationException { return clazz.newInstance(); } }
Collection. java
public class Collection<E extends Collection> extends BaseEntity<E> { public Collection() { super(Collection.class); // compiler error: BaseEntity (java.lang.Class<E>) in BaseEntity cannot be applied to // (java.lang.Class<Collection>) } public Collection(Class<E> clazz) { super(clazz); } }
Document. java
public class Document extends Collection<Document> { public Document() { super(Document.class); } }
With this setting, I hope to achieve such things:
Collection c = new Collection(); c = c.getNewInstance(); // compiler error Document d = new Document(); d = d.getNewInstance(); Collection cd = new Document(); cd = cd.getNewInstance(); // compiler error
Note, however, that collection There is a compiler error in the default constructor of Java I'm not sure why this is the case. I think it will also lead to compiler errors in the example main method What did I do wrong and how to solve this problem?
Please note that this is a human example of a larger problem I am trying to solve I know the implementation itself looks silly
Solution
Collection and lt, e... > are generic types, but your collection C is the original type This means that all its methods will be treated as primitive types, which means that they will return any generic type
Your base class is declared as baseentity < e extends baseentity >, which means that in this method:
E getNewInstance()
Erase yes
BaseEntity getNewInstance();
This means that c.getnewinstance () returns a baseentity instead of a collection, which is the source of compilation errors
Documentation, on the other hand, is not a generic class This means that erasure does not matter at compile time (for these purposes), and getnewinstance () returns the type represented by E, in this case document Therefore, the return type of d.getnewinstance () is document, so this line compiles normally
By the way: whenever you have recursive generics, you should ensure that generics are considered in recursion For example, in this line:
BaseEntity<E extends BaseEntity>
You have defined baseentity as a generic class – but then immediately ignore its generics in the e extension baseentity That line should be:
BaseEntity<E extends BaseEntity<E>>