Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generic of Another generic

Tags:

java

generics

dao

I have interface:

interface Identifable<T extends Serializable> {
      T getID();
}

and class that implement this:

public class Cat implements Identifable<Long> {
       public Long getID(){...};
}

everything works fine. so far. Now I want to create GenericDAO, why I cannot create this?:

public abstract GenericDAO<T extends Identifable<S>> {
    T getByID(S id);
}

I can only declare my GenericDAO as this:

public abstract GenericDAO<T extends Identifable, S> {
  T getById(S id);
}

And complete class:

public CatDAO extends GenericDAO<Cat, Long> {
      Cat getById(Long id);
}

But i think it's useless, because I repeat information. I already declared, that Cat implements Identifable< Long >, so why do I must declare GenericDAO< Cat, Long >, not just GenericDAO< Cat > ?

like image 618
Cichy Avatar asked Dec 19 '13 08:12

Cichy


1 Answers

In Java, every generic type must be specified. You can go without specifying any type, but you can't go without specifying just one.

Also, every generic type must be specified in the declaration. If you want to have class GenericDAO<T extends Identifable<U>>, you must add the generic type declaration for U to your class declaration like this (since U is actually a generic type here):

public abstract class GenericDAO<T extends Identifable<U>, U> 

The following is partially off-topic, but you might find it useful.

I've noticed that in your definition of GenericDAO two generic types are not tied to each other. This might not be what you want.

What you have here is a particular case in which the two generics are matching (the Long type in the Cat and CatDAO definitions). Consider having these declarations:

public class Dog implements Identifable<Long>
public class DogDAO extends GenericDao<Dog, String>

This would force you to write the getById method in DogDAO method:

Dog getById(String id);

Your getId method in the Dog returns a Long so your getById method int DogDAO would have to compare Strings to Longs. This is valid thing to do, but it's a bit counter-intuitive. Having a getById method for DogDAO that takes a Long parameter makes more sense, since the Dogs IDs are actually Longs.

If you want to tie the two types together, you can define the GenericDAO class as:

public abstract class GenericDAO<T extends Identifable<S>, S>

You still have to specify the second parameter, but at least the compiler can help you make sure that the types are matching.

like image 61
lucian.pantelimon Avatar answered Oct 12 '22 15:10

lucian.pantelimon