Недавно в Oracle блоге Brian Goetz опубликовал ссылку на презентацию с Devoxx talk on Language / Library / VM Co-Evolution in Java SE 8.
В статье я попытаюсь вкратце раскрыть основные проблемы, которые будут решены в восьмерке, а также пути их решения, которые были избраны компанией Oracle. Остальные аспекты можно посмотреть в оригинале.
Читайте дальше:
Расширение существующих API с обратной совместимостью;
Java становится еще более объектно-ориентированной;
Лямбда-выражения в Java;
Упрощение многопоточности.
Итак, что хочет сделать Oracle:
Чтобы упростить всем джавистам жизнь, было решено расширить/дополнить JDK, а также дать возможность всем (в том числе существующим фреймворкам) дополнить свои API. При этом обязательным условием является сохранение работоспособности legacy-кода. Для этого ребята из Oracle сделали виртуальные методы расширения(Virtual extension methods).
Виртуальные методы расширения это методы, которые можно добавить в существующие интерфейсы и предоставить дефолтную реализацию этих методов, при этом классы-реализации не потребуют перекомпиляции и будут работать как и работали раньше. Получаем сохранение работоспособности существующих API с одной стороны и возможность расширить функционал с другой.
Все мы знаем метод remove интерфейса Iterator. В javadoc’е сказано, что если реализация итератора не поддерживает метод remove, то она может выбросить UnsupportedOperationException. Согласитесь, криво. Если я не собираюсь реализовывать метод, то зачем мне определять его и выбрасывать exception?
Здесь определяется дефолтная реализация для метода remove. Теперь классы-реализации не обязаны предоставлять реализацию этого метода.
Допустим, есть код, который определяет наибольший балл среди студентов за 2011 год:
На первый взгляд довольно сносный код. Но он не является объектно-ориентированным. Сама итерация по списку происходит в цикле ‘for’ в клиентском коде, который использует этот список. Можно добавить виртуальные методы в коллекции и переписать этот код используя уже объектно-ориентированный подход и «внутреннюю» итерацию.
Здесь уже итерацию выполняет класс SomeCoolList. Но согласитесь, очень уж это громоздко и многословно. И тут на помощь приходят lambda expression.
Данный подход имеет еще одно преимущество – в нем проще распаралелить выполнение, поскольку проход по коллекции выполняется самой коллекцией.
Поскольку сейчас компьютеры с многоядерными процессорами уже стали нормой, то очевидно, что есть смысл использовать эти самые ядра, т.е. писать многопоточные программы. Поэтому следующее улучшение в JDK 8 это упрощение параллелизма.
Код выше только с использованием многопоточности и виртуальных методов расширения можно переписать следующим образом:
На этом основные мажорные фичи восьмерки заканчиваются.
Также напомню, что скачать JDK Standard Edition 8 Developer Preview with Lambda Support можно здесь.
В статье я попытаюсь вкратце раскрыть основные проблемы, которые будут решены в восьмерке, а также пути их решения, которые были избраны компанией Oracle. Остальные аспекты можно посмотреть в оригинале.
Читайте дальше:
Расширение существующих API с обратной совместимостью;
Java становится еще более объектно-ориентированной;
Лямбда-выражения в Java;
Упрощение многопоточности.
Итак, что хочет сделать Oracle:
I. Расширение существующих API с обратной совместимостью.
Чтобы упростить всем джавистам жизнь, было решено расширить/дополнить JDK, а также дать возможность всем (в том числе существующим фреймворкам) дополнить свои API. При этом обязательным условием является сохранение работоспособности legacy-кода. Для этого ребята из Oracle сделали виртуальные методы расширения(Virtual extension methods).
Виртуальные методы расширения это методы, которые можно добавить в существующие интерфейсы и предоставить дефолтную реализацию этих методов, при этом классы-реализации не потребуют перекомпиляции и будут работать как и работали раньше. Получаем сохранение работоспособности существующих API с одной стороны и возможность расширить функционал с другой.
Пример — Iterator и UnsupportedOperationException.
Все мы знаем метод remove интерфейса Iterator. В javadoc’е сказано, что если реализация итератора не поддерживает метод remove, то она может выбросить UnsupportedOperationException. Согласитесь, криво. Если я не собираюсь реализовывать метод, то зачем мне определять его и выбрасывать exception?
Решение:
interface Iterator<T> {
boolean hasNext();
T next();
void remove()
default { throw new UnsupportedOperationException(); };
}
Здесь определяется дефолтная реализация для метода remove. Теперь классы-реализации не обязаны предоставлять реализацию этого метода.
Пример – итерация по списку.
Допустим, есть код, который определяет наибольший балл среди студентов за 2011 год:
List<Student> students = ...
double highestScore = 0.0;
for (Student s: students) {
if (s.getGradYear() == 2011) {
if (s.getScore() > highestScore) {
highestScore = s.score;
}
}
}
На первый взгляд довольно сносный код. Но он не является объектно-ориентированным. Сама итерация по списку происходит в цикле ‘for’ в клиентском коде, который использует этот список. Можно добавить виртуальные методы в коллекции и переписать этот код используя уже объектно-ориентированный подход и «внутреннюю» итерацию.
SomeCoolList<Student> students = ...
double highestScore =
students.filter(new Predicate<Student>() {
public boolean op(Student s) {
return s.getGradYear() == 2011;
}
}).map(new Mapper<Student, Double>() {
public Double extract(Student s) {
return s.getScore();
}
}).max();
Здесь уже итерацию выполняет класс SomeCoolList. Но согласитесь, очень уж это громоздко и многословно. И тут на помощь приходят lambda expression.
Решение:
SomeCoolList<Student> students = ...
double highestScore =
students.filter(Student s -> s.getGradYear() == 2011)
.map(Student s -> s.getScore())
.max();
Данный подход имеет еще одно преимущество – в нем проще распаралелить выполнение, поскольку проход по коллекции выполняется самой коллекцией.
II. Упрощение многопоточности
Поскольку сейчас компьютеры с многоядерными процессорами уже стали нормой, то очевидно, что есть смысл использовать эти самые ядра, т.е. писать многопоточные программы. Поэтому следующее улучшение в JDK 8 это упрощение параллелизма.
Код выше только с использованием многопоточности и виртуальных методов расширения можно переписать следующим образом:
SomeCoolList<Student> students = ...
double highestScore =
students.parallel()
.filter(Student s -> s.getGradYear() == 2011)
.map(Student s -> s.getScore())
.max();
На этом основные мажорные фичи восьмерки заканчиваются.
Также напомню, что скачать JDK Standard Edition 8 Developer Preview with Lambda Support можно здесь.