Странное поведение с параметризованным методом на абстрактном классе - PullRequest
5 голосов
/ 07 января 2010

Может кто-нибудь сказать, почему это дает ошибку компиляции? Я не понимаю, почему приведение к A во втором цикле for приводит к тому, что strings () возвращает общий список объектов.

import java.util.ArrayList;
import java.util.List;

public class E {

    public static void main(String[] args) {
        for (String s : new D().strings()) {
            System.out.println("s = " + s);
        }
        for (String s : ((A) new D()).strings()) {
            System.out.println("s = " + s);
        }
    }

    static class D extends A<C> {
    }

    static abstract class A<T extends B> {
        List<String> strings() {
            return new ArrayList<String>() {{
                add("Foo");
                add("Bar!");
            }};
        }
    }

    static class B {
    }

    static class C extends B {
    }
}

Это особенность дженериков?

Спасибо, Кристиан

1 Ответ

7 голосов
/ 07 января 2010

В строке:

    for (String s : ((A) new D()).strings()) {

Вы преобразуетесь в необработанный тип A, поэтому вы теряете информацию об аргументах типа. В Java любой метод или поле использования в необработанном типе также может привести к необработанному типу (даже если доступна вся параметризованная информация) - хорошо необработанный тип или технически не параметризованный. Таким образом, A.string() рассматривается как необработанный тип List, а не List<String>.

Как JSL указывает в Раздел 4.8 :

Тип конструктора (§8.8), метода экземпляра (§8.8, §9.4) или нестатического поля (§8.3) M необработанного типа C, который не унаследован от его суперклассов или суперинтерфейсов, является стиранием его типа в обобщенном объявлении, соответствующем C. Тип статического члена необработанного типа C совпадает с его типом в обобщенном объявлении, соответствующем C.

...