I've used Java for quite some time now, but some things are still not very clear to me, especially when it comes to generics...
Here's the thing: I have this Search class that I'm using (see here for details), that is constructed like this:
public Search(Class<?> searchClass) {...}
Further more, I have a parametrized generic wrapper around this, as follows:
public class HibernateSearch<E> extends Search implements Serializable {
public HibernateSearch(Class<E> entityClass) {
super(entityClass);
}
// ... omitted for brevity
}
Now, what I need is the following: I'd like to create parametrized class, that contains this class as its field, e.g.
public class BaseSelectorComposer<T> extends SelectorComposer<Window> {
private HibernateSearch<T> searchObject;
...
@Override
public void doAfterCompose(Window comp) throws Exception {
super.doAfterCompose(comp);
this.searchObject =
new HibernateSearchObject<T>( now what...??? );
...
}
...
}
I think that the problem I'm facing is obvious from the given example.
Can someone advise what can be done here, or some alternative ?
Can we have a generic constructor? No, generic constructors are not allowed.
Constructors can be passed as arugments to methods using a method reference, somewhat like a function pointer in C++. This can be a Function type with one argument or a BiFunction type with two arguments, either way its a lambda returning a class of the type it constructs.
A constructor that takes no parameters is called a parameterless constructor. Parameterless constructors are invoked whenever an object is instantiated by using the new operator and no arguments are provided to new .
When we declare an instance of a generic type, the type argument passed to the type parameter must be a reference type. We cannot use primitive data types like int, char.
The easiest way would be to pass the responsibility on to whoever actually instanciates and uses instances of BaseSelectorComposer, i.e.:
public class BaseSelectorComposer<T> extends SelectorComposer<Window> {
private HibernateSearch<T> searchObject;
private final Class<T> theType;
public BaseSelectorComposer(Class<T> token) {
theType = token;
}
...
@Override
public void doAfterCompose(Window comp) throws Exception {
super.doAfterCompose(comp);
this.searchObject = new HibernateSearchObject<T>(theType);
...
}
...
}
If your BaseSelectorComposer is an abstract subclass, which is only ever used like
class IntSelectorComposer extends BaseSelectorComposer<Integer> {
...
}
i.e., as base class for classes, which "bind" the type parameters, there are ways to obtain the type information via reflection (though this is incredibly ugly, since this is not really well-supported in the API IMHO).
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