Project Lombok으로 무지방 Java 코드 작성

게시 됨: 2022-03-11

요즘 내가 없이는 Java 코드를 작성하는 것을 상상할 수 없는 많은 도구와 라이브러리가 있습니다. 전통적으로 Google Guava 또는 Joda Time(적어도 Java 8 이전 시대)은 특정 도메인에 관계없이 대부분의 경우 내 프로젝트에 던지게 되는 종속성 중 하나입니다.

Lombok은 일반적인 라이브러리/프레임워크 유틸리티는 아니지만 내 POM 또는 Gradle 빌드에서도 그 자리를 차지할 가치가 있습니다. Lombok은 2009년에 처음 출시된 지 꽤 오래되었고 그 이후로 많이 발전했습니다. 그러나 저는 항상 더 많은 관심을 기울일 가치가 있다고 느꼈습니다. Java의 자연스러운 장황함을 처리하는 놀라운 방법입니다.

이 포스트에서 우리는 Lombok이 그토록 편리한 도구가 되는 이유를 탐구할 것입니다.

프로젝트 롬복

Java에는 놀라운 소프트웨어인 JVM 자체 외에도 많은 기능이 있습니다. Java는 성숙하고 성능이 뛰어나며 Java를 둘러싼 커뮤니티와 생태계는 거대하고 활발합니다.

그러나 프로그래밍 언어로서 Java에는 고유한 특성이 있으며 다소 장황하게 만들 수 있는 디자인 선택 사항이 있습니다. Java 개발자가 자주 사용해야 하는 일부 구성 및 클래스 패턴을 추가하면 일부 제약 조건 또는 프레임워크 규칙을 준수하는 것 외에는 실제 가치를 거의 또는 전혀 제공하지 않는 많은 코드 라인으로 끝나는 경우가 많습니다.

여기에서 롬복이 등장합니다. 이를 통해 작성해야 하는 "보일러 플레이트" 코드의 양을 크게 줄일 수 있습니다. Lombok의 제작자는 매우 똑똑한 두 사람이며 확실히 유머 감각이 있습니다. 지난 회의에서 만든 이 소개를 놓칠 수 없습니다!

Lombok이 마법을 부리는 방법과 몇 가지 사용 예를 살펴보겠습니다.

롬복 작동 원리

Lombok은 컴파일 타임에 클래스에 코드를 "추가"하는 주석 처리기 역할을 합니다. 주석 처리는 버전 5에서 Java 컴파일러에 추가된 기능입니다. 아이디어는 사용자가 주석 프로세서(자신이 작성하거나 Lombok과 같은 타사 종속성을 통해 작성)를 빌드 클래스 경로에 넣을 수 있다는 것입니다. 그런 다음 컴파일 프로세스가 진행되면서 컴파일러가 주석을 찾을 때마다 "이 @Annotation에 관심이 있는 클래스 경로의 사람이 있습니까?"라고 묻습니다. 손을 들고 있는 프로세서의 경우 컴파일러는 컴파일 컨텍스트와 함께 제어를 프로세서에 전달합니다.

주석 처리기의 가장 일반적인 경우는 새 소스 파일을 생성하거나 일종의 컴파일 시간 검사를 수행하는 것입니다.

Lombok은 실제로 다음 범주에 속하지 않습니다. Lombok이 하는 일은 코드를 나타내는 데 사용되는 컴파일러 데이터 구조를 수정하는 것입니다. 즉, 추상 구문 트리(AST)입니다. 컴파일러의 AST를 수정하여 Lombok은 최종 바이트 코드 생성 자체를 간접적으로 변경합니다.

이 독특하고 오히려 방해가 되는 접근 방식으로 인해 전통적으로 Lombok은 일종의 해킹으로 간주되었습니다. 나 자신도 이 특성화에 어느 정도 동의하지만, 이것을 나쁜 의미로 보기보다는 Lombok을 "영리하고 기술적으로 우수하며 독창적인 대안"으로 볼 것입니다.

그래도 해킹으로 생각하고 이런 이유로 롬복을 사용하지 않는 개발자들이 있습니다. 그것은 이해할 수 있지만 내 경험에 따르면 Lombok의 생산성 이점은 이러한 우려보다 더 큽니다. 나는 수년 동안 프로덕션 프로젝트에 행복하게 사용하고 있습니다.

자세히 설명하기 전에 내 프로젝트에서 Lombok을 사용하는 것을 특히 중요하게 생각하는 두 가지 이유를 요약하고 싶습니다.

  1. Lombok은 코드를 깨끗하고 간결하며 요점으로 유지하는 데 도움이 됩니다. 내 Lombok 주석 클래스는 매우 표현력이 풍부하고 일반적으로 주석이 달린 코드가 의도를 드러낸다는 것을 알지만 인터넷의 모든 사람이 반드시 동의하는 것은 아닙니다.
  2. 프로젝트를 시작할 때 도메인 모델을 생각할 때 진행 중인 작업이 많은 클래스를 작성하는 것으로 시작하는 경향이 있으며 더 생각하고 수정하면서 반복적으로 변경합니다. 이러한 초기 단계에서 Lombok은 이동하거나 생성하는 상용구 코드를 변환할 필요가 없어 더 빠르게 이동할 수 있도록 도와줍니다.

Bean 패턴 및 공통 객체 메소드

우리가 사용하는 많은 Java 도구와 프레임워크는 Bean Pattern에 의존합니다. Java Beans는 기본적으로 인수가 없는 생성자(및 다른 버전도 가능)가 있고 일반적으로 개인 필드가 지원하는 getter 및 setter를 통해 상태를 노출하는 직렬화 가능한 클래스입니다. 예를 들어 JAXB 또는 Jackson과 같은 직렬화 프레임워크 또는 JPA로 작업할 때 이러한 항목을 많이 작성합니다.

최대 5개의 속성(속성)을 보유하는 이 사용자 빈을 고려하십시오. 여기에는 모든 속성, 의미 있는 문자열 표현에 대한 추가 생성자가 있고 이메일 필드 측면에서 동등/해싱을 정의하고 싶습니다.

 public class User implements Serializable { private String email; private String firstName; private String lastName; private Instant registrationTs; private boolean payingCustomer; // Empty constructor implementation: ~3 lines. // Utility constructor for all attributes: ~7 lines. // Getters/setters: ~38 lines. // equals() and hashCode() as per email: ~23 lines. // toString() for all attributes: ~3 lines. // Relevant: 5 lines; Boilerplate: 74 lines => 93% meaningless code :( }

여기서는 간결함을 위해 모든 메서드의 실제 구현을 포함하는 대신 메서드와 실제 구현에 사용된 코드 줄 수를 나열하는 주석을 제공했습니다. 그 상용구 코드는 이 클래스에 대한 코드의 90% 이상을 합쳤을 것입니다!

또한 나중에 emailemailAddress 로 변경하거나 registrationTsInstant 대신 Date 가 되도록 하려면 시간을 할애해야 합니다. / 메서드 이름 및 유형 설정, 유틸리티 생성자 수정 등. 다시 말하지만, 내 코드에 실질적인 비즈니스 가치를 제공하지 않는 것에 대한 귀중한 시간입니다.

Lombok이 여기에서 어떻게 도움이 되는지 봅시다.

 import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.ToString; @Getter @Setter @NoArgsConstructor @AllArgsConstructor @ToString @EqualsAndHashCode(of = {"email"}) public class User { private String email; private String firstName; private String lastName; private Instant registrationTs; private boolean payingCustomer; }

짜잔! 방금 많은 lombok.* 주석을 추가하고 원하는 것을 얻었습니다. 위의 목록은 정확히 내가 작성해야 하는 모든 코드입니다. Lombok은 내 컴파일러 프로세스에 연결되어 나를 위해 모든 것을 생성했습니다(내 IDE의 아래 스크린샷 참조).

IDE 스크린샷

알다시피 NetBeans 검사기(IDE와 상관없이 발생)는 Lombok이 프로세스에 추가한 항목을 포함하여 컴파일된 클래스 바이트코드를 감지합니다. 여기서 일어난 일은 매우 간단합니다.

  • @Getter@Setter 를 사용하여 Lombok에 모든 속성에 대한 getter 및 setter를 생성하도록 지시했습니다. 클래스 수준에서 주석을 사용했기 때문입니다. 어떤 속성에 대해 무엇을 생성할지 선택적으로 지정하려면 필드 자체에 주석을 달 수 있었습니다.
  • @NoArgsConstructor@AllArgsConstructor 덕분에 내 클래스에 대한 기본 빈 생성자와 모든 속성에 대한 추가 생성자를 얻었습니다.
  • @ToString 주석은 기본적으로 이름이 접두사로 붙은 모든 클래스 속성을 표시하는 편리한 toString() 메서드를 자동 생성합니다.
  • 마지막으로 이메일 필드와 관련하여 정의된 equals()hashCode() 메서드 쌍을 갖도록 @EqualsAndHashCode 를 사용하고 관련 필드 목록(이 경우 이메일만)으로 매개변수화했습니다.

롬복 주석 사용자 정의

이제 이 동일한 예에 따라 일부 Lombok 사용자 지정을 사용하겠습니다.

  • 기본 생성자의 가시성을 낮추고 싶습니다. Bean 준수를 위해서만 필요하기 때문에 클래스의 소비자는 모든 필드를 사용하는 생성자만 호출할 것으로 예상합니다. 이를 적용하기 위해 생성된 생성자를 AccessLevel.PACKAGE 로 사용자 지정합니다.
  • 내 필드에 생성자나 setter 메서드를 통해 null 값이 할당되지 않도록 하고 싶습니다. @NonNull 로 클래스 속성에 주석을 다는 것으로 충분합니다. Lombok은 생성자 및 설정자 메서드에서 적절한 경우 NullPointerException 을 발생시키는 null 검사를 생성합니다.
  • password 속성을 추가할 것이지만 보안상의 이유로 toString() 을 호출할 때 표시되는 것을 원하지 않습니다. 이것은 @ToString 의 exclude 인수를 통해 수행됩니다.
  • getter를 통해 공개적으로 상태를 노출하는 것은 괜찮지만 외부 변경 가능성을 제한하는 것을 선호합니다. 그래서 @Getter를 그대로 두고 @GetterAccessLevel.PROTECTED 를 다시 사용 @Setter .
  • 아마도 email 필드에 일부 제약을 적용하여 수정되면 일종의 검사가 실행되도록 하고 싶습니다. 이를 위해 setEmail() 메서드를 직접 구현합니다. Lombok은 이미 존재하는 메소드에 대한 생성을 생략합니다.

User 클래스는 다음과 같이 표시됩니다.

 import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.ToString; @Getter @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PACKAGE) @AllArgsConstructor @ToString(exclude = {"password"}) @EqualsAndHashCode(of = {"email"}) public class User { private @NonNull String email; private @NonNull byte[] password; private @NonNull String firstName; private @NonNull String lastName; private @NonNull Instant registrationTs; private boolean payingCustomer; protected void setEmail(String email) { // Check for null (=> NullPointerException) // and valid email code (=> IllegalArgumentException) this.email = email; } }

일부 주석의 경우 클래스 속성을 일반 문자열로 지정하고 있습니다. 문제가 되지 않습니다. 예를 들어 유형이 잘못되었거나 존재하지 않는 필드를 참조하는 경우 Lombok에서 컴파일 오류가 발생하기 때문입니다. 롬복과 함께라면 우리는 안전합니다.

또한 setEmail() 메서드와 마찬가지로 Lombok은 괜찮을 것이며 프로그래머가 이미 구현한 메서드에 대해서는 아무 것도 생성하지 않습니다. 이것은 모든 메서드와 생성자에 적용됩니다.

불변 데이터 구조

Lombok이 탁월한 또 다른 사용 사례는 변경할 수 없는 데이터 구조를 생성할 때입니다. 이를 일반적으로 "값 유형"이라고 합니다. 일부 언어에는 이를 지원하는 기능이 내장되어 있으며 이를 향후 Java 버전에 통합하는 제안도 있습니다.

사용자 로그인 작업에 대한 응답을 모델링한다고 가정합니다. 이것은 우리가 인스턴스화하고 애플리케이션의 다른 계층으로 반환하려는 종류의 객체입니다(예: HTTP 응답의 본문으로 JSON 직렬화). 이러한 LoginResponse는 변경할 필요가 전혀 없으며 Lombok은 이를 간결하게 설명하는 데 도움이 될 수 있습니다. 물론, 변경할 수 없는 데이터 구조에 대한 다른 많은 사용 사례가 있지만(특히 다중 스레딩 및 캐시 친화적임) 다음과 같은 간단한 예를 살펴보겠습니다.

 import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.ToString; import lombok.experimental.Wither; @Getter @RequiredArgsConstructor @ToString @EqualsAndHashCode public final class LoginResponse { private final long userId; private final @NonNull String authToken; private final @NonNull Instant loginTs; @Wither private final @NonNull Instant tokenExpiryTs; }

여기서 주목할 가치:

  • @RequiredArgsConstructor 주석이 도입되었습니다. 적절하게 명명된 이 기능은 아직 초기화되지 않은 모든 최종 필드에 대한 생성자를 생성합니다.
  • 이전에 발행된 LoginResonse를 재사용하려는 경우(예: "새로 고침 토큰" 작업을 상상해보십시오), 우리는 확실히 기존 인스턴스를 수정하고 싶지 않고 오히려 이를 기반으로 새 인스턴스를 생성하기를 원합니다. . @Wither 주석이 여기에서 어떻게 도움이 되는지 확인하세요. 이것은 우리가 지정하는 새 값을 제외하고 모든 포함된 인스턴스 값을 갖는 LoginResponse의 새 인스턴스를 생성하는 withTokenExpiryTs(Instant tokenExpiryTs) 메서드를 생성하도록 Lombok에 지시합니다. 모든 필드에 대해 이 동작을 하시겠습니까? 대신 클래스 선언에 @Wither 를 추가하기만 하면 됩니다.

@데이터 및 @값

지금까지 논의된 두 가지 사용 사례는 매우 일반적이어서 Lombok은 두 개의 주석을 제공하여 더 짧게 만듭니다. @Data 로 클래스에 주석을 다는 것은 Lombok이 @Getter + @Setter + @ToString +로 주석이 달린 것처럼 동작하도록 트리거합니다. @EqualsAndHashCode + @RequiredArgsConstructor . 마찬가지로 @Value 를 사용하면 클래스가 변경할 수 없는(최종) 클래스로 바뀌며, 위의 목록으로 주석이 추가된 것처럼 다시 한 번 나타납니다.

빌더 패턴

사용자 예제로 돌아가서 새 인스턴스를 생성하려면 최대 6개의 인수가 있는 생성자를 사용해야 합니다. 이것은 이미 상당히 많은 수이며, 클래스에 속성을 더 추가하면 더 나빠질 것입니다. 또한 lastNamepayingCustomer 필드에 대한 일부 기본값을 설정하려고 한다고 가정합니다.

Lombok은 매우 강력한 @Builder 기능을 구현하므로 Builder 패턴을 사용하여 새 인스턴스를 만들 수 있습니다. User 클래스에 추가해 보겠습니다.

 import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.ToString; @Getter @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PACKAGE) @AllArgsConstructor @ToString(exclude = {"password"}) @EqualsAndHashCode(of = {"email"}) @Builder public class User { private @NonNull String email; private @NonNull byte[] password; private @NonNull String firstName; private @NonNull String lastName = ""; private @NonNull Instant registrationTs; private boolean payingCustomer = false; }

이제 다음과 같이 새 사용자를 유창하게 생성할 수 있습니다.

 User user = User .builder() .email("[email protected]") .password("secret".getBytes(StandardCharsets.UTF_8)) .firstName("Miguel") .registrationTs(Instant.now()) .build();

클래스가 성장함에 따라 이 구성이 얼마나 편리해졌는지 상상하기 쉽습니다.

위임/구성

"상속보다 구성 선호"라는 매우 정상적인 규칙을 따르고 싶다면 Java가 실제로 도움이 되지 않는 것입니다. 객체를 구성하려면 일반적으로 모든 곳에서 위임 메서드 호출을 작성해야 합니다.

Lombok은 @Delegate 를 통해 이에 대한 솔루션을 제안합니다. 예를 들어 보겠습니다.

ContactInformation 의 새로운 개념을 도입한다고 상상해보십시오. 이것은 User 가 가지고 있는 일부 정보이며 다른 클래스도 갖고 싶어할 수 있습니다. 그런 다음 다음과 같은 인터페이스를 통해 이를 모델링할 수 있습니다.

 public interface HasContactInformation { String getEmail(); String getFirstName(); String getLastName(); }

그런 다음 Lombok을 사용하여 새로운 ContactInformation 클래스를 소개합니다.

 import lombok.Data; @Data public class ContactInformation implements HasContactInformation { private String email; private String firstName; private String lastName; }

마지막으로 UserContactInformation 으로 구성하고 Lombok을 사용하여 인터페이스 계약과 일치하는 데 필요한 모든 위임 호출을 생성하도록 리팩토링할 수 있습니다.

 import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.Setter; import lombok.ToString; import lombok.experimental.Delegate; @Getter @Setter(AccessLevel.PROTECTED) @NoArgsConstructor(access = AccessLevel.PACKAGE) @AllArgsConstructor @ToString(exclude = {"password"}) @EqualsAndHashCode(of = {"contactInformation"}) public class User implements HasContactInformation { @Getter(AccessLevel.NONE) @Delegate(types = {HasContactInformation.class}) private final ContactInformation contactInformation = new ContactInformation(); private @NonNull byte[] password; private @NonNull Instant registrationTs; private boolean payingCustomer = false; }

HasContactInformation 메서드에 대한 구현을 작성할 필요가 없었음을 주목하십시오. 이것은 우리가 Lombok에 지시하여 ContactInformation 인스턴스에 대한 호출을 위임하는 것입니다.

또한 위임된 인스턴스가 외부에서 액세스되는 것을 원하지 않기 때문에 @Getter(AccessLevel.NONE) 으로 사용자 지정하여 효과적으로 getter 생성을 방지합니다.

확인된 예외

우리 모두 알다시피 Java는 확인된 예외와 확인되지 않은 예외를 구분합니다. 이것은 예외 처리가 때때로 너무 많은 결과를 초래하기 때문에 언어에 대한 논쟁과 비판의 전통적인 소스입니다. 특히 확인된 예외를 throw하도록 설계된 API를 처리하여 개발자가 예외를 포착하거나 메소드를 선언하도록 강요할 때 그들을 던져.

다음 예를 고려하십시오.

 public class UserService { public URL buildUsersApiUrl() { try { return new URL("https://apiserver.com/users"); } catch (MalformedURLException ex) { // Malformed? Really? throw new RuntimeException(ex); } } }

이것은 매우 일반적인 패턴입니다. 우리는 URL이 잘 구성되어 있다는 것을 확실히 알고 있지만 URL 생성자가 확인된 예외를 발생시키기 때문에 강제로 catch하거나 메서드를 선언하여 예외를 throw하고 호출자를 동일한 상황에서 내보내야 합니다. 이러한 확인된 예외를 RuntimeException 내부에 래핑하는 것은 매우 확장된 방법입니다. 그리고 코드를 작성하면서 처리해야 하는 확인된 예외의 수가 증가하면 상황은 더욱 악화됩니다.

이것이 Lombok의 @SneakyThrows 가 정확히 무엇을 위한 것인지, 우리 메서드에서 던져질 체크된 예외를 체크되지 않은 예외로 래핑하고 번거로움에서 우리를 해방시킵니다.

 import lombok.SneakyThrows; public class UserService { @SneakyThrows public URL buildUsersApiUrl() { return new URL("https://apiserver.com/users"); } }

벌채 반출

이런 식으로 클래스에 로거 인스턴스를 얼마나 자주 추가합니까? (SLF4J 샘플)

 private static final Logger LOG = LoggerFactory.getLogger(UserService.class);

어느정도 짐작이 갑니다. 이를 알고 Lombok의 작성자는 사용자 지정 가능한 이름(기본값은 log)으로 로거 인스턴스를 생성하는 주석을 구현하여 Java 플랫폼에서 가장 일반적인 로깅 프레임워크를 지원합니다. 다음과 같이(다시 SLF4J 기반):

 import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @Slf4j public class UserService { @SneakyThrows public URL buildUsersApiUrl() { log.debug("Building users API URL"); return new URL("https://apiserver.com/users"); } }

생성된 코드에 주석 달기

Lombok을 사용하여 코드를 생성하는 경우 실제로 작성하지 않기 때문에 해당 메서드에 주석을 달 수 있는 기능을 상실하는 것처럼 보일 수 있습니다. 그러나 이것은 사실이 아닙니다. 오히려, Lombok을 사용하면 생성된 코드에 주석을 달기 원하는 방법을 말할 수 있지만 다소 특이한 표기법을 사용하여 사실을 알 수 있습니다.

종속성 주입 프레임워크의 사용을 대상으로 하는 이 예제를 고려하십시오. 생성자 주입을 사용하여 UserRepositoryUserApiClient 에 대한 참조를 가져오는 UserService 클래스가 있습니다.

 package com.mgl.toptal.lombok; import javax.inject.Inject; import lombok.RequiredArgsConstructor; @RequiredArgsConstructor(onConstructor = @__(@Inject)) public class UserService { private final UserRepository userRepository; private final UserApiClient userApiClient; // Instead of: // // @Inject // public UserService(UserRepository userRepository, // UserApiClient userApiClient) { // this.userRepository = userRepository; // this.userApiClient = userApiClient; // } }

위의 샘플은 생성된 생성자에 주석을 추가하는 방법을 보여줍니다. Lombok을 사용하면 생성된 메서드와 매개변수에 대해서도 동일한 작업을 수행할 수 있습니다.

더 알아보기

이 게시물에서 설명하는 Lombok 사용법은 개인적으로 몇 년 동안 가장 유용하다고 생각한 기능에 중점을 둡니다. 그러나 다른 많은 기능과 사용자 정의를 사용할 수 있습니다.

Lombok의 문서는 매우 유익하고 철저합니다. 모든 단일 기능(주석)에 대한 전용 페이지가 있으며 매우 자세한 설명과 예제가 있습니다. 이 게시물이 흥미롭다면 롬복과 관련 문서에 대해 더 자세히 알아보시기 바랍니다.

프로젝트 사이트는 다양한 프로그래밍 환경에서 Lombok을 사용하는 방법을 문서화합니다. 간단히 말해서 가장 인기 있는 IDE(Eclipse, NetBeans 및 IntelliJ)가 지원됩니다. 나는 정기적으로 프로젝트별로 하나에서 다른 것으로 전환하고 모든 프로젝트에서 Lombok을 완벽하게 사용합니다.

델롬복!

Delombok은 "Lombok 도구 체인"의 일부이며 매우 편리할 수 있습니다. 기본적으로 Lombok에서 생성한 바이트코드와 동일한 작업을 수행하여 Lombok 주석 코드에 대한 Java 소스 코드 를 생성합니다.

이것은 Lombok 채택을 고려하고 있지만 아직 확실하지 않은 사람들에게 훌륭한 옵션입니다. 자유롭게 사용할 수 있으며 "공급업체 종속"이 없습니다. 나중에 귀하 또는 귀하의 팀이 선택을 후회하는 경우 항상 delombok을 사용하여 해당 소스 코드를 생성한 다음 Lombok에 대한 종속성 없이 사용할 수 있습니다.

Delombok은 또한 Lombok이 무엇을 할 것인지 정확히 배울 수 있는 훌륭한 도구입니다. 빌드 프로세스에 연결하는 매우 쉬운 방법이 있습니다.

대안

Java 세계에는 Immutables 또는 Google Auto Value와 같이 컴파일 시간에 코드를 강화하거나 수정하기 위해 주석 프로세서를 유사하게 사용하는 많은 도구가 있습니다. 이것들(그리고 다른 것들도 확실히!)은 기능면에서 롬복과 겹칩니다. 저는 특히 Immutables 접근 방식을 많이 좋아하고 일부 프로젝트에서도 사용했습니다.

Byte Buddy 또는 Javassist와 같이 "바이트 코드 향상"을 위해 유사한 기능을 제공하는 다른 훌륭한 도구가 있다는 점도 주목할 가치가 있습니다. 이것들은 일반적으로 런타임에 작동하며 이 게시물의 범위를 넘어서는 자체 세계를 구성합니다.

간결한 자바

동일한 문제를 해결하는 데 도움이 되는 보다 관용적이거나 언어 수준의 디자인 접근 방식을 제공하는 최신 JVM 대상 언어가 많이 있습니다. 확실히 Groovy, Scala 및 Kotlin이 좋은 예입니다. 그러나 Java 전용 프로젝트에서 작업하는 경우 Lombok은 프로그램을 보다 간결하고 표현력 있고 유지 관리할 수 있도록 도와주는 훌륭한 도구입니다.

관련: Dart 언어: Java 및 C#이 충분히 날카롭지 않을 때