2009-11-22 5 views
1

J'ai besoin de la classe Cache qui conserve les paires <TKey key, TValue value>. Et il est souhaitable que TKey peut être n'importe quelle classe qui prend en charge l'interface Serializable et TValue peut être n'importe quelle classe qui prend en charge Serializable et mes propres interfaces ICacheable.Comment utiliser une classe générique (ou une interface) dans une autre classe générique (ou une interface) avec les mêmes paramètres de type de données sans lancer

Il existe une autre classe CacheItem qui conserve la paire <TKey key, TValue value>. Je souhaite que la classe Cache possède la méthode void add(CacheItem cacheItem). Voici mon code:

public class Cache<TKey extends Serializable, 
    TValue extends Serializable & ICacheable > 
{ 
private Map<TKey, TValue> cacheStore = 
    Collections.synchronizedMap(new HashMap<TKey, TValue>()); 

public void add(TKey key, TValue value) 
{ 
    cacheStore.put(key, value); 
} 

public void add(CacheItem cacheItem) 
{ 
    TKey key = cacheItem.getKey(); 
    //Do not compiles. Incompatible types. Required: TValue. Found: java.io.Serializable 
    TValue value = (TValue) cacheItem.getValue(); 
    //I need to cast to (TValue) here to compile 
    //but it gets the Unchecked cast: 'java.io.Serializable' to 'TValue' 
    add(key, value); 
} 
} 

Dans un autre fichier:

public class CacheItem<TKey extends Serializable, 
    TValue extends Serializable & ICacheable> 
{ 
TKey key; 
TValue value; 

public TValue getValue() 
{ 
    return value; 
} 

public TKey getKey() 
{ 
    return key; 
} 
} 

est-ce que je pouvais faire pour éviter la coulée?

+0

@Sergey J'édité votre code, pour formater le code. C'est beaucoup plus facile à lire et à comprendre :-) J'espère que cela ne vous dérange pas :-) – KLE

+0

KLE, je suis tout à fait d'accord, après avoir édité le code est beaucoup plus facile à lire. – Sergey

+0

Il n'est pas nécessaire d'utiliser I pour les interfaces. le je n'ajoute rien d'utile - personne ne devrait s'en soucier s'il s'agit d'une interface ou non. Il serait particulièrement nul si, pour une raison quelconque, il devait changer à une classe abstraite à une date ultérieure puisque maintenant le nom serait faux (vous ajouteriez probablement une classe abstraite à la place, mais le fait est que vous n'ajoutez rien en Je suis là). – TofuBeer

Répondre

2

rendre votre signature de la méthode add comme ceci:

public void add(CacheItem<TKey, TValue> cacheItem) 
+0

Ce fut une réponse très utile! Le problème s'est dissout immédiatement. Merci beaucoup à Bozho! – Sergey

1

D'abord, vous pouvez faire ICacheable étend Serializable, ce qui simplifierait votre code.


Pourriez-vous essayer de paramètre de paramétrer la méthode add?

public class Cache<TKey extends Serializable, 
    TValue extends Serializable & ICacheable > 
{ 
... 
public void add(CacheItem<TKey, TValue> cacheItem) 
{ 
    TKey key = cacheItem.getKey(); 
    TValue value = cacheItem.getValue(); 
    add(key, value); 
} 
} 

Parce que CacheItem est une classe paramétrés, la plupart des références à elle doit utiliser les paramètres. Sinon, il a encore des types non résolus, et vous êtes confronté à casts.

+1

"étendre", pas "mettre en œuvre" – Bozho

+0

@Bozho Merci pour le bon détail. – KLE

+0

KLE, Merci pour votre commentaire. Cela efface pourquoi j'ai besoin d'écrire CacheItem et pas simplement CacheItem. – Sergey

2
public void add(CacheItem<TKey, TValue> cacheItem) { 
    TKey key = cacheItem.getKey(); 
    TValue value = cacheItem.getValue(); 
    add(key, value); 
} 
2

Vous utilisez le type brut sur CacheItem. Essayez cette signature:

public void add(CacheItem<TKey, TValue> cacheItem) 

Cela nécessitera que le CacheItem ait les mêmes paramètres génériques que le cache.

+0

Yishai, votre commentaire efface le problème pour moi. Merci d'avoir répondu. – Sergey

0

Je pense que vous devriez changer votre classe comme ci-dessous

public class Cache<TKey extends Serializable, 
    TValue extends Serializable & ICacheable > 
{ 
private Map<Serializable, Serializable> cacheStore = 
    Collections.synchronizedMap(new HashMap<Serializable, Serializable>()); 

public void add(Serializable key, Serializable value) 
{ 
    cacheStore.put(key, value); 
} 

@SuppressWarnings("unchecked") 
public void add(CacheItem cacheItem) 
{ 
    Serializable key = cacheItem.getKey(); 
    //Do not compiles. Incompatible types. Required: TValue. Found: java.io.Serializable 
    Serializable value = cacheItem.getValue(); 
    //I need to cast to (TValue) here to compile 
    //but it gets the Unchecked cast: 'java.io.Serializable' to 'TValue' 
    add(key, value); 
} 

} 
+0

DKSRathore, merci pour votre réponse, mais c'est un peu pas ce que je veux vraiment. En réalité j'utiliserais la méthode value.GetBytesUsed() de l'interface ICacheable que cette variable implémente: TValue value = cacheItem.getValue(); int octets = valeur.GetBytesUsed(); Mais je dois convertir votre code: Serializable value = cacheItem.getValue(); int octets = (valeur (ICacheable)) .GetBytesUsed(); Je veux éviter de lancer partout où c'est possible. – Sergey

Questions connexes