2013-03-08 63 views
1

代码问题与泛型

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

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

EDITED版本的代码:

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”,拱: “AMD64”,家人: “窗口”

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 
+1

你为什么使界面通用?你不要在任何地方使用'T' ... – assylias 2013-03-08 12:25:30

+0

确保Collection类是相同的,以及方法名称是相同的(一个字符可以用不同的语言编写)。 编辑:这很奇怪,它不能缺少@Override? 此外,尝试使用某些参数化“实现BaseIntr”,例如执行BaseIntr dkateros 2013-03-08 12:27:10

+0

@assylias,是否使用T是强制性的,尽管没有使用,但它几乎没有任何意义。 – 2013-03-08 12:30:16

回答

2

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

为了促进与非通用旧代码交互,能够为一种类型使用擦除(§4.6)的参数化类型的(§4.5)或擦除其元素类型为参数化类型的数组类型(第10.1节)。这种类型被称为原始类型。

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

  • 其是通过取一个通用类型声明的名称不具有伴随的类型参数列表形成的引用类型。

的类型构造函数(§8.8),实例方法(8.4节,第9.4节),或者非静态字段(§8.3)原始类型的M C不是从它的超类或超接口继承的是原始类型,它对应于在对应于C的通用声明中删除其类型的原始类型。

即,继承的方法具有签名

saveSwiftMsg(Collection headers) throws Exception 

要覆盖,最重要的方法必须具有相同的签名继承一个。它不会导致编译错误。

我强烈建议只使用原始类型用于其预期用途(与传统代码接口),并启用(并修复)相应的编译器警告。

对于这个问题,所以确实说明书:

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

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

  • 在一个分配给一个字段:如果左手操作数的类型是原始类型,则如果擦除更改字段的类型,则会发生编译时未检查警告。

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

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

1

你neeed在子类中指定也

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

其实你内斯指定type.That是好样的

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

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

实施原始列表是否违法? – 2013-03-08 12:27:15

3

你的接口参数化与类型T时你执行它,你必须指定它的类型是这样的:

class Impl implements BaseIntr<String>{ 
} 

这就是如果你想实现它String。但是,您可以将参数委托给实现类:

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

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

+0

在儿童中使用泛型不是强制性的,对吧?我可能不会在实施中使用泛型。 – 2013-03-08 12:33:18