JAVA/Effective Java 84

[아이템 54] null이 아닌, 빈 컬렉션이나 배열을 반환하라

null을 반환하지 말자 다음 코드와 같이 컬렉션이 비어있으면 null을 반환하는 경우가 있습니다. 위 코드와 같이 null을 반환하는 경우, 클라이언트는 다음 코드와 같이 null 체크 후 적절히 처리하는 코드를 추가해야 합니다. 특히, getCheeses() 메서드와 같이 컬렉션이나 배열과 같은 컨테이너가 비었을 때 null을 반환할 경우 클라이언트는 항시 위와 같이 방어 코드를 넣어줘야 합니다. 클라이언트에서 방어 코드를 누락하면 오류가 발생할 수 있으며, 객체가 0개일 가능성이 희박한 상황에서는 엣지 케이스가 발생할 때까지 코드에서 오류를 인지하기 어려울 수 있습니다. 빈 컨테이너를 반환하는 것보다 null을 반환하는 것이 더 낫지 않나? 소제목처럼 때로는 빈 컨테이너를 할당하는 행위도 비용이 드..

JAVA/Effective Java 2024.03.11

[아이템 53] 가변인수는 신중히 사용하라

가변인수 자바 5+ 버전부터 등장한 가변인수 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있습니다. 가변인수 메서드를 호출하면 다음과 같이 처리합니다. 가장 먼저 인수의 개수와 길이가 같은 배열을 생성하고 인수들을 해당 배열에 저장하여 가변인수 메서드에 건네줌 다음 코드는 입력받은 int 인수들의 합을 계산하는 예제입니다. 위 코드에서 볼 수 있다시피 가변인수 적용 시 메서드를 보다 간결하고 유연하게 만들어주므로, 적절하게 사용하면 코드의 가독성과 유지보수성을 향상할 수 있습니다. 여기까지만 봐서는 가변인수를 무조건 적용해야 하는 것처럼 보이지만, 가변인수 사용 시 몇 가지 규칙과 주의사항이 있습니다. 인수를 0개만 받도록 설계하는 것은 좋지 않음 힙 오염 주의 성능 이슈 메서드 당 한 개의 가변인..

JAVA/Effective Java 2024.03.11

[아이템 52] 다중정의는 신중히 사용하라

다중정의(Overloading) 다중정의란 오버로딩을 의미하며 리턴 타입과 메서드명은 같으나 파라미터의 개수나 타입이 다른 메서드를 작성하는 것을 의미합니다. 다중정의로 인해 예상과 달리 오동작하는 코드들이 있는데 원인은 다음과 같습니다. 오버로딩한 메서드는 정적으로 선택 오버라이딩한 메서드는 동적으로 선택 위 내용을 완벽하게 보여주는 예제 코드는 다음과 같습니다. 코드 부연 설명 다중정의된 세 classify 메서드 중 어느 메서드를 호출할지가 컴파일 타임에 정해짐 컴파일 시점에는 for 문 안의 c는 항상 Collection 타입 런타임에는 타입이 매번 달라지지만 호출할 메서드를 선택하는 시점은 컴파일 타임이기 때문에 영향을 주지 못 함 따라서 컴파일 타임의 매개변수 타입인 Collection을 기준..

JAVA/Effective Java 2024.03.10

[아이템 51] 메서드 시그니처를 신중히 설계하라

메서드 시그니처 메서드 시그니처(Method Signature)는 메서드의 선언 부분에서 메서드의 식별을 정의하는 부분을 의미합니다. 메서드 시그니처에는 메서드의 이름, 매개변수의 타입, 반환 값의 타입이 포함됩니다. 일반적으로 메서드 시그니처는 다음과 같은 형식을 가집니다 형식 부연 설명 returnType: 메서드가 반환하는 값의 데이터 타입을 나타내며 만약 메서드가 반환하는 값이 없으면 void라고 표시 methodName: 메서드의 이름을 나타냄 parameterType1, parameterType2, ...: 메서드가 받는 매개변수의 데이터 타입 param1, param2, ...: 메서드가 받는 실제 매개변수의 이름 여기서 returnType, methodName, 그리고 parameterTy..

JAVA/Effective Java 2024.03.09

[아이템 50] 적시에 방어적 복사본을 만들라

자바의 안전성 자바는 안전한 언어입니다. 자바로 작성한 클래스는 불변식이 지켜짐 자바는 c, c++와 달리 네이티브 메서드를 사용하지 않음 c, c++는 네이티브 메서드를 사용하기 때문에 버퍼 오버런, 배열 오버런, 와일드 포인터 같은 메모리 충돌 오류로부터 안전하지 않음 방어적 프로그래밍을 해야 하는 이유 자바가 아무리 안전한 언어라고 해도 다음과 같은 이유 때문에 방어적 프로그래밍을 해야 합니다. 다른 클래스로부터의 침범을 아무런 노력 없이 막을 수 있는 것은 아님 악의적인 의도를 가진 사람들이 시스템 보안을 뚫으려는 시도가 늘고 있는 추세 휴먼 에러로 인해 클래스가 오동작하게 생성될 수 있음 따라서, 클라이언트가 불변식을 깨드리려고 노력한다고 가정하고 방어적으로 코드를 작성해야 합니다. 객체가 자기..

JAVA/Effective Java 2024.03.09

[아이템 49] 매개변수가 유효한지 검사하라

메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바랍니다. ex) 인덱스 값은 0 이상의 정수 ex) 객체 참조는 null이 아니어야 함 이런 제약은 반드시 문서화가 필요하며 메서드 몸체가 시작되기 전에 검사해야 합니다. 이는 `오류는 가능한 한 빨리 발생한 곳에서 잡아야 한다`는 일반 원칙의 한 사례입니다. 만약 오류를 즉시 잡지 않을 경우 해당 오류를 감지하기 어려워질뿐더러 감지하더라도 오류의 근원지를 찾기 어려워지며 최악의 상황에서는 실패 원자성을 어기는 결과를 낳을 수 있습니다. 실패 원자성을 보장하기 위해서는 호출된 메서드가 실패하더라도 객체는 호출 전의 상태를 유지해야 함 코드 부연 설명 앞서 언급한 일반 원칙을 따르기 위해 생성자가 호출되는 시점에 매개변수를 확인하고 조..

JAVA/Effective Java 2024.03.07

[아이템 48] 스트림 병렬화는 주의해서 적용하라

자바의 동시성 프로그래밍 주류 언어 중에서 자바는 항상 동시성 프로그래밍 측면에서 선두를 달려왔습니다. 첫 릴리즈 된 1996년부터 쓰레드, 동기화, wait()/notify() 메서드 지원 자바 5 버전부터 동시성 컬렉션인 java.util.concurrent 라이브러리와 Executor 프레임워크 지원 자바 7 버전부터 고성능 병렬 분해(parallel decom-position) 프레임워크인 fork-join 패키지 추가 자바 8 버전부터 parallel 메서드만 한 번 호출하면 파이프라인을 병렬 실행할 수 있는 Stream 지원 이처럼 자바로 동시성 프로그램을 작성하기가 점점 쉬워지고 있으나 이를 올바르고 빠르게 작성하는 일은 여전히 어려운 작업입니다. 동시성 프로그래밍을 할 때는 안전성과 응답 ..

JAVA/Effective Java 2024.03.06

[아이템 47] 반환 타입으로는 스트림보다 컬렉션이 낫다

다양한 선형 자료구조를 반환하는 메서드가 많이 있으며, 해당 메서드의 반환 타입은 다음 중 하나였습니다. Collection, Set, 혹은 List와 같은 컬렉션 인터페이스 Iterable 인터페이스 String[]과 같은 배열 1. Collection 인터페이스 기본적으로 컬렉션 인터페이스를 반환 타입으로 채택 2. Iterable 인터페이스 for-each 문에서만 쓰이거나 반환된 원소 시퀀스가 contains(Object)와 같은 일부 Collection 메서드를 구현할 수 없을 경우 사용 3. 배열 반환 원소들이 primitive 타입이거나 성능에 민감할 경우 이처럼 메서드의 반환 타입을 선택할 때는 명확한 기준이 있었습니다. 하지만 자바 8 버전부터 등장한 스트림에 의해 선택하는 기준이 다소 ..

JAVA/Effective Java 2024.03.05

[아이템 46] 스트림에서는 부작용 없는 함수를 사용하라

스트림의 패러다임 스트림이 제공하는 표현력, 속도, 병렬성을 얻으려면 API는 말할 것도 없고 해당 패러다임까지 함께 받아들여야 합니다. 스트림 패러다임의 핵심은 계산을 일련의 변환으로 재구성하는 것 각 변환의 단계는 오직 이전 단계의 결과만이 결과에 영향을 주는 순수한 함수여야 함 즉, 다른 가변 상태를 참조하지 않으면서 함수 스스로도 다른 상태를 변경하면 안 됨 1. 스트림 패러다임을 이해하지 못한 채 사용한 예 위 코드는 텍스트 파일에서 단어별 수를 세어 빈도표로 만드는 일을 수행하지만 문제가 있는 코드입니다. 스트림 코드를 가장한 반복적 코드 위 스트림 파이프라인은 forEach 종단 연산에서 sideEffect map의 상태를 변경 forEach를 사용하는 것은 스트림을 사용하는 것이 아닌 단순..

JAVA/Effective Java 2024.03.03

[아이템 45] 스트림은 주의해서 사용하라

스트림 API 1. 개념 다량의 데이터 처리 작업을 돕고자 자바 8+ 버전부터 추가된 기능 스트림은 데이터 원소의 유한 혹은 무한 시퀀스를 뜻함 스트림 파이프라인은 이 원소들로 수행하는 연산 단계를 표현하는 개념 스트림의 원소들은 어디로부터든 올 수 있으며 대표적으로 컬렉션, 배열, 파일, 정규표현식 패턴 매처, 난수 생성기, 혹은 다른 스트림이 있음 스트림 안의 데이터 원소들은 객체 참조나 기본 타입 값 기본 타입 값은 int, long, double 지원 스트림 API는 메서드 연쇄를 지원하는 fluent API 파이프라인 하나를 구성하는 모든 호출을 연결하여 단 하나의 표현식으로 완성 가능 파아프라인 여러 개를 연결해 표현식 하나로 만들 수 있음 기본적으로 스트림 파이프라인은 순차적으로 수행 파이프..

JAVA/Effective Java 2024.03.02