1

代码

  interface BaseIntr<T>{
      void saveSwiftMsg(Collection<String> headers) throws Exception;
  }

 class Impl implements BaseIntr{
       public void saveSwiftMsg(Collection<String> headers) throws Exception { }     
  }

代码的编辑版本:

  interface BaseIntr<T>{
     T process(T t);
     void saveSwiftMsg(Collection<String> headers)      throws Exception;
  }

  class Impl implements BaseIntr{
     public void saveSwiftMsg(Collection<String> headers) throws Exception {    }
    @Override
    public Object process(Object t) {       return t;   }   
  }

工作环境

Java 版本:1.7.0_04,供应商:甲骨文公司

默认语言环境:en_IN,平台编码:Cp1252

操作系统名称:“windows 7”,版本:“6.1”,arch:“amd64”,家族:“windows”

java 编译器抛出以下异常。但是如果我从 BaseIntr 中删除 < T >,它就可以正常工作。

javac gen\GenericsTest.java
gen\GenericsTest.java:18: error: Impl is not abstract and does not override abstract     method saveSwiftMsg(Collection) in BaseIntr
 class Impl implements BaseIntr{
 ^
 gen\GenericsTest.java:20: error: name clash: saveSwiftMsg(Collection<String>) in Impl and saveSwiftMsg(Collection<String>) in BaseIntr have the same erasure, yet neither overrides the other
 public void saveSwiftMsg(Collection<String> headers) throws Exception {
                ^
2 errors
4

3 回答 3

3

您的接口在实现时使用类型参数化,T您必须像这样指定它的类型:

class Impl implements BaseIntr<String>{
}

也就是说,如果你想为String. 但是您可以将参数委托给实现类:

class Impl<T> implements BaseIntr<T>{
}

然后,您需要在实例化类时指定类型。

于 2013-03-08T12:27:00.523 回答
2

如果您使用泛型类型而不指定其类型参数 ( implements BaseIntr),则使用原始类型。这些由 Java 语言规范定义如下:

为了方便与非通用遗留代码的接口,可以使用参数化类型(§4.5)的擦除(§4.6)或元素类型为参数化类型的数组类型(§10.1)的擦除作为类型. 这种类型称为原始类型。

更准确地说,原始类型被定义为以下之一:

  • 通过采用泛型类型声明的名称而不附带类型参数列表形成的引用类型。

未从其超类或超接口继承的原始类型 C 的构造函数(第 8.8 节)、实例方法(第 8.4 节、第 9.4 节)或非静态字段(第 8.3 节)的类型是对应的原始类型在对应于 C 的泛型声明中擦除其类型。

即继承的方法有签名

saveSwiftMsg(Collection headers) throws Exception 

要覆盖,覆盖方法必须与继承的方法具有相同的签名。它没有,导致编译错误。

我强烈建议仅将原始类型用于其预期目的(与遗留代码交互),并启用(并修复)相应的编译器警告。

就此而言,规范也是如此:

仅允许使用原始类型作为对遗留代码兼容性的让步。强烈反对在将泛型引入 Java 编程语言之后编写的代码中使用原始类型。Java 编程语言的未来版本可能不允许使用原始类型。

为了确保始终标记可能违反类型规则的行为,对原始类型成员的某些访问将导致编译时未经检查的警告。访问原始类型的成员或构造函数时编译时未检查警告的规则如下:

  • 在对字段赋值时:如果左侧操作数的类型是原始类型,则如果擦除更改了字段的类型,则会出现编译时未经检查的警告。

  • 在调用方法或构造函数时:如果要搜索的类或接口的类型(第 15.12.1 节)是原始类型,则如果擦除更改了方法的任何形式参数类型,则会出现编译时未经检查的警告或构造函数。

您应该注意编译器警告,并指定您实现的接口的类型参数。

于 2013-03-08T12:42:01.560 回答
1

您还需要在子类中指定

class Impl implements BaseIntr<T>{
       public void saveSwiftMsg(Collection<String> headers) throws Exception { }     
  }

实际上你需要指定类型。这很好

interface BaseIntr<String>{
      void saveSwiftMsg(Collection<String> headers) throws Exception;
  }

 class Impl implements BaseIntr<String>{
           public void saveSwiftMsg(Collection<String> headers) throws Exception { }     
      }
于 2013-03-08T12:25:19.657 回答