예외의 잘못된 사용 결론적으로 잘못된 코드. 느리다. package com.java.effective.item68; public class Main { public static void main(String[] args) { try { int i = 0; while(true) { range[i++].climb(); } } catch (ArrayIndexOutOfBoundsException e) { } } } 위 코드는 직관적이지 않다. 해당 코드는 배열을 무한루프로 순회하다가 배열의 끝에 도달하여 ArrayIndexOutOfBoundsException이 발생하면 끝을 낸다. 표준적은 관용구 코드로 수정 package com.java.effective.item68; public class Main { pu..
자바의 명명규칙 자바 플랫폼은 명명 규칙이 잘 정립되어 있으며, 그중 많은 것이 자바 언어 명세에 기술되어있다. 자바의 명명 규칙은 크게 철자와 문법, 두 범주로 나뉜다. 철자 규칙 패키지, 클래스, 인터페이스, 메서드, 필드, 타입 변수의 이름을 다룬다. 이 규칙들은 특별한 이유가 없는 한 무조건 따라야한다. 1) 패키지와 모듈 이름은 각 요소를 점(.)으로 구분하여 계층적으로 짓는다. 요소들은 모두 소문자 알파벳 혹은 드물게 숫자로 이뤄진다. 2) 표준 라이브러리와 선택적 패키지들은 각각 java, javax로 시작한다. 3) 패키지 이름의 나머지는 해당 패키지를 설명하는 하나 이상의 요소로 이뤄진다. 각 요소는 일반적으로 8자 이하의 짧은 단어로 한다. utilities -> util 4) 패키지명..
자바 최적화 최적화는 신중히하자. 섣불리 진행하게되면 빠르지도 않고 제대로 동작하지도 않으면서 수정하기는 어려운 소프트웨어가 된다. 성능 때문에 견고한 구조를 포기하지말자. 빠른 프로그램보다는 좋은 프로그램을 작성하자. 프로그램을 완성할 때까지 성능 문제를 무시하라는 뜻이 아닌, 설계 단계에서 성능을 반드시 염두에 둬야한다는 말이다. 1) 성능을 제한하는 설계를 피하자. 완성 후 변경하기가 가장 어려운 설계 요소는 바로 컴포넌트끼리, 혹은 외부 시스템과의 소통 방식이다. API, 네트워크 프로토콜, 영구 저장용 데이터 포맷 등이 대표적이며, 이런 설계 요소들은 완성 후에는 변경하기가 어렵거나 불가능 할수도 있다. 2) API 설계할때 성능에 주는 영향을 고려하자. public 타입을 가변으로 만들면, 즉..
자바 네이티브 인터페이스(Java Native Interface, JNI) 자바 프로그램이 네이티브 메서드를 호출하는 기술이다. 네이티브 메서드 C, C++과 같은 네이티브 프로그래밍 언어로 작성한 메서드를 말한다. 네이티브 메서드의 쓰임 1) 레지스트리와 같은 플랫폼 특화 기능을 말한다. 2) 네이티브 코드로 작성된 기존 라이브러리를 사용한다. 레거시 데이터를 사용하는 레거시 라이브러리가 그 예다. 3) 성능 개선을 목적으로 성능에 결정적인 영향을 주는 영역만 따로 네이티브 언어로 작성한다. -> JVM에는 거의 해당되지 않는다. 플랫폼 특화 기능을 활용하려면 네이티브 메서드를 사용해야한다. 하지만 자바가 성숙해가면서 (OS 같은) 하부 플랫폼의 기능들을 점차 흡수하고있다. 그래서 네이티브 메서드를 사..
리플렉션 리플렉션 기능(java.lang.reflect)을 이용하면 프로그램에서 임의의 클래스에 접근할 수 있다. Class 객체가 주어지면 그 클래스의 생성자, 메서드 필드에 해당하는 Constructor, Method, Field 인스턴스를 가져올 수 있고, 이어서 이 인스턴스들로는 그 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있다. 또한 각 인스턴스들을 사용하여 각각에 연결된 실제 생성자, 메서드, 필드를 조작할 수도 있다. 이 인스턴스들을 통해 해당 클래스의 인스턴스를 생성하거나, 메서드를 호출하거나, 필드에 접근할 수 있다. 리플렉션 단점 1) 컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다. 리플렉션 기능을 써서 존재하지 않는 혹은 접근할 수 없는 메서드를 호..
인터페이스 타입 사용 매개변수 타입으로 클래스가 아니라 인터페이스를 사용해야한다. 또한 적합한 인터페이스만 있다면, 매개변수 뿐만 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하라. 객체의 실체 클래스를 사용해야할 상황은 오직 생성자로 생성할때 뿐이다. 좋은 예. 인터페이스를 타입으로 사용 Set test = new LinkedHashSet(); 나쁜 예. 클래스를 타입으로 사용 LinkedHashSet test = new LinkedHashSet(); 인터페이스를 타입으로 사용하는 습관을 길러두면 프로그램이 훨씬 유연해질 수 있다. 만약 구현 클래스를 교체하고자한다면 그저 새 클래스의 생성자(혹은 다른 정적 팩터리)를 호출해주기만 하면 된다. 구현 클래스 유연하게 변경 Set test =..
문자열 연결시 String 대신 StringBuilder을 사용 권장 문자열 연결 연산자(+)는 여러 문자열을 하나로 합쳐주는 편리한 수단이다. 이는 한줄짜리 출력값 혹은 작고 크기가 고정된 객체의 문자열 표현을 만들때는 괜찮지만, 본격적으로 사용하기 시작하면 성능 저하를 감내하기 어렵다. 문자열 연결 연산자로 문자열 n개를 잇는 시간은 n의 제곱에 비례한다. 문자열은 불변이라서 두 문자열을 연결할 경우 양쪽의 내용을 모두 복사하므로 성능 저하를 피할 수 없는 결과다. 문자열 연결을 잘못 사용한 예시 - 느리다 package com.java.effective.item63; public class Main { public static void main(String[] args) { } public Stri..
문자열을 쓰지않아야할 사례 문자열(String)은 텍스트를 표현하도록 설계되었다. 자바에서 문자열을 의도하지 않은 용도로도 쓰이는 경향이 있는데, 문자열을 쓰지 않아야할 사례에 대해 알아보자. 1) 문자열은 다른 값 타입을 대신하기에 적합하지 않다. 많은 사람이 파일, 네트워크, 키보드 입력으로부터 데이터를 받을 때 주로 문자열을 사용한다. 입력받을 데이터가 진짜 문자열일 경우에만 사용해야한다. 받은 데이터가 수치형이라면 int, float, BigInteger 등 적당한 수치 타입으로 변환해야한다. 기본 타입이든 참조 타입이든 적절한 값 타입이 있다면 그것을 사용하고, 없다면 새로 하나 작성하라. 2) 문자열은 열거타입을 대신하기에 적합하지 않다. 문자열보다는 열거 타입이 월등히 낫다. 3) 문자열을 ..
기본타입과 박싱된 기본타입 자바이 데이터 타입은 크게 두가지로 나눌 수 있다. 바로 int, double, boolean과 같은 기본 타입과 String, List 같은 참조 타입이다. 각각의 기본 타입에 대응하는 참조 타입이 하나씩 존재하고, 이를 박싱된 기본타입이라고 한다. 기본타입 int, double, boolean 박싱된 기본 타입 Integer, Duble, Boolean 오토박싱과 오토언박싱 덕분에 두 타입을 크게 구분하지 않고 사용할 수는 있지만, 둘의 차이는 분명하다. 따라서 상황에 따라 주의해서 선택해야한다. 기본 타입과 박싱 기본타입의 차이 1) 기본 타입은 값만 가지고 있으나, 박싱된 기본 타입은 값에 더해 식별성이란 속성을 갖는다. 박싱된 기본 타입의 두 인스턴스는 값이 같아도 서..
float와 double 타입의 단점 float 와 double 타입은 과학과 공학 계산용으로 설계되었다. 이는 정확한 결과가 필요할 때는 사용하면 안된다. float와 double 타입은 특히 금융 관련 계산과는 맞지 않는다. 0.1 혹은 10의 음의 거듭제곱수 등을 표현할 수 없기 때문이다. 오류 발생하는 코드 package com.java.effective.item60; public class Main { public static void main(String[] args) { double funds = 1.00; int itemBought = 0; for (double price = 0.10; funds >= price; price += 0.10) { funds = funds - price; it..
표준 라이브러리 사용 이유 무작위 정수 하나를 생성하는 예제 코드를 보자. package com.java.effective.item59; public class Random { static java.util.Random rnd = new java.util.Random(); static int random(int n) { return Math.abs(rnd.nextInt()) % n; } } 위 코드는 흔하지만 문제가 많은 코드다. 1) n이 크지 않은 2의 제곱수라면 얼마 지나지않아 같은 수열이 반복된다. 2) n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된다. 3) n 값이 크면 이 현상은 더 두드러진다. 다음 코드는 예시를 위해 특정 범위에서 무작위 수를 백만개 생성한 다음, 그 ..
전통적인 for문 각 경우에 따라 스트림이 제격인 작업이 있고 반복이 제격인 작업이 있다. 컬렉션 순회하기 - 더 나은 방법 package com.java.effective.item58; public class Main { public static void main(String[] args) { for (Iterator i = c.iterator(); i.hasNext();) { element e = i.next(); ... // e 로 무언가를 한다. } } } 배열 순회하기 package com.java.effective.item58; public class Main { public static void main(String[] args) { for (int i = 0; i < a.length; i+..