奇怪的行为围绕“相同的擦除”编译错误

我最近偶然发现了一段代码,由于“相同的擦除”问题,这段代码在我的Eclipse中无法编译(看起来与本文非常相似)。 编写代码的人向我保证,它在当地环境中编译并持续集成,所以我一直在模仿它。

看看这个片段:

package com.mycompany.playground;

import java.util.ArrayList;
import java.util.Collection;

public class GenericsTest {

    public static void main (String[] args) {
        System.out.println(GenericsTest.doSomething(new ArrayList<A>()));
        System.out.println(0 == GenericsTest.doSomething(new ArrayList<C>()));
    }

    public GenericsTest() {
    }

    public static String doSomething(Collection<A> listOfA) {
        return "has done something to Collection<A>";
    }

    public static Integer doSomething(Collection<C> listOfC) {
        return 0;
    }

    private class A {

    }

    private class C {

    }

}

带有1.6.0_21 JDK作为工作空间默认的Eclipse Helios不会编译它,并会抱怨Method doSomething(Collection)与GenericsTest类型中的另一种方法具有相同的删除doSomething(Collection)。 关于另一种方法,它会这么说。

试图强制Eclipse运行它并看到:线程“main”中的异常java.lang.Error:未解决的编译问题:类型GenericsTest中的doSomething(Collection)方法不适用于参数(ArrayList)。

好。 这是可以预料的。 现在。 如果我进入我的命令行并运行简单:

javac GenericsTest.java

它编译。 我检查了1.6.0_21和1.6.0_06(他们在他们的环境中的那个人),但都没有抱怨。 我将类文件复制到Eclipse期望的位置,并强制它再次运行它。

它打印:

has done something to Collection<A>
true

如果我更换

System.out.println(0 == GenericsTest.doSomething(new ArrayList<C>()));

System.out.println(GenericsTest.doSomething(new ArrayList<C>()));

它仍然会在没有来自命令行的警告的情况下进行编译,但在尝试运行时会给出相同的“未解决的编译问题”。

这里有两个问题。

  • javac是否超越了内置的Eclipse编译器? 看起来几乎完全像这个以前问的问题,所以我相信我知道答案。 (顺便说一句,我如何告诉Eclipse使用javac呢?)。

  • 为什么javac会静静地编译java然后运行失败(第二种情况是{0 ==}“提示”被删除?


  • 根据Java规范,应该通过签名(名称+参数类型)区分两种方法,而不是返回类型。 由于JDK中的一个bug,可以编译原始代码http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6182950在某些版本的Eclipse中已修复此错误,这就是为什么有些人无法获得它在Eclipse中编译。 至于为什么编译后的代码能够真正起作用,您应该了解Java语言不等同于JVM字节码。 在字节码中,你可能有很多非法的Java名字,是的,字节码通过签名,返回类型和可能的一些附加信息来区分方法。


    这里的问题是:每当你有两个同名的方法时,它们必须有不同的签名。 这里考虑的签名不包括返回类型,所以这两个方法不能在同一个类中声明

    int foo(A a) 
    float foo(A a)
    

    在你的例子中,你有两个具有不同参数类型的不同方法( Collection<A>Collection<C> ),但在内部,当编译器发挥它的魔力时,泛型被认为是Collection。 这就是“同样的删除”的含义。

    现在我不记得了,如果所有的java版本都显示这种行为,因为我一直被java 5和java 6卡住了太多。

    希望它可以帮助。


    帕维尔,我想我面临着你所描述的同样的问题。

    今天,我用自己的代码进行黑客攻击,并获得了Eclipse和Java编译器相同的不同行为。 虽然,它似乎是一个已知的编译器问题。

    请参阅Bug 6182950。

    谢谢!

    链接地址: http://www.djcxy.com/p/48513.html

    上一篇: weird behavior around "same erasure" compilation error

    下一篇: like "as" keyword (for namespacing) in Ruby