Inheritance 앞장에서 상속을 염두에 두지 않고 설계했고 상속할 때의 주의점도 문서화 해놓지 않은 '외부'클래스를 상속할 때의 위험을 경고했다. 여기서 '외부'란 프로그래머의 통제권 밖에 있어서 언제 어떻게 변경될지 모른다는 뜻이다. 상속을 고려한 설계와 문
Interface 자바가 제공하는 다중 구현 메커니즘은 인터페이스와 추상클래스, 이렇게 두가지이다. 둘의 가장 큰 차이점은 추상클래스가 정의한 타입을 구현하는 클래스는 반드시 추상 클래스의 하위 클래스가 되어야 한다는 점이다. 자바는 단일 상속만을 지원핸, 추상클래
java 8이전에는 기존 구현체를 깨트리지 않고는 인터페이스에 메서드를 추가할 방법이 없었다. 인터페이스에 메서드를 추가하면 보통은 컴파일 오류가 나는데, 추가된 메서드가 우연히 기존 구현체에 이미 존재할 가능성은 아주 낮기 때문이다. 자바 8에 와서는 디폴트 메서드라
Inheritance 두 가지 이상의 의미를 표현할 수 있으며, 그중 현재 표현하는 의미를 태그 값으로 알려주는 클래스를 본 적이 있을 것이다. 예시) 태그 달린 클래스 이러한 클래스는 단점이 한가득이다. 우선 열거 타입 선언, 태그 필드, switch문 등 쓸데
Nested class 중첩 클래스(nested class)란 다른 클래스 안에 정의된 클래스를 말한다. 중첩 클래스는 자신을 감싼 바깥 클래스에서만 쓰여야 하며, 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야한다. 중첩 클래스의 종류는 정적 멤버 클래스, 비정적
소스 파일 하나에 톱레벨 클래스를 여러 개 선언하더라도 자바 컴파일러는 불평하지 않는다.하지만 아무런 득이 없을 뿐더러 심각한 위험을 감수해야 하는 행위다.물론 Main을 실행하면 pankake를 출력한다. 이제 우연히 똑같은 두 클래스를 담은 Dessert.java라
Raw Type Raw Type이란 제네릭 타입을 하나 정의하면 그에 딸린 로 타입(raw type)도 함께 정의된다. 로 타입이란 제네릭 타입에서 매개변수를 전혀 사용하지 않을 때를 말한다. 로 타입은 타입 선언에서 제네릭 타입 정보가 전부 지워진 것처럼 동작하는
제네릭을 사용하기 시작하면 수많은 컴파일러 경고를 보게 될 것이다. 비검사 형변환 경고, 비검사 메서드 호출 경고 등등..가능한한 모든 비검사 경고를 제거한다면 좋다. 모두 제거한다면 그 코드는 타입 안정성이 보장된다. 즉 런타임에 ClassCastException이
배열과 제네릭 타입에는 중요한 차이가 있다 첫째로, 배열은 공변이다. 공변의 의미는 Sub가 Super의 하위 타입이라면 배열\[]는 배열 Super\[]의 하위 타입이 된다. 반면 제네릭은 불공편이다. 즉, 서로 다른 타입 Type1, Type2가 있을때, Lis
Generic JDK가 제공하는 제네릭 타입과 메서드를 사용하는 일은 일반적으로 쉬운 편이지만, 제네릭 타입을 새로 만드는 일은 조금 더 어렵다. 아이템7에서 다룬 단순한 스택 코드를 살펴보자 Object 기반 스택 - generic이 절실하다 위의 클래스는 원래
Generic Method 클래스와 마찬가지로, 메서드도 제네릭으로 만들 수 있다. 매개변수화 타입을 받는 정적 유틸리티 메서드는 보통 제네릭이다. 제네릭 메서드 작성법은 제네릭 타입과 비슷하다. 다음은 두 집합의 합집합을 반환하는, 문제가 있는 메서드다. 로 타
이종 컨테이너 패턴 이란, Set, 혹은 Map에 기본적인 사용방식 보다 유연한 사용방식이 필요할 때 사용한다. 컨테이너 대신 키를 매개변수화한 다음, 컨테이너에 값을 넣거나 뺄 때 매개변수화 한 키를 함께 제공하는 방식이다.각 타입의 Class 객체를 매개변수화한 키
열거 타입은 일정 개수의 상수 값을 정의한 다음, 그 외의 값은 허용하지 않는 타입이다. 사계절, 태양계의 행성, 카드게임의 카드 종류 등이 좋은 예다. 자바에서 열거 타입을 지원하기 전에는 상수를 묶음으로 선언해서 사용하곤 했다.정수 열거 패턴 기법에는 단점이 많다.
재정의(overload)다중정의(overrid)이 코드에는 오류가 있다 무슨 오류가 있을까??"Set" 혹은 "List"를 출력할것 같지만, 실제로 수행해보면 "Unkown Collection"만 출력한다그 이유는 무엇일까? 다중정의(overloading)된 세 cla
Library Random Method 흔하지만 문제 있는 코드 이 메서드는 무작위 수를 출력해 줄것 같지만, n이 별로 크지 않은 2의 제곱수라면 얼마 지나지 않아서 같은 수열이 반복된다. 또 이 메서드의 결함은 지정한 범위 바깥의 수가 종종 나올 수 있다.
float과 double 타입은 과학과 공학 계산용으로 설계되었다.이진 부동소수점 연산에 쓰이며, 넓은 범위의 수를 빠르게 정밀한 ‘근사치’로 계산하도록 섬세하게 설계 되었다. 따라서 정확한 결과가 필요할 때는 사용하면 안된다. \*\*\*float과 double 타입
자바의 데이터 타입은 크게 두 가지로 나눌 수 있다. 바로 int, double, boolean 같은 기본 타입과 String, List 같은 참조 타입이다. 그리고 각각의 기본 타입에는 대응하는 참조 타입이 하나씩 있으며, 이를 박싱된 기본 타입이라고 한다. 예건태
String을 의도하지 않은 용도로 사용되기도 한다. 문자열을 쓰지 않아야할 사례를 알아보자.문자열은 값타입을 대신하기에 적합하지 않다 많은 사람이 파일, 네트워크, 키보드 입력으로부터 데이터를 받을 때, 주로 문자열을 사용한다. 사뭇 자연스러워 보이지만, 입력받을 데
문자열 연결 연산자(+)는 여러 문자열을 하나로 합쳐주는 편리한 수단이다. 하지만 한줄짜리 출력값 정도는 괜찮지만, 본격적으로 사용할 경우 성능저하가 일어난다. 문자열 n개를 잇는 시간은 n2에 비례한다 문자열은 불변이라서 두 문자열을 연결할 경우 양쪽의 내용 모두 복
아이템 51에서 매개변수 타입으로 클래스가 아닌 인터페이스를 사용하라고 했다. 이 조언을 객체는 클래스가 아닌 인터페이스로 참조하라고 확장할 수도 있다.인터페이스를 타입으로 사용하는 습관을 길러두면 프로그램이 훨씬 유연해질 것이다. 나중에 구현 클래스를 교체하고자 하다
자바 네이티브 인터페이스(Java Native Interface)는 자바 프로그램이 네이티브 메서드를 호출하는 기술이다. 여기서 네이티브 메서드란 C나 C++ 같은 네이티브 프로그래밍 언어로 작성한 메서드를 말한다.레지스트리 같은 플랫폼 특화 기능을 사용한다.네이티브
리플렉션 기능(java.lang.reflect)을 이용하면 프로그램에서 임의의 클래스에 접근할 수 있다. Class 객체가 주어지면 그 클래스의 생성자, 메서드, 필드에 해당하는 constructor, Method, Field 인스턴스를 가져올 수 있고, 이어서 이어서
최적화는 좋은 결과보다는 해로운 결과로 이어지기 쉽고, 섣불리 진행하면 특히 더 그렇다. 성능때문에 견고한 구조를 희생시키지 말자. 빠른 프로그램보다는 좋은 프로그램을 작성하라 좋은 프로그램이지만 원하는 성능이 나오지 않는다면 그 아키텍쳐 자체가 최적화할 수 있는 길을
자바 플랫폼은 명명 규칙이 잘 정립되어 있으며 그중 많은 것이 자바 언어 명세에 기술되어 있다. 명명 규칙은 크게 철저와 문법, 두 범주로 나뉜다.철자 규칙은 패키지, 클래스, 인터페이스 등 변수의 이름을 다룬다. 이 규칙은 특별한 이유가 없는 한 반드시 따라야 한다.
무슨 일을 하는지 절혀 알 수 없는 코드이다. 이 코드는 배열을 순회하는데, 끔찍한 방식으로 진행하고 있다. 무한 루프를 돌다가 배열의 끝에 도달해 예외가 발생하면 끝을 내는 것이다.이 코드는 성능 향상을 위해서 작성했다고 생각할 수 있지만, 표준 관용구(for-loo
자바는 문제 상황을 알리는 타입(throwable)으로 검사 예외, 런타임 예외, 에러, 이렇게 세 가지를 제공하는데, 언제 무엇을 사용해야 하는지 헷갈려 하는 프로그래머들이 있다.호출하는 쪽에서 복구하리라 여겨지는 상황이라면 검사 예외를 사용하라 이는 검사 예외와 비
검사 예외는 제대로 활용하면 api와 프로그램의 질을 높일 수 있다. 검사 예외는 발생한 문제를 프로그래머가 처리하여 안정성을 높이게끔 해준다. 물론 검사 예외를 사용하면, 오히려 쓰기 어려운 api가 된다. 어떤 메서드가 검사 예외를 던질 수 있다고 선언됐다면, 이를
표준 예외를 재사용한다면 얻는것이 많다. 내가 작성한 API가 다른 사람이 익히고 사용하기 쉬워지고, 많은 프로그래머에게 익숙한 규약을 그대로 따르기 때문이다. 그리고 여러분의 코드 역시 읽기 쉬워진다.가장 많이 사용되는 예외이다. 호출자가 인수로 부적절한 값을 넘길
수행하려는 일과 관련 없어 보이는 예외가 튀어나오면 당황스러울 것이다. 이는 윗 레벨 api를 오염 시킬 수 있다. 앞서 서술한 문제를 피하기 위해서는 상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꾸어 주어야 한다. 이를 예외 번역이라고 한다
메서드가 던지는 예외는 그 메서드를 올바로 사용하는데 아주 중요한 정보다.검상 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 javadoc의 @throw 태그를 사용하여 정확히 문서화 하자. 공통 상위 클래스 하나로 뭉뚱그려 선언하는 일은 삼가자. ex)
예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 스택 추적 정보를 자동으로 출력한다. 스택 추적은 예외 객체의 toString 메서드를 호출해 얻는 문자열이다.예외의 toString 메서드에 실패 원인에 관한 정보를 가능한 한 많이 담아 반환하는 일은 아주 중요하다
작업 도중 예외가 발생해도 그 객체는 여전히 정상적으로 사용할 수 있다면 멋지지 않을까? 호출된 메서드가 실패하더라도 해당 객체는 메서드 호출 전 상태를 유지해야 한다. 이러한 특성을 실패 원자적 이라고 한다.가장 간단한 방법은 불변 객체로 설계하는 것이다. 불변 객체
예외를 무시하지 말자.안타깝게도 예외를 무시하기란 아주 쉽다. 해당 메서드 호출을 try-catch로 감싼 후 catch 블록에서 아무것도 하지 않으면 된다.예외는 문제 상황에 대처하기 위해 존재하는데, catch블록을 비워두면 예외가 존재할 이유가 사라진다 비유하자면
synchronized 키워드는 해당 메서드나 블록을 한번에 한 스레드씩 수행하도록 보장된다.한 객체가 생성되고, 이 객체 접근하는 메서드는 그 객체에 lock을 건다. 락을 건 메서드는 객체의 상태를 확인하고 필요하면 수정한다. 즉, 객체를 하나의 일관된 상태에서 다
Wildcard 매게 변수화 타입은 불공변(invariant)이다. 즉 서로 다른 타입 Type1과 Type2가 있을때 은 의 하위 타입도 상위 타입도 아니다. 즉 은 와 아무 관계도 아니라는 말이다. 이처럼 매개변수화 타입은 고정되어 있지만 때로는 좀 더 유연하