Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
重写Java中的等效签名,为什么在Java语言规范中编译时错误仅限于这种情况?_Java - Fatal编程技术网

重写Java中的等效签名,为什么在Java语言规范中编译时错误仅限于这种情况?

重写Java中的等效签名,为什么在Java语言规范中编译时错误仅限于这种情况?,java,Java,Java语言规范(确切地说是Java SE 7版): 在一个类中声明两个具有重写等效签名的方法是编译时错误 本规范并未说明根据以下定义声明具有相同签名的两个方法是编译时错误: 如果两个方法具有相同的名称和参数类型,则它们具有相同的签名 因此,有了它,下面的类就不应该编译,因为据我所知,这两个getter不是等价的: public class Foo { private String value = null; public Foo(String value) { this.value

Java语言规范(确切地说是Java SE 7版):

在一个类中声明两个具有重写等效签名的方法是编译时错误

本规范并未说明根据以下定义声明具有相同签名的两个方法是编译时错误:

如果两个方法具有相同的名称和参数类型,则它们具有相同的签名

因此,有了它,下面的类就不应该编译,因为据我所知,这两个getter不是等价的:

public class Foo {

private String value = null;

public Foo(String value) {
    this.value = value;
}

String getValue() {
    System.out.println("String version");
    return value;
}

int getValue() {
    System.out.println("int version");
    return Integer.parseInt(value);
}

public static void main(String[] args) {
    Foo foo = new Foo("5");
    System.out.println(foo.getValue());
    System.out.println(foo.getValue() + 5);
}

}
我的问题是,这不是Java语言规范中的一个疏忽吗?当然,类Foo不应该编译吗

我的IDE有问题,但我的编译器没有。此外,当main方法运行时,getter的声明顺序会更改输出

更新


事实证明,my.class文件是由Eclipse编译器for Java生成的。我不知道这一点,因此感到困惑。

这不应该编译。返回值类型不是参数之一。虚拟机无法确定您所指的方法,因为它不关心您如何处理返回值

对于方法,一个有序的3元组,由以下内容组成:

- argument types: a list of the types of the arguments to the method member.
- return type: the return type of the method member.
- throws clause: exception types declared in the throws clause of the method member.
结合您对Java规范的引用:

如果两个方法具有相同的名称和参数类型,则它们具有相同的签名

使用声明两个方法是编译时错误 重写类中的等效签名

这需要一个编译时错误,因此这是编译器的疏忽。

我通过JDK 7u45(Windows x64)得到了这一点:

您可能正在比较最新的规范和旧的编译器版本

更新编译器或查找旧规范;)

表意文字:


希望有帮助。

您应该阅读您提供的链接:

  • 如果两个方法具有相同的名称和参数类型,则它们具有相同的签名
  • 方法m1的签名是方法m2签名的子签名,如果:
  • m2与m1具有相同的签名,或
  • m1的签名与m2签名的删除(§4.6)相同
  • 两个方法签名m1和m2是覆盖等效的iff m1 是m2的子结构
    ,或m2是m1的子结构

    在一个类中声明两个具有重写等效签名的方法是编译时错误。

    因此,如果两个方法具有相同的签名(与返回类型无关),则它们的签名是彼此的子签名。这使它们重写等价项,从而产生编译错误


    在您的例子中,两个
    getValue
    方法都具有相同的签名,这使得它们重写等效的,这使得类非法。任何合适的java编译器都不应编译此类代码。

    所提供的类不应按照java语言规范进行编译,例如,它不会在Windowsx64上使用最新的JDKu45进行编译,因为正如问题中所指出的,在一个类中有两个具有相同签名的方法会构成编译时错误


    尽管该类不应按照Java语言规范进行编译,但这并不意味着您将看不到该类正在编译。这是因为,例如,使用提供的示例类,它将编译并运行程序。

    即使我也同意该规范。但是找到JVM不按照规范运行的原因并没有使用最新的SDK(JDK 7u45)编译,我得到了一个“复制方法”编译错误。我用6u45、7u7、7u45和8b118进行了尝试,在每种情况下都得到了相同的“错误:方法getValue()已经定义”。它可能是一个逃逸到7u11中的短命bug,或者您的环境中有什么不稳定的地方。@Nico您使用哪个平台?事实证明,Eclipse Java编译器正在生成类文件。
    foo.java:14: error: method getValue() is already defined in class Foo
    int getValue() {
        ^
    1 error