[Java] Методы расширения в Java
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В таких языках программирования, как C#, Kotlin, Groovy, Scala есть возможность расширять класс путем добавления нового функционала, при этом не требуется наследование или изменение самого изначального класса. Это реализовано с помощью специальных выражений, называемых расширения. Java, в отличие от этих языков, не имеет такой возможности из коробки и даже не планирует в ближайших релизах. Благодаря Lombok это стало возможным. Методы расширения были реализованы в Lombok еще 8 лет назад (с поддержкой Eclipse), но для многих все упиралось в поддержку плагином в IDEA (код компилировался, но IDE его не распознавала как валидный). Lombok плагин теперь предустановлен в IDEA 2021.1 EAP, и теперь он поддерживает методы расширения lombok (спасибо akozlova, NekoCaffeine и mplushnikov).
Рассмотрим пример классического статического импорта:
import static org.apache.commons.lang3.StringUtils.capitalize;
public class ExtensionMethods {
public static void main(String[] args) {
String str = "test";
String capitalized = capitalize(str);
// "Test"
System.out.println(capitalized);
}
}
при переходе на метод расширения код станет выглядеть так:
import lombok.experimental.ExtensionMethod;
import org.apache.commons.lang3.StringUtils;
@ExtensionMethod(StringUtils.class)
public class ExtensionMethods {
public static void main(String[] args) {
String str = "test";
String capitalized = str.capitalize();
// "Test"
System.out.println(capitalized);
}
}
Заворачивания аргументов в скобки заменяются на цепочки вызовов, т.е. код вида call3(call2(call1(arg))) превратится в
arg.call1()
.call2()
.call3();
Во многих ситуациях это может облегчить чтение кода, особенно когда цепочки длинные, здесь есть некая аналогия со Stream Api или преобразования значения java.util.Optional.
Фактически это просто синтаксический сахар. Код при компиляции будет заменен на вызов статического метода. Первый аргумент статического метода и станет объектом "this".
null-значения
В отличие от обычных instance-методов, методы расширения могут работать и с null-значениями, т.е. подобный вызов вполне допустим:
import org.apache.commons.lang3.StringUtils;
@ExtensionMethod(StringUtils.class)
public class MethodExtensions {
public static void main(String[] args) throws Exception {
String nullStr = null;
// "isEmpty=true"
System.out.println("isEmpty=" + nullStr.trimToEmpty().isEmpty());
}
}
Еще примеры
Можно добавить в проект на JDK 8 метод, который появится только в JDK 11:
@UtilityClass
public class CollectionExtensions {
public static <T> T[] toArray(Collection<T> list, IntFunction<T[]> generator) {
return list.stream().toArray(generator);
}
}
@ExtensionMethod(CollectionExtensions.class)
public class MethodExtensions {
public static void main(String[] args) throws Exception {
List<Integer> list = Arrays.asList(1, 2, 3);
// toArray(IntFunction<T[]>) добавлен только в Java 11
Integer[] array = list.toArray(Integer[]::new);
// "[1, 2, 3]"
System.out.println(Arrays.toString(array));
}
}
Или добавить более лаконичный вызов Stream.collect(toList()):
@UtilityClass
public class StreamExtensions {
public static <T> List<T> toList(Stream<T> stream) {
return stream.collect(Collectors.toList());
}
}
@ExtensionMethod(CollectionExtensions.class)
public class MethodExtensions {
public static void main(String[] args) throws Exception {
List<Integer> list = Arrays.asList(3, 1, 2);
List<Integer> sorted = list.stream()
.sorted()
.toList();
// "[1, 2, 3]"
System.out.println(sorted);
}
}
Настройка проекта
- Установите последнюю версию IDEA EAP, важно: EAP версии не стабильны, зато бесплатны. Плагин доступен и в Ultimate, и в Community Edition.
- Добавьте зависимость lombok: maven
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
либо для gradle:
compileOnly 'org.projectlombok:lombok:1.18.16'
annotationProcessor 'org.projectlombok:lombok:1.18.16'
testCompileOnly 'org.projectlombok:lombok:1.18.16'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'
- Убедитесь, что включена опция проекта Build, Execution, Deployment -> Compiler -> Annotations processor -> Enable annotation processing
- Добавьте аннотацию @ExtensionMethod на класс (откуда будет вызов), перечисляя все утилитные классы, из которых необходимо импортировать вызовы.
===========
Источник:
habr.com
===========
Похожие новости:
- [Java, Параллельное программирование] Реактивное программирование на Java: как, зачем и стоит ли? Часть I
- [Программирование, Java, Совершенный код, C#, Kotlin] Лучший язык программирования
- [Open source, Java, Scala, Apache, Natural Language Processing] Программируемые NER компоненты
- [JavaScript, ООП] Создание квадратизированной галереи проектов на JS v 2.0
- [Ненормальное программирование, JavaScript, Разработка игр] Свежий взгляд на честное 3D в браузере
- [JavaScript, Программирование] Полезные расширения VS Code для JavaScript-разработчиков (перевод)
- [JavaScript, Программирование, Управление проектами, Управление продуктом, Карьера в IT-индустрии] Pet-проект для джуна. Или зачем и как выбрать pet project. (+личный опыт)
- [Информационная безопасность, Антивирусная защита, Разработка под MacOS] На 30 тысячах компьютеров с macOS нашли странный зловред, который ждёт команду
- [Разработка веб-сайтов, JavaScript, Программирование] Тотальный JavaScript: изучаем JS с акцентом на практической составляющей
- [Программирование, Java, ООП] Java Core для самых маленьких. Часть 3. Переменные
Теги для поиска: #_java, #_java, #_lombok, #_extension_methods, #_java
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:57
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В таких языках программирования, как C#, Kotlin, Groovy, Scala есть возможность расширять класс путем добавления нового функционала, при этом не требуется наследование или изменение самого изначального класса. Это реализовано с помощью специальных выражений, называемых расширения. Java, в отличие от этих языков, не имеет такой возможности из коробки и даже не планирует в ближайших релизах. Благодаря Lombok это стало возможным. Методы расширения были реализованы в Lombok еще 8 лет назад (с поддержкой Eclipse), но для многих все упиралось в поддержку плагином в IDEA (код компилировался, но IDE его не распознавала как валидный). Lombok плагин теперь предустановлен в IDEA 2021.1 EAP, и теперь он поддерживает методы расширения lombok (спасибо akozlova, NekoCaffeine и mplushnikov). Рассмотрим пример классического статического импорта: import static org.apache.commons.lang3.StringUtils.capitalize;
public class ExtensionMethods { public static void main(String[] args) { String str = "test"; String capitalized = capitalize(str); // "Test" System.out.println(capitalized); } } при переходе на метод расширения код станет выглядеть так: import lombok.experimental.ExtensionMethod;
import org.apache.commons.lang3.StringUtils; @ExtensionMethod(StringUtils.class) public class ExtensionMethods { public static void main(String[] args) { String str = "test"; String capitalized = str.capitalize(); // "Test" System.out.println(capitalized); } } Заворачивания аргументов в скобки заменяются на цепочки вызовов, т.е. код вида call3(call2(call1(arg))) превратится в arg.call1()
.call2() .call3(); Во многих ситуациях это может облегчить чтение кода, особенно когда цепочки длинные, здесь есть некая аналогия со Stream Api или преобразования значения java.util.Optional. Фактически это просто синтаксический сахар. Код при компиляции будет заменен на вызов статического метода. Первый аргумент статического метода и станет объектом "this". null-значения В отличие от обычных instance-методов, методы расширения могут работать и с null-значениями, т.е. подобный вызов вполне допустим: import org.apache.commons.lang3.StringUtils;
@ExtensionMethod(StringUtils.class) public class MethodExtensions { public static void main(String[] args) throws Exception { String nullStr = null; // "isEmpty=true" System.out.println("isEmpty=" + nullStr.trimToEmpty().isEmpty()); } } Еще примеры Можно добавить в проект на JDK 8 метод, который появится только в JDK 11: @UtilityClass
public class CollectionExtensions { public static <T> T[] toArray(Collection<T> list, IntFunction<T[]> generator) { return list.stream().toArray(generator); } } @ExtensionMethod(CollectionExtensions.class) public class MethodExtensions { public static void main(String[] args) throws Exception { List<Integer> list = Arrays.asList(1, 2, 3); // toArray(IntFunction<T[]>) добавлен только в Java 11 Integer[] array = list.toArray(Integer[]::new); // "[1, 2, 3]" System.out.println(Arrays.toString(array)); } } Или добавить более лаконичный вызов Stream.collect(toList()): @UtilityClass
public class StreamExtensions { public static <T> List<T> toList(Stream<T> stream) { return stream.collect(Collectors.toList()); } } @ExtensionMethod(CollectionExtensions.class) public class MethodExtensions { public static void main(String[] args) throws Exception { List<Integer> list = Arrays.asList(3, 1, 2); List<Integer> sorted = list.stream() .sorted() .toList(); // "[1, 2, 3]" System.out.println(sorted); } } Настройка проекта
<dependency>
<groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> <scope>provided</scope> </dependency> либо для gradle: compileOnly 'org.projectlombok:lombok:1.18.16'
annotationProcessor 'org.projectlombok:lombok:1.18.16' testCompileOnly 'org.projectlombok:lombok:1.18.16' testAnnotationProcessor 'org.projectlombok:lombok:1.18.16'
=========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 15:57
Часовой пояс: UTC + 5