EffectiveJava 8

문자열 연결을 고민한다면 String 보다는 StringBuilder

성능을 생각한다면 String 대신 StringBuilder 문자열 연결 연산자(+)는 편리하지만, 성능 위주의 환경에서는 성능 저하를 감내하기 어려울 것이다. 문자열 연결 연산자로 문자열 n개를 잇는 시간은 n^2에 비례한다. 문자열은 불변이라서 두 문자열을 연결할 경우 양쪽의 내용을 모두 복사해야 하므로 성능 저하는 피할 수 없다. public String statement() { // 문자열 연결을 잘못 사용한 예 - 느리다! String result = ""; for (int i = 0; i < numItems(); i++) { result += lineForItem(i); // 문자열 연결 } return result; } 성능을 포기하고 싶지 않다면 StringBuilder를 사용하자 publ..

Java 2021.02.08

박싱 타입보다 기본 타입을 사용하라

박싱된 기본 타입보다는 기본 타입을 사용하라 자바의 데이터 타입 기본타입 - int, double, boolean ... 참조타입 - String, List ... 박싱된 기본 타입 - Integer, Double, Boolean ... 오토박싱과 오토언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수는 있지만 차이는 있다. 어떤 타입을 사용하는지는 상당히 중요하다. 기본타입과 박싱된 기본 타입과의 차이 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 더해 식별성이란 속성을 갖는다. 즉 두 인스턴스의 값이 같아도 다르다고 식별 될 수 있다. 기본 타입의 값은 언제나 유효하나, 박싱된 기본 타입의 값은 null(유효하지 않은 값)을 가질 수 있다. 기본 타입이 시간과 메모리 사용면에서 유리하..

Java 2021.02.01

정확한 계산이 필요할 땐 float와 double은 피하자

정확한 계산이 필요할 땐 float와 double은 피하자 float와 double 타입은 과학과 공학 계산용으로 설계되었다. 이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 '근사치'로 계산하도록 세심하게 설계되었다. 따라서 정확한 결과가 필요할 때는 사용하면 안되며, 특히 금융 관련 계산과는 맞지 않는다. 0.1 혹은 10의 음의 거듭 제곱수를 표현할 수 없기 때문이다. 예를 들어 주머니에 1.03 달러가 있는데 그중 42센트를 썼다고 해보자, 남은 돈을 얼마인가? 다음은 어설프게 작성한 코드다 System.out.println(1.03 - 0.42); 안타깝게도 이 코드는 0.6100000000000001을 출력한다. 이는 특수한 사례도 아니다. 이번에는 1달러가 있는데, 10센트짜..

Java 2021.01.18

지역변수의 범위는 최소화하자

지역변수의 범위를 최소화하라 제목의 내용은 '클래스와 멤버의 접근 권한을 최소화하라'와 비슷하다. 지역변수의 유효 범위를 최소로 줄이면 코드 가독성과 유지보수성이 높아지고 오류 가능성은 낮아진다. C와 같이 역사가 깊은 프로그래밍 언어 중에는 지역변수를 코드 블록의 첫머리에 선언하는 경우가 많고, 이 방식을 습관처럼 따르는 프로그래머도 있다. 하지만 자바에서는 문장을 선언할 수 있는 곳이면 어디서든지 선언할 수 있다.(C도 C99 표준부터는 변경되었다.) 지역변수의 범위를 줄이는 가장 강력한 기법은 가장 처음 쓰일 때 선언하기다. 미리 선언부터 해두면 변수를 실제로 사용하는 시점엔 타입과 초기값이 기억나지 않을 수도 있다. 그리고 거의 모든 지역변수는 선언과 동시에 초기화해야 한다. 초기화에 필요한 정보..

Java 2021.01.05

Optional 반환은 신중히하자

옵셔널 반환은 신중히 하라 자바 8 전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때의 선택지가 두 가지 있었다. 예외 - 스택 추적 전체를 캡처하므로 비용이 만만치 않다, 진짜 예외적인 상황에서만 사용해야 한다. null을 반환하면 별도의 null처리 코드를 추가해야 한다. 자바 8로 올라가면서 선택지가 생겼다. Optional이다. null이 아닌 T타입 참조를 하나 담거나, 혹은 아무것도 담지 않을 수 있다. 아무것도 담지 않은 옵셔널은 '비었다'라고 한다. 반대로 어떤 값을 담은 옵셔널은 '비지 않았다'고 한다. 옵셔널은 원소를 최대 1개 가질 수 있는 '불변' 컬렉션이다. Optional가 Collection를 구현하지는 않았지만, 원칙적으로는 그렇다. 보통은 T를 반환해야 하지만 특정 조..

Java 2020.12.31

null을 반환하는 메서드는 자제하자.

// 컬렉션이 비었으면 null을 반환한다. - 하지말자 private final List cheesesInStock = ...; /** * @return 매장 안의 모든 치즈목록을 반환한다. 단 재고가 하나도 없으면 null을 반환한다. **/ public List getCheeses() { return cheesesInStock.isEmpty() ? null : new ArrayList(chessesInStock); } 이 코드처럼 null을 반환한다면, 클라이언트는 이 null 상황을 처리하는 코드를 추가로 작성해야 한다. List cheeses = shop.getCheeses(); if (chesses != null && chesses.contains(Cheese.STILTON)) { System..

Java 2020.11.16

한정적 와일드카드 (Bounded Wildcard Type)

한정적 와일드카드를 사용해 API 유연성을 높이라 매개변수화 타입은 불공변(invariant)이다. 즉, 서로 다른 타입 type1과 type2가 있을 때 List은 List의 하위 타입도 상위 타입도 아니다. List은 List의 하위 타입이 아니라는 뜻인데, List에는 어떤 객체든 넣을 수 있지만, List에는 문자열만 넣을 수 있다. 즉, List은 List가 하는 일을 제대로 수행하지 못하니 하위 타입이 될수 없다.(리스코프 치환 원칙 위배) 불공변 방식보다 유연한 무언가 필요 할때가 있다. public class Stack { public Stack(); public void push(E e); public E pop(); public boolean isEmpty(); } 여기에 일련의 원소를..

Java 2020.07.16

제네릭 메서드

제네릭 메서드의 작성법은 제네릭 타입 작성법과 비슷하다. 아래는 두 집합(Set)의 합 집합을 반환하는 문제가 있는 메서드다. public static Set union(Set s1, Set s2) { Set result = new HashSet(s1); // Type safety : unchecked call... 경고 result.addAll(s2); // Type Safety.. return result; } 컴파일은 되지만 경고가 발생한다. 메서드를 타입 안전하게 만들어야 경고가 사라진다. 메서드 선언에서의 세 집합(입력 2개, 반환 1개)의 원소 타입을 타입 매개변수로 명시하고, 메서드 안에서도 이 타입 매개변수만 사용하게 수정하면 된다.타입 매개변수의 목록은 메서드의 제한자와 반환 타입에서 온..

Java 2020.07.14