简体   繁体   中英

How to use generic class (or interface) in another generic class (or interface) with the same data type parameters without casting

I need the Cache class that keep the <TKey key, TValue value> pairs. And it is desirable that TKey can be any class that supports Serializable interface and TValue can be any class that supports Serializable and my own ICacheable interfaces.

There is another CacheItem class that keeps <TKey key, TValue value> pair. I want the Cache class has the void add(CacheItem cacheItem) method. Here is my 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);
 }
}

In another file:

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

 public TValue getValue()
 {
  return value;
 }

 public TKey getKey()
 {
  return key;
 }
}

Is there anything I could do to avoid casting?

使您的add方法签名如下所示:

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

You are using the raw type on CacheItem. Try this signature:

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

That will require that the CacheItem have the same generic parameters as the Cache.

First, you could make ICacheable extends Serializable , that would simplify your code.


Could you try to parameterize the method add's parameter ?

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);
 }
}

Because CacheItem is a parameterized class, most references to it should use the parameters. Otherwise, it still has unresolved types, and you are confronted to casts .

I think you should change your class like below

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);
 }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM