Java 泛型代码使用 javac 编译,使用 Eclipse Helios 失败 [英] Java generics code compiles with javac, fails with Eclipse Helios

查看:42
本文介绍了Java 泛型代码使用 javac 编译,使用 Eclipse Helios 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下使用泛型重载方法的测试类.它在使用 javac 编译时有效,但在 Eclipse Helios 中无法编译.我的java版本是1.6.0_21.

I have the following test class that uses generics to overload a method. It works when compiled with javac and fails to compile in Eclipse Helios. My java version is 1.6.0_21.

我读过的所有文章都表明 Eclipse 是正确的,这段代码应该不起作用.但是当用 javac 编译并运行时,选择了正确的方法.

All the articles I read indicate that Eclipse is right and this code should not work. However when compiled with javac and run, the right method is selected.

这怎么可能?

谢谢!

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 语言规范,第 8.4.2 节写道:

声明两个方法是编译时错误覆盖等效签名(定义如下)在一个类中.

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

如果 m1 是 m2 的子签名或 m2 是 m1 的子签名,则两个方法签名 m1 和 m2 是覆盖等效的.

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

方法 m1 的签名是方法 m2 签名的子签名,如果有的话

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

  • m2 与 m1 具有相同的签名,或者

  • m2 has the same signature as m1, or

m1 的签名和m2 的签名是一样的.

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

显然,这些方法不是重写等价的,因为 ArrayList 不是 ArrayList(ArrayList).

Clearly, the methods are not override equivalent, since ArrayList<String> isn't ArrayList (the erasure of ArrayList<Integer>).

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

So declaring the methods is legal. Also, the method invocation expression is valid, as there trivially is a most specific method, since there is only one method matching the argument types.

编辑: Yishai 正确地指出,在这种情况下还有另一个限制.Java 语言规范,第 8.4.8.3 节 写道:

Edit: Yishai correctly points out that there is another restriction closely skirted in this case. The Java Language Specification, section 8.4.8.3 writes:

如果类型声明 T 有成员方法,则是编译时错误m1 并且存在一个方法 m2在 T 或 T 的超类型中声明,例如满足以下所有条件保持:

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 和 m2 具有相同的名称.
  • m2 可从 T 访问.
  • m1 的签名不是 m2 签名的子签名(第 8.4.2 节).
  • m1 或某些方法 m1 覆盖(直接或间接)与 m2 或某些方法 m2 覆盖(直接或间接)具有相同的擦除.

附录:肯定和缺乏

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

Contrary to popular notion, generics in method signatures are not erased. Generics are erased in bytecode (the instruction set of the Java virtual machine). Method signatures are not part of the instruction set; they are written to the class file as specified in the source code. (As an aside, this information can also be queried at runtime using reflection).

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

Think about it: If type parameters were erased from class files entirely, how could the code completion in the IDE of your choice display that ArrayList.add(E) takes a parameter of type E, and not Object (=the erasure of E) if you didn't have the JDKs source code attached? And how would the compiler know to throw a compilation error when the static type of the method argument wasn't a subtype of E?

这篇关于Java 泛型代码使用 javac 编译,使用 Eclipse Helios 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆