Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java duplicate generic definition

I'm trying to implement a basic class to create, read, update and delete objects. I'm sure I could find a library to do that but I'm doing it myself for educational purposes.

So I made it that everything that get saved are entities and they has an Identifier of a specific type:

interface Entity<T extends Serializable> extends Serializable
{
    T getIdentifier();
}

Entities are serializable and their identifier as well. Then, I have my EntityPersistor which is supposed to save entity from their content (using serialization) and name them from their key. My only implementation of this persistor for now is saving them on the disk. It is using the identifier as the name of the file to save it into.

Here's my entity persistor:

interface EntityPersistor<K extends Serializable, T extends Entity<K>> extends Iterable<T>
{
    void save(T entity);

    void delete(T entity);

    void deleteById(K id);

    T getById(K id);

    boolean contains(K id);

    List<T> loadAll();
}

So, the problem is I have to redefine the type for the key twice when I want to use it. I would like to write:

interface EntityPersistor<T extends Entity<K extends Serializable>> extends Iterable<T>

but it yields a compiler error. So I have to use it that way:

EntityPersistor<String, Product> persistor = new FileEntityPersistor<>();

which is unconvenient.

Is there a workaround or a better way to do that ? I feel like it will make my declaration less readable but the usage is more important.

EDIT:

I forgot to mention that class Product implements Entity<String>

like image 424
Winter Avatar asked Apr 05 '17 15:04

Winter


Video Answer


1 Answers

Normally there would be a way to remove one or the other, but the problem is that you're using both K and T as parameter types.

There's no way to tell the compiler that the parameter of a method should be the "inner" generic type of the object T (The Entity). Therefore, you need two generics:

One for referring to the "inner" generic type of the Entity (K)

And one for the entity itself:Entity<K> (T)

Due to type erasure, Java wouldn't be able to figure out the parameter type K at runtime without your declaration of it.

like image 145
Zircon Avatar answered Sep 28 '22 09:09

Zircon