2012-08-24 40 views
3
public interface Foo <T> { 
    void setValue(T value); 
} 

public abstract class Bar extends JFormattedTextField{ 
    @Override 
    public void setValue(Object value) { 

    } 
} 

public class FooBar extends Bar implements Foo<String>{ 
    @Override //Foo 
    public void setValue(String aValue) { 
    // TODO Auto-generated method stub 

    } 

    @Override //Bar 
    public void setValue(Object aValue) { 
    // TODO Auto-generated method stub 

} 
} 

这导致实现接口和抽象类具有相同梅索德名称导致通用名称冲突

名称冲突:Foo类型的方法的setValue(M)具有相同的 擦除作为setValue方法(对象)类型的JFormattedTextField,但不 覆盖它

为什么我没有得到任何来自编译器的爱和我怎么能解决这个问题?

+0

Bridge方法是你的问题:http://stas-blogspot.blogspot.de/2010/03/java-bridge-methods-explained.html –

回答

3

这是因为类型擦除(见这个问题:Java generics - type erasure - when and what happens)的

一言以蔽之:编译器将使用String检查所有方法调用和类型转换工作,然后,它会使用Object生成的字节码。这意味着你现在有两种方法具有相同签名:public void setValue(Object aValue)

有这个不完美的解决方案。您可以通过使用Foo<Object>代替Foo<String>对上面编译的代码,但这通常不是你想要的。

一种解决方法是使用专用的适配器:

public class FooBar extends Bar { 
    public Foo<String> adapt() { 
     return new Foo<String>() { 
      public void setValue(String value) { 
       FooBar.this.setValue(value); 
      } 
     } 
    } 
} 

基本上什么adapt()方法应该做的是创建一个实现了正确的接口,并且所有的方法调用映射到this一个新的实例。

+0

所以编译器会将我的FooBar中的setValue(String value) class为setValue(Object value),仅仅因为它是从Foo实现的?如果我没有从富实现它就会让的setValue(字符串值)的是什么?因为我可以在一个类中使用两个具有相同名称但具有不同参数的方法? – Torsten

+0

是的。它知道'T'是'String',这意味着''setValue(String)'必须是接口中定义的方法。它需要知道这一点,以便在生成字节码时可以正确地擦除类型。 –

+0

我不确定你是否理解我的问题,或者我是否理解了你的评论的答案。无论如何,我要将你的答案标记为解决方案,因为它比AmitD更详细。 – Torsten

0

Java使用类型擦除仿制药。在你的情况下,类型是String也是Object的子类。而你的Bar类允许Object发生Nameclash。

在您的情况,因为你是在扩展的类使用非通用遗留类对象作为参数,我会建议你改变方法名或改变Foo类型String`返回1.4天:-)