【问题标题】:How to use generic class (or interface) in another generic class (or interface) with the same data type parameters without casting如何在另一个具有相同数据类型参数的泛型类(或接口)中使用泛型类(或接口)而不进行强制转换
【发布时间】:2009-11-22 14:30:30
【问题描述】:

我需要保留 <TKey key, TValue value> 对的 Cache 类。并且希望TKey 可以是任何支持Serializable 接口的类,TValue 可以是任何支持Serializable 和我自己的ICacheable 接口的类。

还有另一个CacheItem 类保留<TKey key, TValue value> 对。 我希望 Cache 类具有void add(CacheItem cacheItem) 方法。这是我的代码:

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

在另一个文件中:

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

 public TValue getValue()
 {
  return value;
 }

 public TKey getKey()
 {
  return key;
 }
}

有什么办法可以避免强制转换吗?

【问题讨论】:

  • @Sergey 我编辑了您的代码,以格式化代码。它更容易阅读和理解:-)我希望你不介意:-)
  • KLE,我完全同意,编辑后的代码更容易阅读。
  • 接口不用I。我没有添加任何有用的东西——没有人应该关心它是否是一个接口。如果由于某种原因,它必须在以后更改为抽象类,那将特别糟糕,因为现在名称将是错误的(您可能会添加一个抽象类,但重点是 yiou 没有添加任何东西把我放在那里)。
  • 豆腐啤酒,感谢您的评论。 I 字母来自这里的 C#。但我会考虑您的评论,并会重写我的代码以不在我的接口名称中使用 I 字母。
  • 是的,我认为 COM 是从带有匈牙利符号的 windows 中养成的习惯...... lpsz 之类的东西。当编译器在检查类型方面做得不好时,对 C 来说是有意义的(有点)......但是在“真正的”C 编译器中现在不需要它,而且它确实违背了 OO 语言的目的.很多时候你会改变一些东西的类型,这意味着你要么必须改变名字(如果它是非私有的就不能这样做)或者编码的名字不再意味着什么(这很烦人并且可能很危险)。

标签: java interface parameters casting generics


【解决方案1】:

让你的 add 方法签名看起来像这样:

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

【讨论】:

  • 这是非常有帮助的答案!问题立即解决。非常感谢 Bozho!
【解决方案2】:
    public void add(CacheItem<TKey, TValue> cacheItem) {
    TKey key = cacheItem.getKey();
    TValue value = cacheItem.getValue();
    add(key, value);
}

【讨论】:

    【解决方案3】:

    您在 CacheItem 上使用原始类型。试试这个签名:

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

    这将要求 CacheItem 具有与 Cache 相同的通用参数。

    【讨论】:

    • 一晒,您的评论进一步为我解决了这个问题。感谢您的回答。
    【解决方案4】:

    首先,您可以让ICacheable 扩展Serializable,这样可以简化您的代码。


    你能尝试参数化方法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);
     }
    }
    

    因为 CacheItem 是一个参数化的类,所以对它的大多数引用都应该使用参数。 否则,它仍然有未解析的类型,你会遇到casts

    【讨论】:

    • @Bozho 感谢您提供的详细信息。
    • KLE,感谢您的评论。它清楚了为什么我需要编写 CacheItem 而不仅仅是 CacheItem.
    【解决方案5】:

    我认为你应该像下面这样改变你的班级

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

    【讨论】:

    • DKSRathore,感谢您的回答,但这有点不是我真正想要的。实际上,我会使用该变量实现的 ICacheable 接口的 value.GetBytesUsed() 方法: TValue value = cacheItem.getValue() ; int bytes = value.GetBytesUsed();但我需要在您的代码中进行转换:Serializable value = cacheItem.getValue(); int bytes = ((ICacheable)value).GetBytesUsed();我想尽可能避免投射。
    猜你喜欢
    • 2018-07-23
    • 1970-01-01
    • 2019-07-21
    • 2012-02-27
    • 2016-05-18
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多