한 메서드를 여러 스레드가 동시에 호출할 때 그 메서드가 어떻게 동작하느냐는 해당 클래스와 이를 사용하는 클라이언트 사이의 중요한 계약과 같다. API 문서에 아무런 언급도 없으면 그 클래스 사용자는 나름의 가정을 해야하고 그 가정이 틀리면 동기화를 충분히 하지 못하거나 지나치게한 상태로 심각한 오류로 이어질 수 있다. synchronized 키워드 API 문서에 synchronized 한정자가 보이는 메서드는 스레드에 안전하다고 들었겠지만 자바독 기본 옵션에서 생성한 API문서에는 synchronized 한정자가 포함되지 않는다. 메서드 선언에 synchronized 한정자를 선언할지는 구현 이슈일 뿐 API에 속하지 않아 그 메서드가 스레드 안전하다고 믿기 어렵다. 멀티스레드 환경에서도 API를 안전..
자바는 문제 상화을 알리는 타입(Throwable)으로 세 가지를 제공한다. 검사 예외 런타임 예외 에러 검사예외 호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하라. 검사와 비검사 예외를 구분하는 기본 규칙으로 검사 예외를 던지면 호출자가 그 예외를 catch로 잡아 처리하거나 더 상위 객체로 예외를 던지도록 강제한다. RuntimeException을 빼면 모두 검사 예외(checked exception)들이다. 만드려는 API에 반드시 예외적인 상황이 나올 수 있다면 checked exception을 던져 사용한 클라이언트가 예외적인 상황을 처리하도록 강제한다. 상위로 다시 던지거나 try/catch 하지 않으면 컴파일이 되지 않도록 강제하게 된다. 마땅한 검사 예외가 없다면 Exce..
예외(Exception)란 사용자의 잘못된 어플리케이션 조작이나 개발자의 코딩 실수로 인해 발생하는 프로그램 오류를 말한다. 예외가 발생되면 프로그램은 곧바로 종료된다는 점에서 에러와 동일하나, 예외는 예외 처리를 통해 프로그램을 종료하지 않고 정상 실행 상태가 유지되도록 할 수 있다. 예외의 종류는 개발자가 코드 작성을 하고 .class 파일로 만들기 위해 컴파일을 진행할 때 아예 컴파일진행이 되지 않는 컴파일 예외(Checked Exception)와 Run 실행 후 애플리케이션 정상 동작중 발생되는 런타임 예외(Unchecked Exception) 두 종류가 있다. 컴파일 예외는 컴파일러가 예외처리 하라고 강제하여 알려주니 비교적 쉽게 예외처리를 할 수 있지만 런타임 예외는 명시적인 예외 처리가 강제..
자바 플랫폼은 명명 규칙이 잘 정립되어 있으며, 그 중 많은 것이 자바 언어 명세에 기술되어 있다. https://docs.oracle.com/javase/specs/index.html 자바의 명명 규칙은 크게 철자와 문법 두 범주로 나뉜다. 철자 규칙 패키지, 클래스, 인터페이스, 메서드, 필드, 타입 변수의 이름을 다룬다. 이 규칙들은 특별한 이유가 없는 한 반드시 따라야 한다. 이 규칙을 어긴 API는 사용하기 어렵고, 유지보수하기 어렵다. 철자 규칙이나 문법 규칙을 어기면 다른 프로그래머들이 그 코드를 읽기 번거로울 뿐 아니라 다른 뜻으로 오해할 수 있고 그로 인해 오류까지 발생할 수 있다. 패키지와 모듈 패키지와 모듈 이름은 각 요소를 점(.)으로 구분하여 계층으로 짓는다. 요소들은 모두 소문자..
최적화 격언 세개 (맹목적인 어리석음을 포함해) 그 어떤 핑계보다 효율성이라는 이름 아래 행해진 컴퓨팅 죄악이 더 많다(심지어 효율을 높이지도 못하면서). (전체의 97% 정도인) 자그마한 효율성은 모두 있자. 섣부른 최적화가 만악의 근원이다. 최적화를 할 때는 다음 두 규칙을 따르라. 첫번째, 하지마라. 두번째 (전문가 한정) 아직 하지 마라. 다시 말해, 완전히 명백하고 최적화되지 않은 해법을 찾을 때까지는 하지 마라. 최적화는 좋은 결과보다는 해로운 결과로 이어지기 쉽고, 섣불리 진행하면 특히 더 그렇다. 빠르지도 않고 제대로 동작하지도 않으면서 수정하기 어려운 소프트웨어를 탄생시키는 것이다. 좋은 프로그램 설계 방법 빠른 프로그램보다는 좋은 프로그램을 작성하라 좋은 프로그램이지만 원하는 성능이 나..
자바 네이티브 인터페이스(Java Native Interface, JNI)는 자바 프로그램이 네이티브 메서드를 호출하는 기술이다. 네이티브 메서드란 C나 C++ 같은 네이티브 프로그래밍 언어로 작성한 메서드를 말한다. 네이티브 메서드의 주요 쓰임 레지스트리 같은 플랫폼 트고하 기능 사용 네이티브 코드로 작성된 기존 라이브러리 사용. 레거시 데이터를 사용하는 레거시 라이브러리가 그 예 성능 개선을 목적으로 성능에 결정적인 영향을 주는 영역만 따로 네이티브 언어로 작성 플랫폼 특화 기능을 활용하려면 네이티브 메서드를 사용해야 하지만 자바가 발전하면서 OS같은 하부 플랫폼의 기능을 점차 흡수하고 있어서 네이티브 메서드를 사용할 필요가 계속 줄어들고 있다. 대체할 만한 자바 라이브러리가 없는 네이티브 라이브러리..
리플렉션(java.lang.reflect)을 이용하면 프로그램에서 임의의 클래스에 접근할 수 있다. Class 객체가 주어지면 그 클래스의 생성자, 메서드, 필드에 해당하는 Constructor, Method, Field 인스턴스를 가져올 수 있고 이 인스턴스들로는 그 클래스의 멤버 이름, 필드 타입, 메서드 시그니처 등을 가져올 수 있다. Constructor, Method, Field 인스턴스를 이용해 각각 연결된 실제 생성자, 메서드, 필드를 조작할 수 있다. 컴파일 당시에 존재하지 않던 클래스도 이용할 수 있다. 리플렉션의 단점 컴파일타임 타입 검사가 주는 이점을 하나도 누릴 수 없다. 예외 검사도 마찬가지로 프로그램이 리플렉션 기능을 써서 존재하지 않는 혹은 접근할 수 없는 메서드를 호출하려 시..
적합한 인터페이스만 있다면 매개변수뿐 아니라 반환값, 변수, 필드를 전부 인터페이스 타입으로 선언하라. 객체의 실제 클래스를 사용해야할 상황은 오직 생성자로 생성할 때뿐이다. Set 인터페이스를 구현한 LinkedHashSet 변수를 선언하는 올바른 예 Set sonSet = new LinkedHashSet(); 나쁜 예 LinkedHashSet sonSet = new LinkedHashSet(); 인터페이스를 타입으로 사용하는 습관을 길러두면 프로그램이 훨씬 유연해진다. 추후 구현 클래스를 교체하려면 그저 새 클래스의 생성자 혹은 다른 정적 팩터리를 호출해주기만 하면 된다. Set sonSet = new HashSet(); 주의할 점 원래의 클래스가 인터페이스의 일반 규약 이외의 특별한 기능을 제공하며..