Специальное использование дженериков Java: «взломать» или «хорошее повышение производительности»?

мы упростили некоторые определения и использование дженериков в нашем коде. Теперь у нас есть интересный случай, возьмем этот пример:

public class MyWeirdClass {

    public void entryPoint() {
        doSomethingWeird();
    }

    @SuppressWarnings( "unchecked" )
    private <T extends A & B> T getMyClass() {
        if ( System.currentTimeMillis() % 2 == 0 ) {
           return (T) new MyClass_1();
        } else {
           return (T) new MyClass_2();
        }
    }

    private <T extends A & B> void doSomethingWeird() {
        T obj = getMyClass();

        obj.methodFromA();
        obj.methodFromB();
    }

    static interface A {
        void methodFromA();
    }

    static interface B {
        void methodFromB();
    }

    static class MyClass_1 implements A, B {
        public void methodFromA() {};
        public void methodFromB() {};
    }

    static class MyClass_2 implements A, B {
        public void methodFromA() {};
        public void methodFromB() {};
    }
}

Теперь посмотрим на метод doSeomthingWeird () в MyWeirdClass: Этот код будет правильно компилироваться с использованием компилятора Eclipse JDT, однако он не будет работать при использовании компилятора Oracle.Поскольку JDT может создавать рабочий байт-код, это означает, что на уровне JVM это допустимый код, и это «всего лишь» компилятор Oracle, не позволяющий компилировать такой грязный (!?) материал. Мы понимаем, что компилятор Oracle не принимает вызов 'T obj = getMyClass ();' поскольку T на самом деле не существует. Однако, поскольку мы знаем, что возвращаемый объект реализует A и B, почему бы не разрешить это? (Компилятор JDT и JVM делают). Также обратите внимание, что, поскольку код универсальных шаблонов используется только внутри частных методов, мы не хотим раскрывать их на уровне класса, загрязняя внешний код определениями универсальных шаблонов, которые нас не интересуют (извне класса).

В школьном учебнике решение будет заключаться в создании интерфейса AB, расширяющего A, B, однако, поскольку у нас есть большее количество интерфейсов, которые используются в различных комбинациях и поступают из разных модулей, создание общих интерфейсов для всех комбинаций значительно увеличит количество «фиктивных» интерфейсов и, наконец, сделать код менее читабельным. Теоретически потребуется до N-перестановок различных интерфейсов-оболочек, чтобы охватить все случаи. Решение «бизнес-ориентированный инженер» (другие называют его «ленивым инженером») заключалось бы в том, чтобы оставить код таким образом и начать использовать только JDT для компиляции кода. Редактировать: Это ошибка в Oracle Javac 6 и работает без проблем также с Oracle Javac 7

Что вы имеете в виду? Есть ли какие-либо скрытые опасности при принятии этой «стратегии»?


Дополнение во избежание обсуждения (для меня) не относящихся к делу вопросов: Я не спрашиваю, почему приведенный выше код не компилируется на компиляторе Oracle Я знаю причину и не хочу изменять такой код без уважительной причины, если он отлично работает при использовании другого компилятора. Пожалуйста, сконцентрируйтесь на определении и использовании (без указания конкретного типа) метода doSomethingWeird (). Есть ли веская причина, почему мы не должны использовать только компилятор JDT, который позволяет писать и компилировать этот код, и прекратить компиляцию с помощью компилятора Oracle, который не примет код выше? (Спасибо за ввод)

Изменить : приведенный выше код правильно компилируется на Oracle Javac 7, но не на Javac 6. Это ошибка Javac 6. Это означает, что в нашем коде нет ничего плохого, и мы можем придерживаться его. На вопрос дан ответ, и я отмечу его как таковой после двухдневного перерыва в моем собственном ответе. Спасибо всем за конструктивный отзыв.

8
задан Danilo Tommasina 22 February 2012 в 07:14
поделиться