Is this valid Java?

2019-01-10 09:42发布

Is this valid Java?

import java.util.Arrays;
import java.util.List;

class TestWillThatCompile {

    public static String f(List<String> list) {
        System.out.println("strings");
        return null;
    }

    public static Integer f(List<Integer> list) {
        System.out.println("numbers");
        return null;
    }

    public static void main(String[] args) {
        f(Arrays.asList("asdf"));
        f(Arrays.asList(123));
    }

}
  • Eclipse 3.5 says yes
  • Eclipse 3.6 says no
  • Intellij 9 says yes
  • Sun javac 1.6.0_20 says yes
  • GCJ 4.4.3 says yes
  • GWT compiler says yes
  • Crowd at my previous Stackoverflow question says no

My java theory understanding says no!

It would be interesting to know what the JLS is saying about it.

10条回答
乱世女痞
2楼-- · 2019-01-10 10:05

Eclipse can produce byte code out of this:

public class Bla {
private static BigDecimal abc(List<BigDecimal> l) {
    return l.iterator().next().multiply(new BigDecimal(123));
}

private static String abc(List<String> l) {
    return l.iterator().next().length() + "";
}

public static void main(String[] args) {
    System.out.println(abc(Arrays.asList("asdf")));
    System.out.println(abc(Arrays.<BigDecimal>asList(new BigDecimal(123))));
}
}

Output:

4

15129

查看更多
戒情不戒烟
3楼-- · 2019-01-10 10:09

Well, if I understand bullet point three correctly in the first list from section 8.4.2 of the spec, it says your f() methods have the same signature:

http://java.sun.com/docs/books/jls/third_edition/html/classes.html#38649

It's the spec that really answers this question, and not the observed behavior of compiler X or IDE X. All we can say by looking at the tools is how the author of the tool interpreted the spec.

If we apply bullet three, we get:

...
    public static String f(List<String> list) {
        System.out.println("strings");
        return null;
    }

    public static Integer f(List<String> list) {
        System.out.println("numbers");
        return null;
    }
...

and the signatures match, so there's a collision and the code shouldn't compile.

查看更多
男人必须洒脱
4楼-- · 2019-01-10 10:14

Java type inference (what's going on when you call static, generic methods like Array.asList) is complicated and not well-specified in the JLS. This paper from 2008 has a very interesting description of some of the issues and how it might be fixed:

Java Type Inference is Broken: How Can We Fix it?

查看更多
放我归山
5楼-- · 2019-01-10 10:19

It's valid vased on the specification.

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.

So these are not subsignatures of eachother because the erasure of List<String> is not List<Integer> and vice versa.

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

So these two are not override-equivalent (note the iff). And the rule for overloading is:

If two methods of a class (whether both declared in the same class, or both inherited by a class, or one declared and one inherited) have the same name but signatures that are not override-equivalent, then the method name is said to be overloaded.

Therefore, these two methods are overloaded and everything should work.

查看更多
登录 后发表回答