泛型和继承问题

时间:2011-03-25 22:25:24

标签: java generics inheritance

我有三个班级:

public abstract class fileHandler<Key extends Object, Value extends Object> {
}    

public A extends fileHandler<String, String[]> {
}

public B extends fileHandler<String, String> {
}

现在在我的主要功能中,我做了类似的事情:

fileHandler file= null;
If (<condition>) {
    fileHandler = new A();
} else
    fileHandler = new B():
}

但是这会产生2个编译时错误:

  1. 无法将A转换为fileHandler
  2. 无法将B转换为fileHandler
  3. 如果基类不是通用的,我怎么能摆脱这些错误,因为我没有得到这个错误。

    更新

    我的班级层次结构是:

    1. class fileHandler<Key, Value> { }
    2. class A extends fileHandler<String, String[]> { }
    3. class B extends fileHandler<String, String> { }
    4. 调用函数gen(object of A)
    5. 的C类
    6. 调用函数gen(object of B)的D类。
    7. C和D都来自抽象类E。
    8. 现在我应该如何在C和D和E中定义这些函数:

      我给出了以下内容:

      E:

      public abstract void gen (fileHandler A) throws exception;
      

      C:

      void gen (fileHandler A) throws exception;
      

      d

      void gen (fileHandler A) throws exception;
      

      C,D和E给出错误fileHandler是原始类型。应该参数化泛型类型fileHandler(Key,Value)。

4 个答案:

答案 0 :(得分:3)

当您实例化具有不同类型参数的泛型类型时,这两个实例不是类型兼容的。泛型类型的不同实例化不是类型等效的,因为从另一个类继承的类与该类等效,即使类型参数本身可能通过继承相关也是如此。通用性和多态性是两种不同的语言特征。

您的代码等同于以下内容:

// Java defaults unspecified type arguments to Object.
fileHandler<Object, Object> file;

if (...) {
   // Error: fileHandler<String, String> is not equivalent to fileHandler<Object, Object>
   file = new fileHandler<String, String>();
} else {
   // Error: fileHandler<String, String[]> is not equivalent to fileHandler<Object, Object>
   file = new fileHandler<String, String[]>();
}

如果你真的想要隔离一个独立于用于实例化你的fileHandler类的类型的多态接口,那么我建议你使用一个接口:

interface IFileHandler
{
    // If this interface needs to talk about keys and values, it
    // does so using only java.lang.Object.
}

public class fileHandler<Key extends Object, Value extends Object>
    implements IFileHandler
{
    // ...
}

public class A extends fileHandler<String, String>
{
    // ...
}

public class B extends fileHandler<String, String[]>
{
    // ...
}

IFileHandler file;

if (...) {
    file = new A();
} else {
    file = new B();
}

答案 1 :(得分:1)

问题在于您尝试将实例分配给类名。你应该说

if (condition) {
   file = new A();    
} else {
   file = new B();
}

“file”是这里的引用“fileHandler”是类名。

干杯。

答案 2 :(得分:1)

我没有编译错误...如果我修复了您提供的代码中的所有错误

  class fileHandler<Key, Value> {
    }

  class A extends fileHandler<String, String[]> {
    }

  class B extends fileHandler<String, String> {
    }

然后

fileHandler file= null;
if (/* condition */) 
{
    file = new A();
} 
else
{
    file = new B();
}

答案 3 :(得分:0)

您决定如何修复此警告实际上取决于您要执行的操作以及您希望如何严格限制gen()参数的允许类型。

示例1

非常宽松

abstract class E {
    public abstract void gen(fileHandler<?,?> A) throws Exception;
}

class C extends E {
    @Override
    public void gen(fileHandler<?,?> A) throws Exception {}
}

示例2

Key通用限制为String

abstract class E {
    public abstract void gen(fileHandler<String,?> A) throws Exception;
}

class C extends E {
    @Override
    public void gen(fileHandler<String,?> A) throws Exception {}
}

示例3

您可能想要命名无限制类型,以便您可以参考它。

abstract class E {
    public abstract <Value> void gen(fileHandler<String,Value> A) throws Exception;
}

class C extends E {
    @Override
    public <Value> void gen(fileHandler<String,Value> A) throws Exception {}
}