通过泛型方法覆盖非泛型方法

时间:2014-09-23 10:11:17

标签: java android generics override

我想在我的android项目中自动构建视图。所以,我想覆盖

View findViewById(int id) {...}

方法

<T extends View> findViewById(int id) {...}

方法。但是java编译不允许这样做,但是重写的方法不会与parental冲突,并且总是会返回视图对象或其子对象。我发现了一些信息,java不允许通过泛型方法覆盖非泛型方法,但解释为什么我无法找到。

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ824 这个常见问题解答说这是不可能的,但我不明白为什么。例如,我们有这样的类:

class Super { 
  public void set( Object arg) { ... } 
  public Object get() { ... } 
} 
class Sub extends Super {  
  public <S extends Number> void set( S arg) { ... } // overloads 
  public <S extends Number> S get() { ... } // overloads 
}

常见问题解答他们应该使用重载进行编译,但我有一些奇怪的事情: getter返回与我的findViewById相同的错误,但setter编译没有错误。

有人可以解释一下这件事吗?为什么java不允许通过泛型覆盖非泛型,为什么setter编译,getter - no?

我知道,我可以使用其他方法,例如

<T extends View> findView(int id){
  return (T) findViewById(id);
}

<T extends View> findView(int id, Class<T> clazz) {
  return clazz.cast(findViewById(id));
}

但我想明白,为什么我应该使用新方法而不是覆盖?

//1
@Override
public View findViewById(int id) {
    return (View) super.findViewById(id);
}
//2
@Override
public <T extends View> T findViewById(int id) {
    return (T) super.findViewById(id);
}

那么,在编译时,1和2有什么区别?甚至方法1也比2更普遍。

//3
@Override
public <T extends View> View findViewById(int id) {
    return (View) super.findViewById(id);
}

在我添加上述方法之后,我终于意识到,&#34; T扩展了View&#34;告诉编译器,它与没有&#34; T扩展View&#34;的方法不同。所以,实际上,我创建了另一个新方法,但是具有相同的名称和参数,因此无法进行编译。也许这不完全正确,但正如我所理解的那样 - 类似于真实。

谢谢大家,他们试图帮助我。

1 个答案:

答案 0 :(得分:1)

set中的Sub方法进行编译,因为您声明了一个名为set方法,可以接受任何参数S that extends Number。 。注意你没有覆盖你已经重载set方法的Sub类中的Super类的set方法 使用get方法你完全相同,即重载get方法,但这次编译器抱怨因为它无效,因为你只改变了方法的返回类型。对于例如

public Object get() {
    return null;
}

并通过仅改变方法的返回类型来声明同一个或子类中的另一个方法

    public Number get() {
        return null;
    }

然后编译器会抱怨“方法get()已经定义”因为在java返回类型中不是方法签名的一部分。
如果声明

,则可以为set方法复制相同的问题
public <S extends Number> void set( Object arg) {  }

在这种情况下我们再次改变方法的返回类型但是有效的重载方法参数应该是不同的所以

public <S extends Number> void set( String arg) {  } // overloads

将是有效的重载