Generic class compiles in Java 6, but not Java 7

前端 未结 2 1751
北恋
北恋 2020-12-09 10:22

I have an interface in Java 6 that compiles correctly:

public interface IMultiMap extends Map> {

    public int valueSize(         


        
相关标签:
2条回答
  • 2020-12-09 10:28

    I ran the reflection code on Java 6.

    Here's the code:

    public static void main(String[] args) {
        Class<IMultiMap> immClass = IMultiMap.class;
        Method[] methods = immClass.getMethods();
        for (Method method : methods) {
            if (method.getName().equals("put"))
                System.out.println(method.toString());
        }
    }
    

    Here are the method signatures for the class:

    public abstract boolean IMultiMap.put(java.lang.Object,java.lang.Object)
    public abstract java.lang.Object java.util.Map.put(java.lang.Object,java.lang.Object)
    

    Or more concisely:

    boolean put(Object, Object)
    Object  put(Object, Object)
    

    So they are erased to the same parameters with a different return type. I guess it's a bug an unspecified edge case in the Java 6 JLS then, as per assylias' answer. I wonder how Java 6 managed to resolve these methods correctly on runtime?

    Edit: According to x4u's comment, the calling bytecode maintains a reference to the entire signature when it's compiled, so that's why the correct method was being called by the JVM. Since the compiler was probably capable of telling which method I was calling due to its access to the source (and thus to the generics information), the compiler probably linked it to the correct method via the entire signature. Interesting to know!

    0 讨论(0)
  • 2020-12-09 10:47

    I think it's a bug in 1.6 that was fixed in 1.7. Extract from this page:

    Synopsis: A Class Cannot Define Two Methods with the Same Erased Signature but Two Different Return Types
    Description: A class cannot define two methods with the same erased signature, regardless of whether the return types are the same or not. This follows from the JLS, Java SE 7 Edition, section 8.4.8.3. The JDK 6 compiler allows methods with the same erased signature but different return types; this behavior is incorrect and has been fixed in JDK 7.
    Example:

    class A {
       int m(List<String> ls) { return 0; }
       long m(List<Integer> ls) { return 1; }
    }
    

    This code compiles under JDK 5.0 and JDK 6, and is rejected under JDK 7.

    0 讨论(0)
提交回复
热议问题