Почему это компилируется? Код, кажется, нарушает ограничения на параметры типа

В следующем тесте TesterClass накладывает ограничение на связь между двумя параметрами своего типа. Метод func2(), похоже, нарушает это ограничение, и я ожидаю, что он вызовет ошибку компиляции при наборе текста где-нибудь (в определении func2 или всякий раз, когда класс используется с любым вторым параметром, кроме String), но это не так!

Кроме того, если я вызову func2 и сохраню результат в переменной с соответствующим типом, компиляция завершится ошибкой (для типа этой переменной). Но сделать то же самое и сохранить в более общем типе (например, Object) удается, несмотря на то, что возвращаемый тип функции должен иметь один и тот же тип в обоих случаях (до приведения).

Что тут происходит?

Спасибо!

public class TestGenerics {
    public static class ParamedType<T> {}


    public class TesterClass<A extends ParamedType<B>, B> {
        public TesterClass<A, B> func() {
            return new TesterClass<A, B>();
        }

        public TesterClass<A, String> func2() {
            return new TesterClass<A, String>();
        }
    }

    public Object test() {
        // How can I use these type parameters? Doesn't .func2 now have an invalid return type?
        TesterClass<ParamedType<Integer>,Integer> testClass = new TesterClass<TestGenerics.ParamedType<Integer>, Integer>();

        //TesterClass<ParamedType<String>, Integer> res2 = testClass.func2(); // <-- will not compile
        Object res = testClass.func2(); // Compiles
        return res;
    }
}

EDIT: это не компилируется в javac (версии указаны ниже). Я использую Eclipse и пытаюсь выяснить, какой компилятор на самом деле работает. Будет обновляться. Может быть ошибка JDT (компилятор Eclipse).

Я открыл отчет об ошибке для jdt eclipse: https://bugs.eclipse.org/bugs/show_bug.cgi?id=333503


person sinelaw    schedule 04.01.2011    source источник
comment
У меня не компилируется, javac 1.6.0_21.   -  person axtavt    schedule 04.01.2011
comment
Компилируется компилятором Eclipse на уровне соответствия Java 6.0   -  person Mike Tunnicliffe    schedule 04.01.2011
comment
В конце кода отсутствует фигурная скобка, но он по-прежнему не компилируется (через javac в JDK 1.6.0_20).   -  person kvista    schedule 04.01.2011
comment
Отсутствие фигурной скобки является ошибкой форматирования. (Исправлена)   -  person Mike Tunnicliffe    schedule 04.01.2011
comment
Я считаю, что компилятор Eclipse является частью основного компонента JDT и включает в себя функции инкрементной компиляции. eclipse.org/jdt/core   -  person Mike Tunnicliffe    schedule 04.01.2011
comment
Это может быть ошибка JDT, вот моя версия JDT: 3.6.1.r361_v20100714-0800-7z8XFUSFLFlmgLc5z-Bvrt8-HVkH Идентификатор сборки: M20100909-0800   -  person sinelaw    schedule 04.01.2011
comment
На самом деле, чтобы иметь смысл, вы должны изменить TestGenerics‹...› в закомментированной строке на TesterClass‹ParamedType‹Integer›, String›. Класс testClass имеет параметр типа A из ParamedType<Integer>. Чтобы иметь смысл, тип для левой var res2 должен иметь те же параметры типа, что и func2 (A => ParamedType<Integer>, B => String — в закомментированной строке String и Integer поменяны местами.). Строка по-прежнему не компилируется, но я думаю, что тест имеет больше смысла с этими изменениями.   -  person Bert F    schedule 04.01.2011
comment
Берт Ф., проблема в том, что он вообще компилируется (с закомментированной строкой). По-видимому, ошибка Eclipse, я пытаюсь выяснить.   -  person sinelaw    schedule 04.01.2011
comment
@sinelaw - я понимаю проблему. Я попробовал ваш код, и у меня возникла та же проблема. Я раскомментировал закомментированную строку, чтобы попробовать, и она пометила несколько (других несвязанных) ошибок. Вы попытались получить результат func2() в переменную с типом, отличным от func2() - например, необработанный тип res2 - это TestGenerics, который не является вашим общим классом TesterClass. Эти проблемы не связаны с рассматриваемой проблемой, но я хотел указать на опечатки.   -  person Bert F    schedule 04.01.2011
comment
Протестировано с javac 1.7.0_21 и не компилируется (как и ожидалось)   -  person sinelaw    schedule 03.06.2013


Ответы (2)


Простой ответ: он не компилируется, по крайней мере, в javac 1.7:

Test.java:10: type parameter A is not within its bound
    public TesterClass<A, String> func2() {
                       ^
  where A,B are type-variables:
    A extends ParamedType<B> declared in class Test.TesterClass
    B extends Object declared in class Test.TesterClass
Test.java:11: type parameter A is not within its bound
        return new TesterClass<A, String>();
                               ^
  where A,B are type-variables:
    A extends ParamedType<B> declared in class Test.TesterClass
    B extends Object declared in class Test.TesterClass
2 errors

Вы не сказали, под чем вы его компилировали - я предполагаю, что в вашем компиляторе Java есть ошибка.

person Jon Skeet    schedule 04.01.2011
comment
Я только что протестировал javac 1.6.0_23, и он действительно не компилируется. - person sinelaw; 04.01.2011
comment
Между прочим, прошло более двух лет с тех пор, как я сообщил об этой проблеме в Eclipse, и она до сих пор не исправлена. Можно было бы подумать, что обеспечение безопасности типов будет высоко оцениваться по шкале критичности компилятора Java... - person sinelaw; 04.06.2013

Судя по всему, это ошибка Eclipse в JDT.core. Я открыл отчет об ошибке по адресу https://bugs.eclipse.org/bugs/show_bug.cgi?id=333503

person sinelaw    schedule 04.01.2011