Is it true that overloading must differ in parameter types or number of parameters but not erasure in Java?

86 views Asked by At

Erasure is decided at runtime and overloaded method to call is resolved at compile time.

Is it correct to say that overloading must differ in parameter types or number of parameters but not erasure in Java? Is it not equivalent in the context of overloading? If the methods differ in types or number of parameters, then their erasures differ as well every time? Is it incorrect to say that overloading must differ in the erasure just because it refers to runtime instead of compile time?

EDIT: For example, foo(List<String>) and foo(List<Integer>) have the same erasure and different parameter types, right? But compiling them result in an error

java: name clash: foo(java.util.List<java.lang.Integer>) and foo(java.util.List<java.lang.String>) have the same erasure

So what is more important? Erasure or parameter type?

1

There are 1 answers

0
banan3'14 On

Erasure is decided at runtime

No, it's not. The erasure of a type is known at compile-time. The link you've provided is effectively saying that "at execution time, the type information has been erased from the object". In other words, if you just have a reference to an object, you can't tell the difference between a List<String> and a List<Integer>.

The overloading section of JLS:

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.

This fact causes no difficulty and never of itself results in a compile-time error.

And signature is defined in another section of JLS:

Two methods or constructors, M and N, have the same signature if they have the same name, the same type parameters (if any) (ยง8.4.4), and, after adapting the formal parameter types of N to the type parameters of M, the same formal parameter types.

So because method signature consists of the method name and parameter list, in case of overloads, overloads are methods of the same name with different formal parameter types.

foo(List<String>) and foo(List<Integer>) are overloads of foo by the above definitions. The fact that it doesn't compile is because of a rule specified in another section.

In summary, it's not the erasure but the parameter list that defines whether the method is overloaded.


Thank @Jon Skeet and @Sweeper for providing valuable comments and references. The answer is mostly a combination of their comments and the text from references