微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java泛型代码编译与javac,失败与Eclipse Helios

我有以下测试类,它使用泛型来重载一个方法.它在使用 javac编译时工作,并且无法在 Eclipse Helios中编译.我的java版本是1.6.0_21.

我看到的所有文章都表明Eclipse是正确的,这段代码不行.但是当使用javac进行编译并运行时,将选择正确的方法.

这怎么可能?

谢谢!

import java.util.ArrayList;

public class Test {
    public static void main (String [] args) {
        Test t = new test();
        ArrayList<String> ss = new ArrayList<String>();
        ss.add("hello");
        ss.add("world");
        ArrayList<Integer> is = new ArrayList<Integer>();
        is.add(1);
        is.add(2);
        System.out.println(t.getFirst(ss));
        System.out.println(t.getFirst(is));
    }   
    public String getFirst (ArrayList<String> ss) {
        return ss.get(0);
    }
    public Integer getFirst (ArrayList<Integer> ss) {
        return ss.get(0);
    }
}

解决方法

Java Language Specification,section 8.4.2写道:

It is a compile-time error to declare two methods with
override-equivalent signatures
(defined below) in a class.

Two method signatures m1 and m2 are override-equivalent iff either m1 is a subsignature of m2 or m2 is a subsignature of m1.

The signature of a method m1 is a subsignature of the signature of a method m2 if either

  • m2 has the same signature as m1,or

  • the signature of m1 is the same as the erasure of the signature of m2.

很明显,这些方法不是覆盖等价的,因为ArrayList< String>不是ArrayList(ArrayList< Integer>的擦除).

所以宣称这些方法是合法的.此外,方法调用表达式是有效的,因为这是一个最具体的方法,因为只有一种匹配参数类型的方法.

编辑:沂山正确地指出,在这种情况下,还有另外一个限制. Java Language Specification,section 8.4.8.3写道:

It is a compile time error if a type declaration T has a member method
m1 and there exists a method m2
declared in T or a supertype of T such
that all of the following conditions
hold:

  • m1 and m2 have the same name.
  • m2 is accessible from T.
  • The signature of m1 is not a subsignature (§8.4.2) of the signature of m2.
  • m1 or some method m1 overrides (directly or indirectly) has the same erasure as m2 or some method m2 overrides (directly or indirectly).

附录:关于呃,还有它的缺乏

与流行概念相反,方法签名中的泛型不会被清除.泛型被字节码(Java虚拟机的指令集)擦除.方法签名不是指令集的一部分;它们被写入源代码中指定的类文件. (除此之外,还可以在运行时使用反射查询此信息).

想想一下:如果类型参数完全从类文件删除,那么您选择的IDE中的代码完成如何可以显示ArrayList.add(E)接受类型为E的参数,而不是Object(= E的擦除)如果您没有附加JDK源代码?当方法参数的静态类型不是E的子类型时,编译器如何知道抛出编译错误

原文地址:https://www.jb51.cc/java/121573.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐