Luk*_*lor 3 java oop inheritance interface
假设我有两个接口:
public interface InterfaceA {
public int getStuff();
}
public interface InterfaceB {
public String getStuff();
}
Run Code Online (Sandbox Code Playgroud)
现在我有一个实现这两个接口的类:
public class Testing implements InterfaceA, InterfaceB{
public String getStuff() {
return "one";
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,这会编译吗?如果它确实编译了,它会运行吗?
编辑:
我确实在我的电脑上试过这个,发现它编译并运行了,但是当调用 getStuff() 时,程序以
未解决的编译问题
任何想法 Java 在较低级别上做什么?
这会编译吗?如果它确实编译了,它会运行吗?
您可能会感到惊讶:它不会编译,但如果编译了,它会运行。
Java 编译器要求您实现在您在类上声明的接口中声明的所有方法。在你的情况,你需要实现两个 public int getStuff();和public String getStuff();。如果不这样做,编译器将显示错误:
测试不是抽象的,并且不会覆盖 InterfaceA 中的抽象方法 getStuff() 测试中的 getStuff() 不能在 InterfaceA 中实现 getStuff()
现在,对于 Java 虚拟机,在您的类中同时拥有这两种方法就完全没问题了。但是,Java 编译器不允许:
方法 getStuff() 已在类 Testing 中定义
所以你的代码不会以一种或另一种方式编译。
任何想法 Java 在较低级别上做什么?
让我们回到 JVM 本身并做一些邪恶的事情。看看这个jasmin程序:
.class public Testing
.super java/lang/Object
.implements InterfaceA
.implements InterfaceB
.method public static getStuff()I
ldc 666
ireturn
.end method
.method public static getStuff()Ljava/lang/String;
ldc "Evil stuff"
areturn
.end method
.method public static main([Ljava/lang/String;)V
.limit stack 10
getstatic java/lang/System/out Ljava/io/PrintStream;
dup
invokestatic Testing/getStuff()I
invokevirtual java/io/PrintStream/println(I)V
invokestatic Testing/getStuff()Ljava/lang/String;
invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V
return
.end method
Run Code Online (Sandbox Code Playgroud)
我们声明了一个类Testing,它声明了两个具有相同名称和参数的方法,唯一的区别是返回类型。它实现了这两个接口,并有一个public static void main(String[] args)方法来调用这两个方法(getStuff()和getStuff())并显示结果。而且这个程序确实有效,虚拟机没有抱怨任何东西。
为什么有效?的JVM规范定义了描述这样的方法的:
MethodDescriptor:
( ParameterDescriptor* ) ReturnDescriptor
Run Code Online (Sandbox Code Playgroud)
该描述符用于(除了类和方法名称之外)在运行时解析方法。因为它包含ReturnDescriptor,所以可以有多个同名的方法。
编译器呢?编译器不使用它们的描述符来识别方法,而是使用它们的签名。在Java语言规范包含此:
如果两个方法具有相同的名称和参数类型,则它们具有相同的签名。
如果以下所有条件都成立,则两个方法或构造函数声明 M 和 N 具有相同的参数类型:
它们具有相同数量的形式参数(可能为零)
它们具有相同数量的类型参数(可能为零)
设 A1, ..., An 为 M 的类型参数, B1, ..., Bn 为 N 的类型参数。 将 N 类型中每次出现的 Bi 重命名为 Ai 后,对应类型变量的边界为相同,且 M 和 N 的形参类型相同。
因此,在源代码中无法通过方法的返回类型来区分方法,并且编译器禁止声明仅在返回类型上不同的方法。
| 归档时间: |
|
| 查看次数: |
2179 次 |
| 最近记录: |