мы упростили некоторые определения и использование обобщений в нашем коде.
Теперь у нас есть интересный случай, возьмем этот пример:
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:
Этот код будет правильно скомпилирован с использованием JDT-компилятора eclipse, однако произойдет сбой при использовании компилятора 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. Это означает, что в нашем коде нет ничего плохого, и мы можем придерживаться его.
На вопрос дан ответ, и я отмечу его как таковой после двухдневного перерыва в моем собственном ответе.
Спасибо всем за конструктивный отзыв.