
// 예외를 완전 잘못 사용한 예 try { int i = 0; while (true) { range[i++].climb(); } } catch (ArrayIndexOutOfBoundsException e) { } 위 코드는 직관적이지 않게 예외를 작성하였다. 무한루프를 돌다가 배열의 끝에 도달해 예외가 발생하면 끝을 내는 것이다. 이 코드를 아래와 같이 작성 했다면 모든 프로그래머가 이해할 수 있을 것이다. for(Mountain m : range) m.climb(); 그런데 예외를 쓴 이유가 무엇일까? 3가지 면에서 잘못된 추론을 해서 예외를 사용한게 더 성능이 좋을 것이라고 생각했을 가능성이 있다. 이를 바로잡고자 한다. 1) 예외는 예외상황에 쓸 용도로 설계되어서 JVM 구현자 입장에서는 명확한 ..

철자 규칙 패키지, 클래스, 인터페이스, 메서드, 필드, 타입 변수의 이름을 다룸 특별한 이유가 없는 한 따라야함 → 어기면 코드를 읽기 어렵고 유지보수하기 어려움 1) 패키지와 모듈 각 요소를 점(.)으로 구분하여 계층적으로 짓기 요소들은 모두 소문자 알파벳 혹은 드물게 숫자로 이루어짐 조직의 인터넷 도메인 이름을 역순으로 사용 ex) com.google, org.eff 예외로 표준 라이브러리는 java, 선택 패키지들은 javax로 시작 패키지 이름의 나머지는 해당 패키지를 설명하는 하나 이상의 요소로 이루어짐 각 요소는 8자 이하의 짧은 단어로 (한 단어 혹은 약어) 2) 클래스와 인터페이스 하나 이상의 단어로 이루어짐, 각 단어는 대문자로 시작 ex) List 여러 단어의 첫글자만 딴 약자나 ma..

최적화는 오히려 좋은 결과보다 해로운 결과로 이어지기 쉽다. 빠르지도 않고 제대로 동작하지도 않고 수정하긴 어려운 소프트웨어가 탄생할 수 있다. 빠른 프로그램보다는 좋은 프로그램을 작성하라 성능 때문에 견고한 구조를 희생하지 말자. (견고한 구조 - 내부 응집성이 높고 외부와 결합성이 낮은) 좋은 프로그램은 정보 은닉 원칙을 따라 개별 컴포넌트의 내부가 독립적으로 설계됨 → 나머지에 영향 주지않고도 각 요소를 재설계 가능 [아이템 15] 완성된 아키텍처의 결함이 성능을 제한하는 상황이라면 시스템 전체를 작성해야 해결 할 수 있기 때문에 설계 단계에서 성능을 반드시 염두에 두자. 성능을 제한하는 설계를 피하라 완성 후 변경하기 가장 어려운 설계 요소는 컴포넌트끼리, 또는 외부 시스템과의 소통 방식 ex) ..

자바 네이티브 인터페이스 (Java Native Interface, JNI) 자바 프로그램이 네이티브 메서드를 호출하는 기술 네이티브 메서드 : C나 C++ 같은 네이티브 프로그래밍 언어로 작성한 메서드 네이티브 메서드의 주요 쓰임 1) 레지스트리 같은 플랫폼 특화 기능 사용 자바가 성숙해가면서 (OS같은) 하부 플랫폼 기능을 흡수하고 있음 → 점차 네이티브 메서드 사용 필요성 감소 ex) 자바9는 processAPI를 추가하여 OS 프로세스에 접근할 수 있도록 함 2) 네이티브 코드로 작성된 기존 라이브러리 사용 레거시 데이터를 사용하는 레거시 라이브러리 대체할만한 자바 라이브러리가 없는 네이티브 라이브러리를 사용해야할때 네이티브 메서드 써야함 3) 성능 개선을 목적으로 성능에 결정적인 영향을 주는 영..

리플렉션 ( java.io.reflect ) 리플렉션 기능을 이용하면 임의의 클래스에 접근할 수 있다. 자바 클래스파일 정보는 컴파일되면 클래스파일로 변환되어 메모리의 Static 영역에 위치 Static 영역의 정보는 언제든지 접근할 수 있기 때문에 클래스의 이름만 알면 정보들을 가져올 수 있음 Class 객체가 주어지면 그 클래스의 생성자, 메섣, 필드에 해당하는 인스턴스를 가져올 수 있음 인스턴스들로 그 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있음 인스턴스를 이용하여 각각에 연결된 생성자, 메서드, 필드 조작 가능 (해당 클래스 인스턴스 생성, 메서드 호출, 필드 접근 등 가능) // 클래스 얻기 Class class = Class.forName(); //생성자 얻기 Co..

적합한 인터페이스만 있다면 매개변수[아이템 51] 뿐 아니라 반환값, 변수, 필드를 전부 클래스가 아닌 인터페이스 타입으로 선언하라. (객체의 실제 클래스를 사용할 상황은 오직 생성자로 생성할 때뿐) //좋은 예 : 인터페이스를 타입으로 사용 Set sonSet = new LinkedHashSet(); //나쁜 예 : 클래스를 타입으로 사용 LinkedHashSet sonSet = new LinkedHashSet(); 인터페이스를 타입으로 사용할 때 유연성 증가 프로그램이 훨씬 유연해진다. 나중에 구현 클래스를 교체하고 싶다면 그저 새 클래스의 생성자 or 다른 정적 팩터리를 호출해주기만 하면 된다. 다른 코드는 전혀 손대지 않아도 된다. //Set sonSet = new LinkedHashSet(); ..

문자열 연결 연산자 (+) 문자열 연결 연산자(+)는 여러 문자열을 편리하게 합쳐주지만, 본격적으로 사용하면 성능 저하를 감내하기 어려움 문자열 연결 연산자로 문자열 n개를 잇는 시간은 n^2에 비례 (문자열은 불변 [아이템 17] 이라서 두 문자열 연결 시 양쪽 내용을 모두 복사해줘야해서) //문자열 연결을 잘못 사용한 예 - 느리다 public String statement() { String result = ""; for(int i=0; i

문자열을 쓰지 않아야 할 사례 1) 문자열은 다른 값 타입을 대신하기에 적합하지 않다. 기본 타입이든 참조 타입이든 적절한 값 타입이 있다면 그것을 사용하고, 없다면 새로 하나 작성하라. 2) 문자열은 열거 타입을 대신하기에 적합하지 않다. 상수를 열거할때는 문자열보다 열거 타입이 월등히 좋다. [아이템 34] 3) 문자열은 혼합 타입을 대신하기에 적합하지 않다. 여러 요소가 혼합된 데이터를 하나의 문자열로 표현하는 것은 좋지 않다. String compoundKey = className + "#" + i.next(); 각 요소를 개별로 접근하려면 문자열을 파싱해야해서 느리고 귀찮고 오류 가능성도 커진다. equals, toString, compareTo 메서드를 제공할 수 없다. → 차라리 전용 클래스..