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

时间:2010-07-15 17:09:12

标签: java generics type-erasure

  

可能重复:
  Is this valid Java?

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

它还编译了许多版本的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;
   }

}

2 个答案:

答案 0 :(得分:2)

编译器足够聪明,可以在编译时消除歧义,但最终它会执行类型擦除。参数化泛型的重点是提供编译时类型安全检查,类型擦除只是一个实现细节。

答案 1 :(得分:-3)

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