맞는데 왜 틀릴까..?

전체 글 306

[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

[Effective Java] Item 45. 스트림은 주의해서 사용하라

스트림 스트림 API는 다량의 데이터 처리 작업을 돕고자 자바 8에 추가되었다. 컬렉션과 다르게 요소(element)를 저장하는 자료구조가 아닌, 데이터의 흐름을 처리하고 변환하는 파이프라인이다. 스트림은 데이터를 다루는 연산들을 조합하여 복잡한 처리 과정을 간결하고 가독성 있게 표현할 수 있다. 또한 내부적으로 데이터를 병렬로 처리하여 성능을 향상할 수 있는 장점도 가지고 있다. 스트림 안의 데이터 원소들은 객체 참조나 기본 타입 값(int, long, double)이다. 1. 데이터 소스 스트림은 컬렉션, 배열, I/O 채널 등 다양한 데이터 소스에서 생성할 수 있다. 2. 파이프라인 스트림은 연속된 작업들의 파이프라인으로 구성된다. 파이프라인은 데이터 소스에서 시작하여 중간 연산(intermedia..

Java/Effective Java 2023.07.08

[Effective Java] Item 44. 표준 함수형 인터페이스를 사용하라

자바가 람다를 지원하면서 API를 작성할 때 기존의 오버라이딩을 통한 템플릿 메서드 패턴보다, 같은 효과의 함수 객체를 받는 정적 팩토리나 생성자를 제공하는 방식이 좋아졌다. 함수형 인터페이스는 람다식으로 만든 객체에 접근하기 위해서 사용한다. 불필요한 함수형 인터페이스 표준 함수형 인터페이스를 사용 함수형 인터페이스 함수형 인터페이스(Functional Interface)는 자바에서 함수형 프로그래밍을 지원하기 위한 개념이다.자바 8부터 함수형 인터페이스가 도입되었으며, 람다식과 메서드 참조를 활용하여 함수를 일급 객체로 다룰 수 있으며, 이를 통해 코드의 간결성과 가독성을 높일 수 있다.함수형 인터페이스는 딱 하나의 추상 메서드를 가지는 인터페이스로, 이 추상 메서드를 함수형 인터페이스의 시그니처라고..

Java/Effective Java 2023.07.08