2016-09-20 3 views
1

Следующий код:Почему это переопределение метода объявляет ошибку компиляции?

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

class Child extends Parent { 

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

не удается скомпилировать со следующей ошибкой:

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 

Но я проверяю, что JLS8 в §8.4.8.1 говорит:

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.

...

И в §8.4.2 в нем говорится:

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.

И в этом случае объявления оригинала и переопределения метода имеют одно и то же стирание, так почему компиляция терпит неудачу?

+3

'Список ' не является стиранием 'List', поэтому по спецификации, которую вы указали, это не поднаклейка. Я думаю, вы перепутали 'm1' и' m2'. – 4castle

+0

Не считаются ли они стилями типа 'List '?. –

+1

Они оба типа стираются в 'List', но спецификация, которую вы указали, касается не того, есть ли у них обычное стирание, это вопрос о том, является ли метод подкласса методом стирания суперкласса. Если родительский класс имеет «Список », а подкласс имеет «Список», все будет в порядке. – 4castle

ответ

2

Потому что, после стирания типа, есть только List (List<Object> если хотите). Я думаю, что вы хотели родовое Parent как

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

class Child extends Parent<String> { 
    public void method(List<String> parameter) { 
    } 
} 
+0

Я не уверен, что ваше первое утверждение отвечает на вопрос, потому что OP сделал аналогичный случай, почему он не должен быть ошибкой компилятора. – 4castle

+0

Фактический родительский класс принадлежит устаревшей библиотеке, но в любом случае я на самом деле не ищу решение, но причина, по которой компилятор ведет себя так. –

+0

@JaimeHablutzel Так, чтобы устаревший код (например, у вас здесь) продолжает функционировать с добавлением общих типов (которые почти полностью являются системой проверки типа времени компиляции). –

2

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

То же стиранием не хватает. Еще раз взгляните на раздел JLS, который вы указали:

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.

Это не говорит, что стирания должны быть равны. Это говорит о том, что подпись m1 должна быть стирание подписи из м2. Здесь мы не снимаем подпись m1.

+0

В этом случае класса 'Parent { недействительного метод (Список параметра) { } } класса Ребенок расширяет Parent { недействительного метода (List параметра) { } }' должен составлять, как подпись M1 таких же, что стирание подписи m2, но это не так. –

+1

@JaimeHablutzel: m1 и m2 - это наоборот. – user2357112

+0

m1 и m2 ссылались на правильные методы, проблема с примером в моем предыдущем комментарии была типом стирания для 'List ' не 'List ', а просто 'List'.Следующий пример поясняет, когда 'm1 такое же, как стирание подписи m2' и она работает правильно' класса Parent { недействительным метод (List Foo) { }} класс Ребенок расширяет Parent { недействительным метод (Строка списка) { } } '. –

Смежные вопросы