이펙티브자바, 38. 확장할 수 있는 열거 타입이 필요하면 인터페이스를 사용하라

열거 타입과 인터페이스 열거 타입은 인터페이스를 구현할 수 있고, 이를 통해 확장 가능하다. 인터페이스는 표준 구현체 역할을 하며, 해당 값을 매개변수로 활용하는 등 유연하게 사용 가능하다.

이펙티브자바, 35-38. 열거 타입 사용에서의 팁들, ordinal(), EnumSet, EnumMap

35. ordinal 메서드 대신 인스턴스 필드를 사용하라 enum은 ordinal()을 제공하며, 이것은 각각의 상수를 숫자로 관리하는 기능이다. 이 기능은 상수의 변화에 따라 가변적이기 때문에 사용해서는 안된다. 만약 정수를 사용하고 싶다면 ordinal()이 아닌 필드를 사용해야 한다.

이펙티브 자바, 34. int 상수 대신 열거 타입을 사용하라

열거타입과 기존 열거 패턴의 문제점 열거타입, enum은 일정 개수의 상수를 정의한 다음, 그 외의 값을 허용하지 않는 타입이다. 기존에는 아래와 같은 방식으로 정수 상수를 정의하였다.

이펙티브자바, 31. 한정적 와일드카드를 사용해 API 유연성을 높이라

와일드카드와 extends, super 제네릭 는 불공변이다. E의 매개변수가 Number이며 실제 삽입되는 인자가 그것의 하위 타입인 Interger라 하더라도, 형변환이 허용되지 않는다. 와일드카드 <?>는 데이터에 대한 비교와 더불어 형변환을 위한 기능도 제공한다. 아래의 코드를 사용하여 하위타입에 대한 유연성을 높혀준다. <? extends E> 생산자 <? super E> 소비자 전자는 매개변수가 생산자일 때 동작하며, 생산자란 데이터를 내보내는 경우를 의미한다. 후자는 매개변수가 소비자일 때 동작하며, 소비자란 데이터를 변경하는 경우를 의미한다. 기본 행태의 와일드 카드<?>로 받은 인자의 데이타를 변경할 수 없는 것과 대비하여, <? super E>는 그것의 인자의 데이터를 변경할 수 있다. 해당 코드는 아래와 같다. Stack을 활용한다.

이펙티브자바, 30. 이왕이면 제네릭 메서드로 만들라

이왕이면 제네릭 메서드 제네릭 타입으로 클래스를 작성하듯, 이왕이면 제네릭 메서드를 작성한다. 첫 번째는 제네릭이 없고 두 번째는 제네릭이 있다.

이펙티브자바, 29. 이왕이면 제네릭 타입으로 만들라

기왕이면 제네릭으로 스택 등 자료구조의 경우 배열의 요소를 특정 객체에 의존하거나 Object로 호환성을 높히는 경우가 있다. 전자의 경우 범용성이 떨어진다. 후자의 경우 해당 자료구조 밖에서 형변환을 해야하는 문제가 발생한다. 형변환의 잘못으로 인한 예외를 런타임에서 부담해야 한다.

이펙티브자바, 28. 배열보다는 리스트를 사용하라

배열과 리스트의 차이 배열의 경우 Sub[] 이 Super[] 의 하위타입이 된다. 그러니까 Object[] 가 String[] 의 하위타입이 된다. 이러한 배열의 특성 때문에 문법 상 맞지 않는 코드가 컴파일 과정에서 승인된다. 그리고 런타임 과정에서 예외가 발생한다. 리스트, 정확히 제너릭 클래스와 인터페이스는, 컴파일 시점에서 타입이 맞지 않는 코드에 대하여 에러를 던진다. 추가적으로 Object[] 타입으로 String[]이 초기화되는 것과 달리, 제네릭 클래스와 인터페이스는 상위/하위타입으로 타입변화가 허용되지 않는다. 타입의 표현력과 안정성문제로 배열보다는 리스트가 선호된다.

이펙티브자바, 27. 비검사 경고를 제거하라

제네릭의 컴파일 경고 제네릭타입을 사용할 경우 컴파일러의 경고를 확인할 수 있다. 컴파일러의 경고를 최대한 해소한다. 컴파일러의 경고에도 불구하고 문제가 없음이 확실하다면 @SuppressWarnings 어너테이션으로 경고를 없앤다. @SuppressWarnings을 사용하면 컴파일 시점에서 제너릭과 관련한 에러를 누락한다. 하지만 런타임 시점에서 컴파일러의 우려대로 예외가 발생할 수 있다.

이펙티브자바, 26. 로 타입은 사용하지 마라

제네릭 타입과 제네릭 매개변수의 정의 클래스와 인터페이스를 선언할 때 타입 매개변수가 쓰이면, 이를 제네릭 클래스 혹은 제네릭 인터페이스라 한다. 이를 통틀어서 제네릭 타입이라 한다. 제네릭 타입은 매개변수화 타입(parameterized type)을 정의한다.

java, 중첩 클래스의 기본 - inner class와 nested class와 사용

중첩 클래스란? 클래스 내부에 선언하는 클래스를 중첩 클래스라 한다. 장점으로는, 두 클래스간 필드에 서로 쉽게 접근할 수 있으며, 외부에 불필요한 클래스를 감추며 코드의 복잡성을 줄인다. 중첩클래스는 클래스와 인터페이스 모두에서 사용할 수 있다. 중첩 클래스는 인스턴스 맴버클래스와 정적 맴버클래스가 있다. 그리고 메서드 안에서 선언되는 로컬 클래스가 있다.

java, 클래스와 인터페이스의 기본 - 접근제어와 안전한 작성

들어가며 이펙티브 자바에서 클래스/메서드 파트를 공부를 공부할 때 자바 기본 지식에 대한 부족함을 느꼈다. 신용권 개발자님의 이것이 자바다를 참고하였다.

이펙티브자바, 23 태그 달린 클래스보다는 클래스 계층구조를 활용하라

태그 주석으로 설명하지 말고 코드로 설명하라 하나의 클래스에 여러 개의 내용이 있고 복잡한 경우 주석을 통해 복잡하게 설명하는 경우가 있다.

이펙티브자바, 21-22 인터페이스의 default 메서드 주의점, 상수 인터페이스 지양

21 인터페이스는 구현하는 쪽을 생각해 설계하라 : java 8, default method 자바 7까지는 interface는 구현된 메서드가 존재하지 않았다. 그러나 자바 8 부터 default 메서드가 생겼다. default는 코드 품질이 높고 범용적이라 대부분의 상황에서 잘 작동한다. 하지만 모든 상황에서 불변식을 해치지 않는다고 보장할 수 없다. default를 고려하지 않은 어떤 구현체는, 자바 8 이후 새롭게 릴리즈 된 인터페이스의 default를 호출할 때, 런타임 에러가 발생하곤 한다. default를 재정의하는 등, 보완책이 존재한다. 하지만 어떤 문제가 발생할지 모르기 때문에 default 메서드를 추가하여 릴리즈 하는 것은 신중해야 한다. 새롭게 인터페이스를 구현한다면 default는 구현체를 고려하여 잘 작성한다.

이펙티브자바, 19 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라.

19. 상속을 고려해 설계하고 문서화하라. 그러지 않았다면 상속을 금지하라. 매서드를 재정의하면 어떤 일이 일어나는지를 정확하게 정리하여 문서로 남겨야 한다. 달리 말하면, 상속용 클래스는 재정의할 수 있는 메서드들을 내부적으로 어떻게 이용하는지(자기사용) 문서로 남겨야 한다. 자기사용이란 클래스 내부에서 사용하는 매서드를 의미한다. 자기사용 매서드를 노출하여 발생하는 문제는, Set을 extends하여 발생한 문제를 다뤘던 아이템18에서 확인할 수 있다. 재정의 가능이란 public 과 protected 메서드 중 final이 아닌 모든 메서드를 뜻한다. 해당 객체는 개방되어 있는 필드 혹은 메서드이며 하위 클래스나 객체를 통해 수정 가능하다. “좋은 API 문서란 ‘어떻게’가 아닌 ‘무엇’을 하는지를 설명해야 한다.” 상속을 위하여 문서화하는 순간, 내부 구현 방식을 설명하기 시작하며, 좋은 API문서로부터 멀어진다.

이펙티브자바, 18 상속보다는 컴포지션을 사용하라

상속의 위험성 클래스가 다른 클래스를 상속하는 구현 상속은 오류를 내기 쉬운 소프트웨어를 만든다. 상속은 캡슐화를 깨뜨린다. 상위 클래스의 내부 구현에 하위 클래스가 종속되고 오작동의 가능성을 내포한다.

이펙티브자바, 15-17 클래스의 접근 및 변경 가능성을 최대한 제한한다.

15. 클래스와 멤버의 접근 권한을 최소화하라. 접근 권한의 최소화 잘 설계된 컴퍼넌트를 구현하기 위해서는 다른 컴퍼넌트와 API로만 통신해야 한다. 외부에서는, 컴퍼넌트의 API 이외에는 접근하지 못한다. 그러니까 개발과정에서 API의 명세가 변경되지 않는 한, 내부 동작은 어떤 식으로든 변경할 수 있게 된다. 개발 속도와 신뢰도를 높힌다. 기본 원칙은 모든 클래스와 멤버의 접근성을 가능한 좁힌다. 가장 이상적인 방식은 private이며, 불가피한 상황에서는 package-private 으로 한다. public, protected가 되는 순간, 그 클래스와 필드는 외부와 통신하는 API로 동작하게 되며, 변경 및 유지보수 과정에서 하위 호환성을 위하여 영원히 관리하게 된다.

이펙티브자바, toString을 항상 재정의하라

toString toString은 Object의 메서드 중 하나이다. 모든 객체는 toString을 재정의 할 수 있다. 아래는 재정의하지 않은 toString을 호출한다.

이펙티브 자바, 다 쓴 객체 참조를 해제하라

GC와 메모리 해제 자바는 가비지 컬렉터로 인하여 메모리를 해제할 필요가 없다. 하지만 모든 메모리에 대해서는 아니다. 개발자는 쓸모 없는 객체로 판단했더라도 GC 입장에서는 정상적으로 참조되는 메모리가 존재할 수 있다. 그 중 예는 Stack의 포인터를 움직일 때 발생한다.

이펙티브자바, 불필요한 객체 생성은 피하라

박싱타입과 기본타입의 성능 문제 대체로 객체를 생성하는 것은 좋다. 기본타입에서도 마찬가지인데 null을 사용할 수 있는 등 객체로서 동작한다. 하지만 기본타입을 객체로 박싱하기 때문에 이로 인한 성능 상 문제가 있다. 아래의 코드는 전자가 후자보다 약 5배 느리다.

이펙티브자바, 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라

싱글턴과 정적유틸리티가 외부 객체를 사용할 때 아래는 정적유틸리티를 구현한 형태이다. 클래스 내부에서 필요한 객체의 인스턴스를 생성하고 static 매서드로 활용한다.

이펙티브 자바, private 생성자나 열거 타입으로 싱글턴임을 보장하라

싱글턴? 싱글턴이란 인스턴스를 오직 하나만 생성할 수 있는 클래스를 말한다.

이펙티브자바, 빌드패턴, 들어가며

객체를 생성하는 다양한 방법 점진적 생성자 점진적 생성자란 모든 필드를 인자로 가지는 생성자(일종의 @AllArgsConstructor)를 만든다. 그리고 필요에 따라 일부분의 인자만을 가지는 생성자를 만들고, 자신보다 더 많은 인자를 가진 생성자에 대하여 this()로 생성자를 호출한다. 작은 생성자 -> 중간 생성자 -> 전체 생성자를 호출하는 형태를 가진다. 이러한 형태를 점진적 생성자라 한다.

이펙티브 자바를 읽으며

이펙티브 자바를 읽으며 개발자로서 정말로 할 것들이 많다. 스프링 / 자바는 기본이다. 자바/스프링만이 아니다. Junit, Spring JPA, security, batch, reactive 등 다양한 라이브러리를 알아야 한다. 알고리즘 공부도 빼놓을 수 없다. 서버에 대한 학습도 필요하다. 최소한 도커나 AWS, 리눅스 따위는 어느정도 다뤄야 할테다. 백엔드만이 아니다. HTML/CSS/JS는 기본으로 알아야 한다. JSP를 넘어서 타임리프 정도는 자유롭게 사용할 줄 알아야 한다. vue.js 정도를 능숙하게 다뤄야겠지. 다양한 기술을 익히는 것도 중요하지만, 내가 좋은 코드를 작성하는지에 대한 고민도 많다. 클린코드, 테스트 주도 개발, 도메인 주도 개발, 리팩터링, 디자인 패턴, 에자일 등 좋은 품질의 코드를 작성하고 좋은 개발 문화를 위한 고민 또한 빼놓을 수 없다. 하루 하루...

spring-data-jpa, web 확장 -도메인 클래스 컨버터

도메인 클래스 컨버터 컨트롤러에서도 도메인을 조회할 수 있다.

spring-data-jpa가 엔티티가 새 엔티티를 판별하는 방법, Persistable

save()의 동작원리 스프링이 jpa 인터페이스를 구현할 때, 그러니까 JpaRepository 과 그것을 상속한 인터페이스를 구현할 때, SimpleJpaRepository 로 구현한다. SimpleJpaRepository의 코드를 보면 다음과 같다.

spring-data-jpa 페이징

spring-data-jpa 의 페이징 기능 페이징과 정렬 기능을 구현하였음 org.springframework.data.domain.Sort org.springframework.data.domain.Pageable 반환타입도 편리하게 구현하였음 org.springframework.data.domain.Page : count를 포함하는 페이징 org.springframework.data.domain.Slice : count가 없는 다음 페이지 List : 자바 컬렉션 리스트로 리턴할 경우 데이터만 출력함. map 매서드를 통해 dto로 쉽게 변환 가능.

spring-data-jpa @EntityGraph, @QueryHints, @Lock

spring-data-jpa 에서 제공하는 몇 가지 기능 이번 블로그에서는 몇 가지 기능을 가볍게 정리한다.

spring-data-jpa auditing 과 엔티티의 수정일, 등록일의 자동 생성

등록일과 수정일 등에 대한 자동 등록 기능 등록일과 수정일에 대하여 자동 등록이 가능하다. 해당 기능을 jpa로 구현하면 다음과 같다.

spring-data-jpa 사용자 정의 리포지토리

매서드를 정의하여 사용할 수 없을까? JpaRepository를 상속받은 인터페이스는 메서드에 어너테이션을 기반으로 정의해야 한다. 해당 인터페이스를 구현하여 Override 할 수 없다. 하지만 필요에 따라 특정 매서드는 구체적으로 구현해야할 필요가 있다. 동시에 스프링 데이타 jpa의 기능을 함께 사용하고 싶을 수 있다. 이러한 것에 대하여 스프링 데이터 jpa는 지원한다.

spring-data-jpa 벌크연산

벌크연산이란? 벌크연산은 update를 여러 개 날리는 쿼리를 의미한다. update member set age = age + 1 where username = 'kim'; 벌크연산을 위와 같은 쿼리로 jpql로 할 수 있으며, spring-data-jpa의 인터페이스 메서드를 통해서도 가능하다.