功能或错误:为什么这个Java代码会编译?

And*_*dyC 7 java generics type-erasure

可能重复:
这是有效的Java吗?

我惊讶地发现下面的Java类编译.它有几个方法,具有相同的名称,参数数量和以下类型 - 擦除类型的参数.然而,它使用各种版本的Sun JDK 1.6编译器在Windows上编译并按预期工作.所以,如果这是一个bug已经存在多年......

它还编译了许多版本的Eclipse,但不使用Eclipse 3.6附带的编译器进行编译

此外,调用代码按预期工作 - 即.关于调用代码的ambigious方法没有错误.

如果你迭代ErasureExample.class.getMethods()返回的方法,它们都存在.....

根据JLS,如果方法具有"覆盖等效"签名将是非法的 - 严格来说它们不会,因为Collection,Collection和Collection都不是覆盖等价的....如果Eclipse是错误的话,JDK正确...

功能还是错误?它应该编译吗?

/**
 * Demonstrates that a class with methods that differ only by return type can exist.
 * Section 8.4 of the JLS suggests this is an error IFF the methods had
 * override equivalent signatures, which they dont''
 *
 * 
 * From JLS 8.4...

 * It is a compile-time error for the body of a class to declare as members two methods 
 * with override-equivalent signatures (§8.4.2) (name, number of parameters, and types
 * of any parameters). 
 *
 * Should it compile?
 */
public class ErasureExample {
   // note the single Collection<Integer> argument...
   public static int[] asArray(Collection<Integer> vals) {
      if (vals == null)
         return null;

      int idx = 0;
      int[] arr = new int[vals.size()];
      for (Integer i : vals) {
         arr[idx] = i==null? 0 : i.intValue();
         idx++;
      }
      return arr;
   }

   // same method name as above, type differs only by generics.... surely this violates 8.4 of JLS...
   public static long[] asArray(Collection<Long> vals) {
      if (vals == null)
         return null;

      int idx = 0;
      long[] arr = new long[vals.size()];
      for (Long i : vals) {
         arr[idx] = i==null? 0 : i.longValue();
         idx++;
      }
      return arr;
   }

   // same method name as above, type differs only by generics.... surely this violates 8.4 of JLS...
   public static boolean[] asArray(Collection<Boolean> vals) {
      if (vals == null)
         return null;

      int idx = 0;
      boolean[] arr = new boolean[vals.size()];
      for (Boolean b : vals) {
         arr[idx] = b==null? false : b.booleanValue();
         idx++;
      }
      return arr;
   }

}
Run Code Online (Sandbox Code Playgroud)

Jed*_*Pie -3

这些方法根本不具有相同的签名。返回值不同,参数类型不同。是的,确实,仿制药确实有很大的不同。这里一切看起来都不错。

  • 更正:返回值不是签名的一部分 (7认同)
  • 实际上,在字节码级别,方法描述符也包含返回类型,可以用来区分它们。编译器有时可以利用这一点,通过检查保存结果的变量的类型,因为编译器可以告诉应该调用什么方法,而在字节码中,它只是指令“带有描述符 this-and- 的调用方法”那'。根据规范,这并不完全正确,但编译器目前允许这样做。显然在 Java 7 中他们可能会改变这一点。 (5认同)