Java define Generic Class param with a const or static method - java

I'd like to improve my code especially my way to use Generic classes.
In my project I have about 30 classes like folowing :
GenericEntity<T extends Serializable>{
protected T id;
public T getId(){ return id;};
...
}
public class A extends GenericEntity<Integer>{
...
}
public interface IService<T extends GenericEntity, T extends Serializable>{
...
}
public class AService extends IService<A,Integer>{
...
}
I would like to specify the class of my entity Id only one time instead of one in GenericEntity and one in Service like that.
public class A extends GenericEntity<getIdType()>{
public final static Class getIdType(){
return Integer.class;
}
}
public class AService extends IService<A,A.getIdType()>{
...
}
I'm aware it doesn't work like that but I'm hoping there is a way to do it.
Thanks for your help.

Instead of:
class GenericEntity<T extends Serializable>{
protected T id;
public T getId(){ return id;};
}
// THESE ARE UNNECESSARY as far as I can tell
class A extends GenericEntity<Integer>{ }
class B extends GenericEntity<Long>{ }
// where U matches the generic type of GenericEntity<?>
interface IService<T extends GenericEntity<?>, U extends Serializable>{ }
class AService extends IService<A, Integer>{ }
class BService extends IService<B, Long>{ }
You could do this:
class GenericEntity<T extends Serializable> {
protected T id;
public T getIdFromEntity() { return id; }
}
// 'IService' can/should only know of 'id' as some type that extends 'Serializeable'
// So if something implements 'IService' then everything knows it will have
// a method with the signature 'T getGenericEntity(Serializable id);'
interface IService<T extends GenericEntity<?>> {
public T getGenericEntity(Serializable id);
}
// 'AService' knows that 'id' will be an 'Integer'
class AService implements IService<GenericEntity<Integer>> {
Map<Serializable, GenericEntity<Integer>> entityMap = new HashMap<>();
void someMethod() {
GenericEntity<Integer> entity = this.getGenericEntity(Integer.valueOf(1));
Integer i1 = entity.getIdFromEntity();
// ... do stuff
}
// even though 'AService' knows that 'id' will be an 'Integer'
// the 'IService' interface defines this as taking a 'Serializable'
// so it must keep that method signature.
#Override public GenericEntity<Integer> getGenericEntity(Serializable id) {
return entityMap.get(id);
}
}
class BService implements IService<GenericEntity<Long>> {
#Override public GenericEntity<Long> getGenericEntity(Serializable id) { return null; }
// ... similar to AService ...
}
This would cut out all your excess class X extends GenericEntity<SOME_TYPE> classes.
You would only need the one generic GenericEntity<T extends Serializable> and the one interface IService<T extends GenericEntity<?>>. Also, since they aren't generic AService and BService know the actual type that extends Serializeable (Integer and Long), so they don't need the extra info passed to them in generics.
Since IService is generic for any T extends GenericEntity<?> it shouldn't know a concrete type for genericEntity.getId() (and you probably shouldn't want it to). Also you should avoid making it concrete because it's an Interface.
The type of id as far as IService cares is Serializable, since IService<GenericEntity<?>> implies that the wildcard ? extends Serializeable since class GenericEntity<T extends Serializeable> requires it to.

Related

How to make method generic when using inheritance in Java?

I have class Employee and 3 classes that extends Employee class.
I also have EmployeeService interface where i want to have only one save method to handle saving each type of Employee. So i assumed that it could be solved using generics.
This is what i tried in EmployeeService interface:
public interface EmployeeService {
<SubRequestT extends Employee>EmployeeResponse save(SubRequestT requestT);
}
And class that provide implementation:
#Service
public class EmployeeServiceImpl implements EmployeeService {
// So here in argument i want to have to put any kind of Employee, for example:
#Override
public EmployeeResponse save(OfficeEmployee requestT) {
// Logic for saving employee
return null;
}
}
But when i changed from Employee type to any other, for example OfficeEmployee who is extending from Employee, complier is giving me an error. What is best way to solve this?
With "method generics" I (me & compiler) also struggle, but with "type generics" we can do that!
Assuming:
class Foo {/*...*/}
class Bar extends Foo {}
class Baz extends Foo {}
// extending your question to two generic parameters:
class FooResult {}
class BarResult extends FooResult {}
class BazResult extends FooResult {}
When we define our interface like:
interface FooI<I extends Foo, R extends FooResult> { //or with even more (fixed size) "generic parameters"
R save(I request);
}
We can override it like:
class BarImpl implements FooI<Bar, BarResult> {
#Override
public BarResult save(Bar bar) {
// ...
return ...;
}
}
class BazImpl implements FooI<Baz, BazResult> {
#Override
public BazResult save(Baz baz) {
// ...
return ...;
}
}

Relation between generics type in Java

Please, consider my code:
interface AInterface {}
interface BInterface extends AInterface {}
class AClass implements AInterface { }
class BClass extends AClass implements BInterface {}
class Descriptor<S extends AClass, T extends AInterface> {
private Class<S> classClass;
private Class<T> interfaceClass;
public Descriptor(Class<S> classClass, Class<T> interfaceClass) {
this.classClass = classClass;
this.interfaceClass = interfaceClass;
}
}
class Foo {
public void test() {
Descriptor<AClass, BInterface> descriptor =
new Descriptor<>(AClass.class, BInterface.class);//LINE X
}
}
So, I have two interfaces and two classes that implement them. And I have a descriptor to which I must add two classes - the class of the interface and class of the implementation. The question is how to add relation restrict between them. I mean, that at LINE X I must get compilation error, because AClass doesn't implement BInterface. How to do it?
I do not think this is possible. Enforcing multiple type bounds is possible when all of them but the first one (optionally) are interfaces, but I'm unaware of any trick allowing to do it for multiple classes. Here's how it works for interfaces:
public class Bar {}
public class Baz extends Bar {}
public class Foo1<T extends Bar & Serializable> {} // compiles
public class Foo2<T extends Serializable & Bar> {} // doesn't compile
public class Foo2<T extends Bar & Baz> {} // doesn't compile
public class Foo3<T extends Serializable & Closeable> {} // compiles
public class Foo4<T extends Serializable & Closeable & Runnable> {} // compiles
What's your real use case? Perhaps there's a way to approach the problem differently.

Extending a generic implementer class

I have a DAO object that I'd normally extend with the entity class name like so:
public class DAO<T> {
private final Class<T> clazz;
public DAO(Class<T> clazz {
this.clazz = clazz;
}
}
public class EntityDAO extends DAO<Entity> {
public EntityDAO() {
super(Entity.class);
}
}
However, I have some abstract entities that I would like to create an abstract DAO that gets implemented into a concrete class later on:
public class DAO<T> {
private final Class<T> clazz;
public DAO(Class<T> clazz {
this.clazz = clazz;
}
}
public abstract class AbstractEntityDAO extends DAO<T extends AbstractEntity> {
public AbstractEntityDAO () {
super(AbstractEntity.class);
}
}
public abstract class EntityDAO extends AbstractEntityDAO <Entity> {
public EntityDAO() {
super(Entity.class);
}
}
But this doesn't work as the AbstractEntityDAO complains about an unexpected bound and it cannot resolve T. Is it possible to do this? And if so, how is it written?
This is using Java 1.7
Put the generic type definition on AbstractEntityDAO:
public abstract class AbstractEntityDAO<T extends AbstractEntity> extends DAO<T> {
...
}
With your current code AbstractEntityDAO <Entity> should make the compiler complain about AbstractEntityDAO not having generic paremeters.
Besides that your AbstractEntityDAO() constructor needs to accept a Class parameter as well. However, you don't need to pass the class as a parameter at all if you always use instances of classes with concrete types. Using reflection a class can determine the type of T if there is a concrete definition as in EntityDAO. The built-in reflection utilities provide no easy way to do this but fortunately you only need a little additional code to provide one, have a look here: http://www.artima.com/weblogs/viewpost.jsp?thread=208860
That's basically what we're doing as well. Here's a rough rundown of our approach:
abstract class BaseDAO<T> {
Class<?> entityClass;
BaseDAO() {
//this is based on the link I posted above but basically uses the actual concrete class
//(subclass determined by getClass() ) to extract the generic types and
//since we only have one we get the first one from the returned list
entityClass = ReflectionHelper.getTypes(getClass(), BaseDAO.class).get(0);
}
public T getEntity(Object id) {
...
}
}
abstract class TranslatableDAO<T extends TranslatableEntity> extends BaseDAO<T> {
...
}
//Users are not translatable
class UserDAO extends BaseDAO<User> {
...
}
//Products are translatable, i.e. Product extends TranslatableEntity
class ProductDAO extends TranslatableDAO<Product> {
...
}

Generic type parameter which implements generic interace

In a Java application, I'd like to use a generic type parameter which implements an interface which uses a generic parameter itself.
public interface SuperInterface<T> { ... }
public interface MyInterface extends SuperInterface<MyClass> { ... }
public class Worker<T extends SuperInterface<U>> extends SuperWorker<String, Boolean> {
}
However, the class declaration won't work like that. T should be of type MyInterface (or any other interface which implements the SuperInterface) and U should be of type MyClass (or any other class according to the interface).
You have to declare all of the type parameters at the top level. It's annoying, but that's how it is.
public class Worker<U extends MyClass, T extends SuperInterface<U>> { ...
The order of the parameters doesn't matter; you can also do Worker<T extends..., U extends...>. All that matters is that each is declared at the top level of the nested generics.
Here's a complete class:
public class MyClass {
public interface SuperInterface<T>{}
public interface MyInterface extends SuperInterface<MyClass> {}
public class Worker<U extends MyClass, T extends SuperInterface<U>> {}
public void compileTest() {
// just to make sure the declaration compiles
Worker<MyClass, MyInterface> worker = null;
}
}

need trick with object creator

This is my code:
public interface InterfaceA<J>{
// …
}
public interface InterfaceB extends InterfaceA<String> {
// …
}
public interface InterfaceC extends InterfaceA<Long>{
// …
}
public class Creator<J, I extends InterfaceA<J>> {}
public abstract class Base<J, J1> implements InterfaceA<J> {
protected Creator<J, J1> creator;
protected Base() {
creator=ObjectCreator.createCreator();
}
}
public class Extension1 extends Base<Integer> implements InterfaceB {
// …
}
public class Extension2 extends Base<Double> implements InterfaceC {
// …
}
I want Extension1 to have Creator<Integer, InterfaceB> and Extension2 to have Creator<Double, interfaceC>. See the pattern? Creator<T1, T2> where T1 is the type of immediate parent and T2 is the interface implemented by said class. Is there any way to do this? can anybody tell the code of ObjectCreator.createCreator()?
Right now my code looks like this:
public class ObjectCreator {
public static <J, I extends InterfaceA<J>> Creator<J, I> createCreator() {
return new Creator();
}
}
I got errors all over my code. I'm really confused. What am I missing here?
There's a whole bunch of stuff you missed, a compiling version would look something like this:
package scratch;
interface InterfaceA<J> {
// …
}
interface InterfaceB extends InterfaceA<String> {
// …
}
interface InterfaceC extends InterfaceA<Long> {
// …
}
class Creator<J, I extends InterfaceA<J>> {
}
abstract class Base<J, I extends InterfaceA<J>> {
protected Creator<J, I> creator;
protected Base(Class<J> jClass, Class<I> iClass) {
creator = ObjectCreator.createCreator(jClass, iClass);
}
}
class Extension1 extends Base<String, InterfaceB> implements InterfaceB {
protected Extension1() {
super(String.class, InterfaceB.class);
}
}
class Extension2 extends Base<Long, InterfaceC> implements InterfaceC {
protected Extension2() {
super(Long.class, InterfaceC.class);
}
}
class ObjectCreator {
public static <J, I extends InterfaceA<J>> Creator<J, I>
createCreator(Class<J> jClass, Class<I> iClass) {
return new Creator();
}
}
In no particular order of importance:
When you have a class with a signature like createCreator() has, you need to pass Class objects as type tokens to it. The Java compiler can't infer the types based on the type of the variable you're assigning the return value to. Besides, you want them there anyway because of type erasure, otherwise you couldn't specialise the Creator based on the given types.
If you have Base<J, I> with two type parameters, extending classes should use both of those type parameters.
Your extension class signatures were odd. You can't have class Extension1 extends Base<Integer, InterfaceA<String>>, because you can't have a Creator<Integer, InterfaceA<String>>. Using explicit type tokens in createCreator() would have forced you to propagate this constraint everywhere it needs to be and made the error less mysterious. You can't really make Base independent of the constraint between the J and I type parameters.

Categories