
문자열 연결 연산자(+)는 여러 문자열을 하나로 합쳐주는 편리한 수단이지만, 성능 저하가 상당하다. 문자열 연결 연산자로 문자열 n개를 잇는 작업은 n^2에 비례한다. 예시 청구서의 item을 전부 하나의 문자열로 연결하는 메서드가 있다. // 문자열 연결을 잘못 사용한 예 - 느리다! public String statement() { String result = ""; for (int i = 0; i < numItems(); i++) { result += lineForItem(i); } return result; } 각 item의 원소 개수만큼 문자열을 잇는다. 품목의 개수가 많아지면 많아질수록 성능 저하가 심해진다. 성능을 포기하고 싶지 않다면 String 대신 StringBuilder를 사용하자! ..

문자열은 텍스트를 표현하도록 설계되었다. 하지만 워낙 흔하고 자바가 잘 지원해주기 때문에 설계 의도와 다르게 사용될 때가 많다. 문자열을 쓰지 않아야 할 사례들 1. 문자열로 다른 값 타입을 대신하는 경우 받는 데이터가 수치를 나타낸다면 int, float, BigInteger 등을, Y / N을 나타낸다면 boolean을 사용하는 것이 적절하다. 즉, 기본 타입이든 참조 타입이든 알맞는 값 타입이 있다면 그것을 사용하고, 없다면 새로 만들어서 사용하자. 2. 문자열로 열거 타입을 대신하는 경우 아이템 34에서도 설명했듯, 상수를 열거할 때는 문자열보다 열거 타입을 사용하자. 3. 문자열로 혼합 타입을 표현하는 경우 혼합된 데이터를 하나의 문자열로 표현하는 것은 좋지 않은 생각이다. // 혼합 타입을 문..

자바의 데이터 타입은 크게 int, long, boolean과 같은 기본 타입과 String, List 같은 레퍼런스 타입으로 나눌 수 있다. 각각의 기본 타입에는 대응하는 레퍼런스 타입이 하나씩 존재하고, 이를 박싱 된 기본 타입(Integer, Long, Boolean 등)이라 한다. 오토 박싱과 오토 언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수 있지만, 어떤 타입을 선택하고 사용하는지는 상당히 중요하다. 이 둘의 차이점을 명확히 파악하고 사용해야 발생하는 문제들을 최소화할 수 있다. 기본 타입과 박싱된 기본 타입의 차이점 1. 기본 타입은 값만 가지고 있으나, 박싱 된 기본 타입은 식별성도 가지고 있다. 박싱 된 기본 타입의 두 인스턴스는 값이 같아도 서로 다른 인스턴스로 인식될 수 있다..

float와 double 타입은 공학 계산용으로 설계되었다. 넓은 범위의 수를 빠르게, 정밀한 근사치로 계산하도록 설계되었다. 따라서 정확한 결과가 필요할 때는 사용하면 안 된다. 특히, 금융(돈) 관련 계산에는 float와 double 타입 사용을 피하자. 금융 계산에 부동소수 타입을 사용한 경우 public static void main(String[] args) { double funds = 1.00; int itemBought = 0; for(double price = 0.10; funds >= price; price += 0.10) { funds -= price; itemsBought++; } System.out.println(itemBought + "개 구입"); System.out.print..

Java 생태계에는 java.io, java.lang, java.util 등 자바 표준 라이브러리나 고품질의 서드파티 라이브러리 등 수많은 라이브러리들이 존재한다. 아주 특별한 나만의 기능이 아니라면 이미 누군가가 라이브러리 형태로 구현해놓았을 가능성이 크다. 이러한 라이브러리들은 일반적으로 코드의 품질이 좋고 지속해서 개선된다. 구현해야 할 기능이 라이브러리로 존재한다면 그것을 사용하자. 있는지 잘 모르겠다면 찾아보자. 우리는 그 라이브러리가 어떤 영역의 기능을 제공하는지 살펴보고, 익히고, 사용하면 된다. 표준 라이브러리를 잘 활용하지 못한 예제 아주 흔히 마주치는 문제로, 다음과 같은 메서드를 만들곤 한다. // 문제가 많은 코드! static Random rnd = new Random(); sta..

가능한 모든 곳에서 전통적인 for 문보다는 for-each 문을 사용하는 것이 좋다. 전통적인 for 문과 비교했을 때 for-each문은 명확하고, 유연할 뿐 아니라 버그를 예방해주는 효과가 있다. 또 성능 저하도 없다. // 전통적인 for 문 - 컬렉션 순회 for(Iterator i = c.iterator(); i.hasNext();) { Element e = i.next(); } // 전통적인 for 문 - 배열 순회 for (int i = 0; i < a.length; i++) { int z = a[i]; // a[i]로 무언가를 한다. } 전통적인 for 문은 while문 보다는 낫지만 가장 좋은 방법은 아니다. 우리에게 필요한 건 원소뿐인데 for 문 안의 반복자와 인덱스가 코드를 지저분..

클래스와 멤버의 접근 권한을 최소화하면 얻을 수 있는 이점이 많듯, 지역변수의 유효 범위를 최소로 줄이면 코드 가동성과 유지보수성을 높일 수 있고 오류 가능성을 낮출 수 있다. 지역변수 범위 최소화하기 1. 가장 처음 쓰일 때 선언하기 가장 강력한 기법은 역시 '가장 처음 쓰일 때 선언하기'이다. 변수를 미리 선언해두면 코드가 어수선해지고 가독성이 떨어진다. 또한, 의도한 범위 외에서 그 변수를 사용하면 오류 가능성이 높아진다. 2. 선언과 동시에 초기화 초기화에 필요한 정보가 충분하지 않다면 충분해질 때까지 선언을 미뤄야 한다. 단, try-catch 구문에서의 이 규칙은 예외이다. 3. 메서드를 작게 유지하고 한 가지 기능에 집중하기 하나의 메서드가 여러가지 역할을 가지는 경우 그중 한 기능과만 관련..

API를 쓸모 있게 하려면 잘 작성된 문서도 함께 제공해야 한다. 자바에서는 자바독이라는 유틸리티가 이 작업을 도와준다. 문서화 주석을 작성하는 규칙은 공식 언어 명세에 속하진 않지만 자바 프로그래머라면 응당 알아야 하는 업계 표준 API라 할 수 있다. API를 올바르게 문서화하는 방법 API를 올바로 문서화하려면 공개된 모든 클래스, 인터페이스, 메서드, 필드 선언에 문서화 주석을 달아야 한다. 직렬화할 수 있는 클래스라면 직렬화 형태에 대해서도 적어야 한다, 문서가 잘 갖춰지지 않은 API는 쓰기 헷갈려서 오류의 원인이 되기 쉽다. 꼭 문서화를 하자. 기본 생성자에는 문서화 주석을 달 수 없으니 공개 클래스는 절대 기본 생성자를 사용하지 말자. 유지보수를 고려한다면 대다수의 공개되지 않은 클래스, ..

Java8 이전에는 메서드가 특정 조건에서 값을 반환할 수 없을 때 예외를 던지거나, null을 반환하는 두 가지 방법이 있었다. 그런데 Java8로 버전이 올라가면서 Optional라는 또 하나의 선택지가 생겼다. Java8 이전, 메서드가 특정 조건에 값을 반환할 수 없을 때 처리 방법에는 예외를 던지거나 null을 반환하는 두 가지의 선택지가 존재한다. 하지만 이 방법들에는 모두 단점이 존재한다. 1. 예외를 던진다. 예외는 진짜 예외적인 상황에서만 사용해야 한다. 예외를 생성할 때 스택 추적 전체를 캡처하는 비용이 만만치 않다. 2. null을 반환한다. 별도의 null 처리 코드를 추가해야 한다. null 처리를 무시하고 저장해두면 언젠가 NullPointerException이 발생할 가능성이 ..