我有两个 Java 接口和一个实现类。
(我使用Eclipse直接运行程序,并且我没有尝试通过从命令行显式编译来检查任何编译器警告等。)
为什么他们运行没有问题?为什么 Java 允许这样做,即使它满足两个接口的“契约”,但在实现类时会产生歧义?
更新了示例。
public interface CassettePlayer {
void play();
}
public interface DVDPlayer {
void play();
}
public class CarPlayer implements CassettePlayer,DVDPlayer{
@Override
public void play() {
System.out.println("This plays DVD, screw you Cassette !");
}
public static void main(String args[]) {
CarPlayer cp = new CarPlayer();
cp.play();
CassettePlayer firstInterface = new CarPlayer();
firstInterface.play();
DVDPlayer secondInterface = new CarPlayer();
secondInterface.play();
}
}
“Java 语言规范”第 8.1.5 节特别允许这种情况:
允许类中的单个方法声明实现多个超级接口的方法。例如,在代码中:文中接着指出,如果方法签名具有不同的返回类型,例如
interface Fish { int getNumberOfScales(); } interface Piano { int getNumberOfScales(); } class Tuna implements Fish, Piano { // You can tune a piano, but can you tuna fish? int getNumberOfScales() { return 91; } }
类
getNumberOfScales
中的方法Tuna
的名称、签名和返回类型与接口Fish
中声明的方法匹配,也与接口Piano
中声明的方法匹配;它被认为同时实现。
double
和
int
,则无法在同一个类中实现这两个接口,并且会产生编译时错误。
接口是一种“契约”,这样人们就知道在具有该接口的类中强制实现了哪些方法。
因此,如果您需要一个实现“DVDPlayer”的类(因为您需要“play()”方法),您将找到 CarPlayer。实现 CassettePlayer 的类的需求也是如此。这就是技术解释。
但是当然,在语义编码中,您应该确保 CarPlayer 的方法“play()”满足 DVDPlayer 和 CassettePlayer 的语义。我认为在实际应用中这将是一个不好的做法。
当然,在您的示例中,让两个接口声明相同的方法是一个坏主意。更实际的是,您应该使用方法“play()”创建一个接口“Player”,并拥有另外两个从 Player 继承的更具体的接口 DVDPlayer 和 CassettePlayer(具有针对 DVD 和盒式磁带的特定方法)。 另一方面,如果您不需要 DVD 或盒式磁带的特定方法,那么您不需要两个不同的接口只实现一个且相同的方法 - 只需使用一个接口 Player 就足够了。
interface Animal {
public void eat() throws IOException;
}
interface Plants {
public void eat() throws NullPointerException;
}
编译器选择哪一个?为什么下面的代码会出错?
public class Test implements Animal, Plants {
public void eat() throws IOException {
}
}
编译器说:异常 IOException 与 Plants.eat() 中的 throws 子句不兼容