1

The following code:

class Parent {
    public void method(List parameter){
    }
}

class Child extends Parent {

    public void method(List<String> parameter) {
    }
}

fails to compile with the following error:

Parent.java:12: error: name clash: method(List<String>) in Child and method(List) in Parent have the same erasure, yet neither overrides the other
    public void method(List<String> parameter) {
                ^
1 error

But I'm checking that JLS8 in §8.4.8.1 says:

An instance method mC declared in or inherited by class C, overrides from C another method mA declared in class A, iff all of the following are true:

...

The signature of mC is a subsignature (§8.4.2) of the signature of mA.

...

And in §8.4.2 it says:

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

...

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

And in this case both the original and the overriding method declarations have the same erasure, so why the compilation fails?

Jaime Hablutzel
  • 6,117
  • 5
  • 40
  • 57
  • 3
    `List` is not the erasure of `List`, so by the spec you cited it isn't a subsignature. I think you got `m1` and `m2` mixed up. – 4castle Sep 20 '16 at 23:07
  • Aren't they both considered to be type erased to `List`?. – Jaime Hablutzel Sep 20 '16 at 23:36
  • 1
    They are both type erased to `List`, but the specification you cited isn't about whether they have a common erasure, it's about whether the subclass' method is the erasure of the superclass' method. If the parent class had `List` and the subclass had `List`, you would be fine. – 4castle Sep 20 '16 at 23:46
  • @4castle, I see, I got it wrong in my question, what should I do? edit the question? or remove it as the question itself was not correctly formulated?. – Jaime Hablutzel Sep 21 '16 at 05:31

2 Answers2

2

Because, after type erasure, there are only List (List<Object> if you prefer). I think you wanted a generic Parent like

class Parent<T> {
    public void method(List<T> parameter){
    }
}

class Child extends Parent<String> {
    public void method(List<String> parameter) {
    }
}
Elliott Frisch
  • 198,278
  • 20
  • 158
  • 249
  • I'm not sure your first statement answers the question, because the OP made a similar case for why it shouldn't be a compiler error. – 4castle Sep 20 '16 at 23:22
  • The actual parent class belongs to a legacy library but anyway I'm not actually looking for a solution but the reason for the compiler to behave that way. – Jaime Hablutzel Sep 20 '16 at 23:40
  • @JaimeHablutzel So that legacy code (such as you have here) continues to function with the addition of generic types (which are, almost entirely, a compile time type checking system). – Elliott Frisch Sep 21 '16 at 00:12
2

And in this case both the original and the overriding method declarations have the same erasure, so why the compilation fails?

The same erasure isn't enough. Take another look at the JLS section you quoted:

The signature of a method m1 is a subsignature of the signature of a method m2 if either:

...

the signature of m1 is the same as the erasure (§4.6) of the signature of m2.

That's not saying the erasures have to be equal. That's saying that the signature of m1 has to be the erasure of the signature of m2. We're not taking the erasure of m1's signature here.

user2357112
  • 260,549
  • 28
  • 431
  • 505
  • In that case `class Parent { void method(List parameter){ } } class Child extends Parent { void method(List parameter) { } }` should compile as m1's signature is the same that the erasure of m2's signature, but it doesn't. – Jaime Hablutzel Sep 20 '16 at 23:44
  • 1
    @JaimeHablutzel: m1 and m2 are the other way around. – user2357112 Sep 20 '16 at 23:49
  • m1 and m2 were referring to the right methods, the problem with the example in my previous comment was the type erasure for `List` is not `List` but just `List`. The following example clarifies when `m1 is the same as the erasure of the signature of m2` and it works correctly `class Parent { void method(List foo){ } } class Child extends Parent { void method(List bar) { } } `. – Jaime Hablutzel Sep 21 '16 at 05:27
  • Your answer is actually pinpointing the problem formulating my question as @4castle spotted too. Should I edit the question as it was incorrectly formulated or should I delete it as your answer wouldn't apply if it just asks `Why does this overriding method declaration produce a compilation error?` without quoting the JLS (which I didn't interpreted correctly)?. – Jaime Hablutzel Sep 21 '16 at 05:35