Java 21

Effective Java 제 11장 - 동시성

공유 중인 가변 데이터는 동기화해 사용해라! Synchronized 키워드로 데이터 변경은 하나의 쓰레드만 수행할 수 있도록 만들어라. 최대한 동기화 블럭 크기를 줄여라! 동기화 블럭을 크게 잡아두면 교착 상태에 놓일 확률이 크다. 뿐만 아니라 성능도 크게 저하되므로 되도록 최소한 사용하고 적은 범위에 적용해라! wait, notify보다 동시성 유틸리티를 애용해라! wait, notify는 매우 저수준의 쓰레드 처리 메서드다. 때문에 사용하기 굉장히 까다롭고 위험하다. 이것들을 쉽고 안전하게 사용할 수 있게 고수준 동시성 유틸리티를 만들어 놓았다. java.util.concurrent에 이러한 고수준 유틸리티가 많이 구현되어 있으니 이러한 메서드를 사용해라! 스레드 안전성 수준을 문서화해라! 약간 난해..

Java 2023.08.22

Effective Java 제 10장 - 예외

예외를 흐름제어와 같은 예외가 아닌 상황에서 사용하지 말라! 아래와 같이 흐름제어를 위해 if문을 대체하는 코드를 사용하지 않아야 한다. 성능적으로 손해를 많이 볼 수 있고 무엇보다도 가독성이 최악으로 치닫기 때문이다. try { int i=0; while(true) { range[i++].climb(); } } catch (ArrayIndexOutOfBoundsException e) {} 참고로 위 코드는 아래와 같다. for(Mountain m : range) { m.climb(); } 추상화 수준에 맞는 예외를 던져라! 여러 라이브러리를 조합해서 새로운 라이브러리를 만들면 수행하려는 일과는 상관없어 보이는 예외가 튀어나올 수도 있다. 이런 에러는 클라이언트들의 디버깅을 어렵게 만든다. 때문에 추상화..

Java 2023.08.22

Effective Java 제 9장 - 일반적인 프로그래밍 원칙

정확한 답이 필요하다면 float와 double과 같은 타입은 사용하지 마라! 해당 타입은 부동소수점 연산에 사용되며, 근사값으로 계산할 수 있게 설계된 타입이다. 금융 관련 계산에서는 절대 사용하면 안된다. 다수의 문자열을 잇는 연산을 할 때, 무조건 StringBuilder를 사용해라! 그냥 String 객체를 잇는 연산은 O(n^2) 복잡도를 가지고 있다. String 객체는 내부 데이터를 불변의 형태로 지니고 있기 때문에 그러하다. 때문에 StringBuilder를 이용해서 성능을 높일 수 있다. 리플렉션 사용을 지양하라! 리플렉션을 이용하면 컴파일러에 의해 생성된 바이너리 파일를 사용하는 것이 아닌 JVM에 의해 생성된 바이트코드를 메모리 위에 올려서 사용하게 된다. 당연히 바이너리 파일을 사용..

Java 2023.08.22

Effective Java 제 8장 - 메서드

매개변수 유효성 검사를 필히 진행하라! 메서드에 입력된 값은 때때로 null인지, 양수인지, 허용한 범위 내에 있는지 등등을 검사해야 한다. 이 때, java 7부터 추가된 requireNonNull, checkFromToIndex 등등을 사용하면 1줄로 검사가 끝나기도 하고 의미도 명확해 굳이 주석을 달지 않아도 된다. 내부 데이터를 보호하기 위해 복사 객체를 내놓기도 해야 한다! 만약 특정 객체의 속성을 final로 설정한다해도 해당 속성이 만약 List와 같이 내부 요소를 맘대로 수정할 수 있다면 악의적인 사용자 혹은 실수로 인해 변경된 값을 가질 수도 있다. 때문에 readonly로만 속성값을 출력하고 싶다면 진짜 속성값을 주는 것이 아니라 해당 속성값의 복사본을 Return하면 된다. 물론 복사..

Java 2023.08.22

Effective Java 제 7장 - 람다와 스트림

가독성을 위해 익명 클래스보다 람다식을 사용해라! 만약 구현해야 하는 인터페이스의 메서드가 1개뿐이라면 익명 클래스와 람다식은 동일하다. 람다식은 최소의 표현으로 작동 방식에 대해 서술하므로 가독성이 좋고 Cost도 적다. 하지만 만약 코드 Line 수가 너무 많거나 코드에 대한 설명이 필요한 경우, 람다식보다 차라리 클래스 파일 하나를 더 만드는 것이 좋다. 가독성을 위해 람다식보다 메서드 참조를 사용해라! 역시나 위 내용처럼 가독성을 위해 메서드 참조를 권장한다. 하지만 위 사례보다는 예외가 많기 때문에 가독성을 위해 두가지 선택지를 유동적으로 선택하면 된다. 표준 함수형 인터페이스를 적극 활용하라! 표준 함수형 인터페이스란, java.util.function 패키지의 인터페이스를 일컫는 말로, Fu..

Java 2023.08.22

Effective Java 제 6장 - 열거 타입과 애너테이션

Enum 타입의 ordinal 메서드는 가급적 사용하지 말기! 이는 클래스 소스 코드 내의 열거 타입 순서가 바뀌면 변경되기에 지양해야 한다. 비트 필드 대신 EnumSet을 사용해라! 비트 필드란 Enum 타입을 사용할 때, 라디오 버튼마냥 1개만 선택하는 한계를 해결하기 위해 체크 박스처럼 다중 선택을 위해 첫 항목을 (0001), 두번째를 (0010), 셋째는 (0100), ... 등등으로 설정해 (0101)라고 입력하면 첫 번째와 세번째 항목을 입력했다는 것을 인지하기 위해 사용한다. 이 방식은 위에서 언급한 ordinal 처럼 소스코드 순서에 너무 의존하기 때문에 사용한다. 때문에 차라리 Set을 이용하는 것이 낫다. 열거 타입을 확장하고 싶다면 인터페이스를 사용해라! 열거 타입은 대부분의 경우..

Java 2023.08.22

Effective Java 제 5장 - 제네릭

로 타입[List가 아니라 List로만 사용하는 형태]는 절대 사용마라! 컴파일러가 인지하지도 못하고 표현력도 떨어지므로 절대 사용하지 않아야 한다. 자바 측에서 로 타입을 문법적 오류로 규정짓지 않는 이유는 오직 이전 버전과의 호환성 때문이다. 배열보다 리스트를 사용해라! 배열은 컴파일 시점에서 타입 체크를 하지 않고 공변성이 있어서 런타임에 오류를 내놓을 확률이 비교적 크다. 재사용성을 위해 되도록 제네릭 클래스, 메서드를 만들라! 클라이언트가 직접 형변환을 하지 않게 제네릭을 활용하라. 제네릭은 불공변성[List -> List]이기에 한정적 와일드카드[List

Java 2023.08.22

Effective Java 제 4장 - 클래스와 인터페이스

클래스와 멤버의 접근 권한을 가능하다면 최소화해라! 필요한 부분만 외부 API로 노출시켜야 유지보수가 편하다. 모든 부분을 노출시키면 모든 부분을 지속적으로 지원해야 한다. public 클래스의 필드는 public을 사용하지 마라! OOP의 캡슐화를 극대화하기 위해 필드에 직접 접근하는 것을 지양하기. 불변 객체를 사용해라! 모든 필드를 final로 선언함으로서 동시성에서 안전하게 해야 한다. final을 사용하지 않으면 다중 스레드 환경에서 안전하려면 동기화 블록을 설정해야 하는데 그럴바엔 불변 객체를 이용해서 block없이 연산할 수 있게 한다. 상속보다 컴포지션 이용하기! 상속으로 클래스를 만들면 부모 클래스에 의해 자식 클래스가 휘둘릴 수도 있다. 부모 클래스의 코드를 수정했을 뿐인데 자식 클래스..

Java 2023.08.22

Effective Java 제 3장 - 모든 객체의 공통 메서드

Object.equals() 메서드를 재정의할 때, 주의해야 한다! 해당 내용은 2 회독 때, 더 자세히 정리할 계획이다. 내용이 굉장히 많다. Object.equals()를 재정의하거든 Object.hashCode()도 재정의해라! HashMap이나 HashSet과 같은 컬렉션을 이용하려면 hashCode()을 재정의해야 한다. 이 때, hashCode()를 재정의할 때 유의할 점이 있는데 마찬가지로 2회독 때, 자세하게 다룬다. 다만 전형적인 hashCode 알고리즘이 있다고 하여 이것을 여기에 적고자 한다. 31은 홀수면서 소수다. 소수를 곱해서 hashCode를 구성하는 이유는 명확하지 않지만 관습적으로 그리 해왔다고 한다. 더보기 class Example { int area; int prefix..

Java 2023.08.22