I can't use inherited class instead of mother class in generics - java

Hi suppose this following simple class:
public class CRUDController<T extends __Entity<T>> {
...
}
And
public class Tag extends __Entity<Tag> {
...
}
And
public class KalaTag extends Tag {
...
}
When I use public class TestController extends CRUDController<Tag> everything is ok but when I use public class TestController extends CRUDController<KalaTag> the following error appears:
Type parameter 'KalaTag' is not within its bound; should extend '__Entity < KalaTag >'
What is my problem?
What did I wrong?
Thank you in advance ;)

CRUDController expects its argument (T) to extend __Entity<T>.
Clearly KalaTag does not do it, as it extends __Entity<Tag>.
Possible solutions:
Make KalaTag extend __Entity<KalaTag> directly
Define Tag as class Tag<T> extends __Entity<T> and then class KalaTag extends Tag<KalaTag>

Another options is to allow CRUDController to work with any __Entity bound by parent type of T.
public class CRUDController<T extends __Entity<? super T> > {
}
Again this really depends on your usage of T in CRUDController and its subclasses.

Related

How to check if a (type variable) Class<T> is implementing the Interface SomeInterface<T extends SomeInterface<T>>?

I'm working with JSON data and converting it into Java POJO class, then I built an interface like this:
public interface DataUtil<T extends DataUtil<T>> {
default T someDefaultFn() { ... };
}
And I used this interface for some POJO data class like:
public MyPoJo extends DataUtil<MyPojo> { ... }
And I get stuck when I to try check the type variable Class<FType> (a FieldType of any fields are declared inside T class) whether FType extends DataUtil<FType extends DataUtil<FType>> or not? I'm also trying to research the java.reflect package but did not find the expected answer. Can anyone help me to resolve this problem or find another design solution for this scenario?

How to use Spring Dependency Injection with class inheritance

I have a parent class called BaseService and I have other services that inherit from BaseService as they all need those methods to do their jobs. As always the methods of the superclass are available inside the subclass... However, when I use #Autowired DI to inject the subclass I am not able to use the methods defined by the parent class, I am only able to use what is defined separately in the subclass. How can I inject the subclass and have it properly instantiate the subclass such that the methods of the parent class are available to me?
Ex. Parent Class
#Service
public class BaseService{
public BooleanExpression combineBools(Predicate predicate, BooleanExpression bool){
BooleanExpression result = runupBool.and(predicate);
return result;
}
}
Ex. Child Class
#Service
public class EqServiceImpl extends BaseService implements EqService{
public EqServiceImpl(){
super();
}
#Override
public Iterable getAllData(Map<String, String> params, Predicate predicate) {
// Some Method Specific to Child Class
}
}
Ex. Controller
#RestController
public class EqController {
#Autowired
EqService eqService
...
}
If I wanted to access the method eqService.combineBools() inside the controller I am unable to. Why is this? How can I fix it?
As DarrenForsythe pointed out I am instantiating with EqService as the type so it would not have all of the methods of the BaseService since it does not extend that class, rather it is the EqServiceImpl that extends that class. Therefore I would need the type to be EqServiceImpl. Without making some other changes #Autowired is not the best choice for DI here.

Creating two generic parameters in an interface

I am trying to create a generic interface for my classes that will satisfy them all. I have created base classes to link them all together but the interface I'm trying to create isn't working like I'd expect it to and I cant find the right words to type into the search to find them.
The interface so far is:
public <T extends SDOBase> T entityToSDO(<? extends BaseEntity> entity, T sdo) throws Exception;
How do I make entity a second generic type?
Try declaring your method this way:
public <T extends SDOBase, E extends BaseEntity> T entityToSDO(E entity, T sdo) throws Exception;
I think you want something more along the lines of:
public interface MyInterface<T extends SDOBase>
{
public T entityToSDO(<? extends BaseEntity> entity, T sdo) throws Exception;
}
You just need
public <T extends SDOBase> T entityToSDO(BaseEntity entity, T sdo) throws Exception;
Anything that is an instance of a subtype of BaseEntity automatically is an instance of BaseEntity.

How do I bind a Generic class?

When I try to mock a Dao using Jukito I get the following exception:
java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
at org.jukito.JukitoModule.addKeyDependency(JukitoModule.java:338)
at org.jukito.JukitoModule.addInjectionPointDependencies(JukitoModule.java:330)
at org.jukito.JukitoModule.addDependencies(JukitoModule.java:313)
The object I try to mock is a ConcreteDao.
public class ConcreteDao extends AbstractDao<MyDomain> {
}
public abstract class AbstractDao<T extends DatastoreObject> {
}
I read several posts on SO about this binding generics but I can't figure out a way to use TypeLiteral for my binding.
This is what I tried:
bind(new TypeLiteral<AbstractDao<MyDomain>>(){}).to(ConcreteDao.class);
You need to bind like this:
bind(new TypeLiteral<AbstractDao<MyDomain>>(){}).to(new TypeLiteral<ConcreteDao<MyDomain>>(){});
This is how you can retrieve the generic class:
class AbstractDao {
protected final Class<T> clazz;
#Inject
public AbstractDao(TypeLiteral<T> type) {
clazz = (Class<T>) type.getRawType();
}
}
Subclasses of AbstractDao will need to pass entity specific TypeLiterals to the parent class (AbstractDao):
class ConcreteDao extends AbstractDao<MyDomain> {
#Inject
public ConcreteDao(TypeLiteral<MyDomain> type) {
super(type);
}
}
Note that you can make your AbstractDao class non-abstract and implement basic CRUD operations, so that you can use it without the need to extend AbstractDao for each entity. You will just need a binding for each entity like this:
bind(new TypeLiteral<GenericDao<User>>(){}).in(Scopes.SINGLETON);
See my blog-post for more information.

java generic wildcards

Currently I'm working on a service interface which retrieves domain objects based on a primary key. However I get the feeling I'm not efficiently using generics.
Base domain objects look as follows:
public interface DomainObject<PK extends Serializable> extends Serializable {
PK getID();
}
My service interface looks as follows:
public interface LoadService<T extends DomainObject<PK>, PK extends Serializable> {
T load(PK ID);
}
This works, however I have to specify the PK type in the service generics, even though the PK type is already known inside T. Is there any way I can get around having to define my PK again in the LoadService interface? Something like:
LoadService<T extends DomainObject<? extends Serializable as PK> { ... }
Help will be greatly appreciated!
There is no way to avoid that because you use PK class at the 'LoadService'. I mean that you can define service like
interface LoadService<T extends DomainObject<?>> {
void store(T data);
}
However, that's not the option if you use PK class because compiler checks that PK type is compatible with the domain object type.
Another option is to remove type parameter from DomainObject, i.e. perform the following:
interface DomainObject extends Serializable {
Serializable getID();
}
Try using multiple bounds for the type parameter, if T both extends DomainObject and implements Serializable:
interface LoadService<T extends DomainObject<T> & Serializable> {
}

Categories

Resources