맞는데 왜 틀릴까..?

Java 108

[Effective Java] Item 56. 공개된 API 요소에는 항상 문서화 주석을 작성하라

API를 쓸모 있게 하려면 잘 작성된 문서도 곁들여야 한다. 자바에서는 자바독(Javadoc)이라는 유틸리티가 소스코드 파일에서 문서화 주석(doc comment; 자바독 주석)이라는 특수한 형태로 기술된 설명을 추려 API 문서로 변환해 준다. 문서화 주석 문서화 주석을 작성하는 규칙은 공식 언어 명세에 속하진 않지만 자바 프로그래머라면 알아야 하는 업계 표준 API다. 이 규칙은 문서화 주석 작성법 (How to Write Doc Comments) 웹 페이지에 기술되어 있다. API를 올바로 문서화하려면 공개된 모든 클래스, 인터페이스, 메서드, 필드 선언에 문서화 주석을 달아야 한다. 직렬화할 수 있는 클래스라면 직렬화 형태에 관해서도 적어야 한다. 문서화 주석이 없다면 자바독도 그저 공개 API ..

Java/Effective Java 2023.07.22

[Effective Java] Item 55. 옵셔널 반환은 신중히 하라

메서드가 값을 반환할 수 없을 때 1. 예외를 던짐 진짜 예외적인 상황에서만 사용해야 한다. 예외를 생성할 때 스택 추적 전체를 캡처하므로 비용도 많이 든다. 2. 반환 타입이 객체 참조라면 null을 반환 null을 반환할 수 있는 메서드를 호출할 때는, 별도의 null 처리 코드를 추가해야 한다. null 처리를 무시하고 반환된 null 값을 어딘가에 저장해 두면 언젠간 NullPointerException이 발생할 수 있다. (실제 원인과는 전혀 상관없는 코드에서) 3. Optional 자바 8 이후 Optional 는 null이 아닌 T타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다. 아무것도 담지 않은 옵셔널을 '비었다'라고 말한다. 어떤 값을 담은 옵셔널을 '비지 않았다'라고 한다..

Java/Effective Java 2023.07.22

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

null을 반환하는 메서드 컬렉션이 비었으면 null을 반환하는 메서드 - 따라 하지 말 것 private final List cheeseInStock = ...; /** * @return 매장 안의 모든 치즈 목록을 반환한다. * 단, 재고가 하나도 없다면 null을 반환한다. */ public List getCheeseInStock{ return cheeseInStock.isEmpty() ? null : new ArrayList(cheeseInStock); } 이 코드처럼 null을 반환한다면, 클라이언트는 이 null 상황을 처리하는 코드를 추가로 작성해야 한다. 컬렉션이나 배열 같은 컨테이너가 비었을 때 null을 반환하는 메서드를 사용할 때면 항시 이와 같은 방어 코드를 넣어줘야 한다. 클라이언..

Java/Effective Java 2023.07.16

[Effective Java] Item 53. 가변인수는 신중히 사용하라

가변인수 가변인수 메서드는 명시한 타입의 인수를 0개 이상 받을 수 있다. 가변인수 메서드를 호출하면, 가장 먼저 인수의 개수와 길이가 같은 배열을 만들고 인수들을 이 배열에 저장하여 가변인수 메서드에 건네준다. 가변인수 활용 예 입력받은 int 인수들의 합을 계산해 주는 가변인수 메서드다. sum(1,2,3)은 6을, sum()은 0을 돌려준다. 인수가 1개 이상이어야 하는 메서드 - 잘못 구현한 예 지저분한 코드 인수를 0개만 넣어 호출하면 컴파일타임이 아닌 런타임에 실패한다. args 유효성 검사를 명시적으로 해야 하고, min의 초깃값을 Integer.MAX_VALUE로 설정하지 않고는 더 명료한 for-each문도 사용할 수 없다. 인수가 1개 이상이어야 하는 메서드 - 가변인수를 제대로 사용한..

Java/Effective Java 2023.07.16

[Effective Java] Item 51. 메서드 시그니처를 신중히 설계하라

API 설계 요령 메서드 이름을 신중히 짓자. 표준 명명 규칙을 따라야 한다. 이해할 수 있고, 같은 패키지에 속한 다른 이름들과 일관되게 짓는 게 최우선 목표다. 긴 이름은 피하자. 편의 메서드를 너무 많이 만들지 말자. 메서드가 너무 많은 클래스는 익히고, 사용하고, 문서화하고, 테스트하고, 유지보수하기 어렵다. 인터페이스도 마찬가지다. 메서드가 너무 많으면 이를 구현하는 사람과 사용하는 사람 모두 힘들다. 클래스나 인터페이스는 자신의 각 기능을 완벽히 수행하는 메서드로 제공해야 한다. 아주 자주 쓰일 경우에만 별도의 약칭 메서드를 두고 확신이 서지 않으면 만들지 말자. 매개변수 목록은 짧게 유지하자. 4개 이하가 좋다. 4개가 넘어가면 매개변수를 전부 기억하기 쉽지 않다. 같은 타입의 매개변수가 여..

Java/Effective Java 2023.07.16

[Effective Java] Item 50. 적시에 방어적 복사본을 만들라

자바는 네이티브 메서드를 사용하지 않아 C, C++ 같이 안전하지 않은 언어에서 흔히 보는 버퍼 오버런, 배열 오버런, 와일드 포인터 같은 메모리 충돌 오류에서 안전하다. 자바로 작성한 클래스는 시스템의 다른 부분에서 무슨 짓을 하든 그 불변식이 지켜진다. 메모리 전체를 하나의 거대한 배열로 다루는 언어에서는 누릴 수 없는 강점이다. 네이티브 메서드 네이티브 메서드(Native method)는 자바 언어로 작성된 프로그램에서 자바 가상 머신(JVM) 상에서 실행되는 것이 아니라, 네이티브 코드로 작성된 외부 라이브러리나 시스템 함수를 호출하기 위해 사용되는 메서드다. 자바 언어는 일반적으로 플랫폼에 독립적인 코드를 작성하기 위해 설계되었다. 그러나 특정한 하드웨어나 운영체제의 기능을 활용하거나, 네이티브..

Java/Effective Java 2023.07.16

[Effective Java] Item 49. 매개변수가 유효한지 검사하라

메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건 (인덱스 값이 음수이면 안되고, 객체 참조는 null이 아니어야 한다)을 만족하길 바라고 이런 제약은 반드시 문서화해서 메서드 몸체가 시작되기 전에 검사해야 한다. 메서드 몸체가 실행되기 전에 매개변수를 확인한다면 잘못된 값이 넘어왔을 때 즉각적이고 깔끔한 방식으로 예외를 던질 수 있다. 매개변수 검사를 제대로 하지 못하면 생기는 문제 1. 메서드가 수행되는 중간에 모호한 예외를 던지며 실패할 수 있다. 2. 메서드가 잘 수행되지만 잘못된 결과를 반환할 수 있다. 3. 메서드는 문제없이 수행되지만 어떤 객체를 이상한 상태로 만들어놓아서 미래의 알 수 없는 시점에 이 메서드와는 관련 없는 오류를 낼 수 있다. 매개변수 제약 문서화 public과 pr..

Java/Effective Java 2023.07.16

[Effective Java] Item 48. 스트림 병렬화는 주의해서 사용하라

자바 8부터 parallel 메서드만 호출하면 파이프라인을 병렬 실행할 수 있는 스트림을 지원헀다. 이처럼 자바는 동시성 프로그램을 작성하기가 점점 쉬워지고 있지만, 이를 올바르고 빠르게 작성하는 일은 여전히 어려운 작업이다. 동시성 프로그래밍을 할 때는 안정성(safety)과 응답 가능(liveness) 상태를 유지하기 위해 애써야 하는데, 병렬 스트림 파이프라인 프로그래밍에서도 다를 바 없다. 스트림을 사용해 처음 20개의 메르센 소수를 생성하는 프로그램 해당 프로그램의 속도를 높이고 싶어 스트림 파이프라인의 parallel()을 호출하면 CPU를 90%나 잡아먹고 아무것도 출력하지 못하는 상태가 무한히 계속된다. 스트림 라이브러리가 이 파이프라인을 병렬화하는 방법을 찾아내지 못했기 때문이다. 데이터..

Java/Effective Java 2023.07.09

[Effective Java] Item 47. 반환 타입으로는 스트림보다 컬렉션이 낫다

자바 7까지 원소를 반환하는 메서드의 반환 타입으로 가장 적합한 타입은 컬렉션 인터페이스였지만 자바 8이 스트림이라는 개념을 들고 오면서 이 선택이 복잡한 일이 되어 버렸다. 어댑터 메서드 스트림은 반복을 지원하지 않는다. 따라서 API를 스트림만 반환하도록 짜놓으면 반환된 스트림을 for-each로 반복하길 원할 때 불편할 것이다. 사실 Stream 인터페이스는 Iterable 인터페이스가 정의한 추상 메서드를 전부 포함하고 정의한 방식대로 동작하지만 Stream이 Iterable을 확장하지 않았기 때문에 이를 사용할 수 없다. 형변환을 통한 우회 방법 Stream의 iterator 메서드에 메서드 참조를 건내고 적절히 형변환 하면 동작하긴 하지만 너무 난잡하고 직관성이 떨어진다. 어댑터 메서드를 사용..

Java/Effective Java 2023.07.09

[Effective Java] Item 46. 스트림에서는 부작용 없는 함수를 사용하라

스트림 패러다임의 핵심은 계산을 일련의 변환으로 재구성하는 부분이다. 각 변환 단계는 가능한 한 이전 단계의 결과를 받아 처리하는 순수 함수여야 한다. 각 변환 단계는 가능한 한 이전 단계의 결과를 받아 처리하는 순수 함수여야 한다. 순수 함수란 오직 입력만이 결과에 영향을 주는 함수를 말한다. 다른 가변 상태를 참조하지 않고, 함수 스스로도 다른 상태를 변경하지 않는다. 이렇게 하려면 스트림 연산에 건네는 함수 객체는 모두 부작용(side effect)이 없어야 한다. 스트림을 잘못 사용한 예 스트림 코드로 텍스트 파일에서 단어별 수를 세어 빈도표를 만드는 프로그램 스트림 코드를 가장한 반복적 코드이다. 스트림 API의 이점을 살리지 못하여 같은 기능의 반복적 코드보다 조금 더 길고, 읽기 어렵고, 유..

Java/Effective Java 2023.07.09