본문 바로가기

이펙티브 자바

(61)
[이펙티브 자바] 아이템 29. 이왕이면 제네릭 타입으로 만들라 제네릭 타입 : 제네릭 타입은 자바에서 컬렉션과 같은 클래스나 인터페이스를 정의할 때, 타입 파라미터를 사용하여 타입 안정성을 확보하는 방법이다. 즉, 클래스나 인터페이스를 선언할 때 실제 타입이 아닌 타입 매개변수를 사용하여 일반화된 형태로 선언한다. // 제네릭을 사용하지 않은 ArrayList List list = new ArrayList(); list.add("Hello"); String item = (String) list.get(0); // 형변환 필요 // 제네릭을 사용한 ArrayList List list = new ArrayList(); list.add("Hello"); String item = list.get(0); // 형변환 필요 없음 결론 : 클라이언트에서 직접 형변환해야 하는 타..
[이펙티브 자바] 아이템 28. 배열보다는 리스트를 사용하라 공변성 (Covariance): 공변성은 서브타입 관계에서 타입이 변할 때 같은 방향으로 변하는 특성을 말합니다. 즉, A가 B의 서브타입인 경우, A 타입의 객체를 B 타입으로 변환할 수 있습니다. 예를 들어, List이 List의 서브타입이라면, List 타입의 객체를 List 타입으로 변환할 수 있습니다. 이것은 배열의 공변성과 유사합니다. 불변성 (Invariance): 불변성은 서브타입 관계에서 타입이 변하지 않는 특성을 말합니다. 즉, A가 B의 서브타입이더라도 A 타입의 객체를 B 타입으로 변환할 수 없습니다. 예를 들어, List이 List의 서브타입이 아니라면, List 타입의 객체를 List 타입으로 변환할 수 없습니다. 결론 : 배열과 제네릭에는 매우 다른 타입 규칙이 적용된다. 배열..
[이펙티브 자바] 아이템 27. 비검사 경고를 제거하라 비검사 경고(Unchecked Warning) : 컴파일러가 코드에서 타입 안전성을 검사하지 못하는 상황을 감지하여 발생하는 경고 메시지이다. 이 경고는 제네릭을 사용하는 코드에서 발생할 수 있는데, 일반적으로 제네릭을 사용하면서 발생하는 타입 캐스팅이나 원시 타입 사용 등의 상황에서 발생한다. 할 수 있는 한 모든 비검사 경고를 제거해야 한다. 비검사 경고를 제거할 수는 없지만 타입 안전하다고 확실할 수 있다면 @SuppressWarning("unchecked") 애너테이션을 달아 경고를 숨기자. 단 타입 안전함을 반드시 검증해야만 한다. 이 에너테이션을 사용했다면 그 경고를 무시해도 안전한 이유를 항상 주석으로 남겨야만 한다. 이 애너테이션은 보통은 변수 선언, 아주 짧은 메서드, 혹은 생성자 등 가..
[이펙티브 자바] 아이템 26. 로 타입은 사용하지 말라 로 타입(raw type) : 제네릭 클래스나 인터페이스에서 타입 매개변수를 명시하지 않고 raw 타입으로 사용하는 것을 의미 제네릭 : 자바에서 컬렉션 클래스 및 메서드, 인터페이스 등을 작성할 때 타입을 파라미터화하는 기능 컬렉션 클래스 : 자바에서 데이터를 모으고 관리하는 데 사용되는 클래스들의 집합 //잘못된 예 List list = new ArrayList(); // 로 타입 사용 list.add("hello"); list.add(123); String str = (String) list.get(0); // 형변환 필요 int num = (int) list.get(1); // 형변환 필요 //옳은 예 List list = new ArrayList(); // 제네릭 사용 list.add("hell..
[이펙티브 자바] 아이템 25. 톱레벨 클래스는 한 파일에 하나만 담으라 톱 레벨 클래스 : 다른 클래스의 내부에 정의되지 않고, 자체 파일에 독립적으로 존재하는 클래스. 즉, 톱 레벨 클래스는 패키지 내에서 최상위에 위치하는 클래스이며, 다른 클래스의 멤버가 아닌 독립된 클래스. 아래 예시는 한 파일에 두 개의 클래스가 정의된것이다. 절대 따라하면 안되는 코드이다. class Utensil { static final String NAME = "pan"; } class Dessert { stattic final String NAME = "cake"; } 위와 같은 코드로 작성할 경우 오류가 발생 할 수 있다. 이를 해결하려면 단순히 톱 레벨 클래스들을 서로 다른 소스 파일로 분리해주면 된다. 굳이 여러 톱 레벨 클래스를 한 파일에 담고 싶다면 정적 멤버 클래스로 만들 수 있다..
[이펙티브 자바] 아이템 24. 멤버 클래스는 되도록 static으로 만들라 중첩 클래스(nested class) : 다른 클래스 내부에 선언된 클래스. 중첩 클래스의 종류 4가지 : 정적 멤버 클래스 정적 멤버 클래스는 바깥 클래스의 인스턴스와 독립적으로 존재할 수 있는 클래스다. 즉, 바깥 클래스의 인스턴스 없이도 생성하고 사용할 수 있다. 정적 멤버 클래스는 바깥 클래스의 정적 멤버에만 접근할 수 있으며, 바깥 클래스의 인스턴스 멤버에는 접근할 수 없다. 비정적 멤버 클래스 비정적 멤버 클래스는 바깥 클래스의 인스턴스와 연관되어 있는 클래스다. 이러한 클래스의 객체는 바깥 클래스의 객체와 연결되어 있으며, 바깥 클래스의 인스턴스 멤버와 메서드에 접근할 수 있다. 비정적 내부 클래스는 바깥 클래스의 인스턴스를 통해서만 생성할 수 있다. 정적 클래스와 의 구문적 차이는 단지 s..
[이펙티브 자바] 아이템 23. 태그 달린 클래스보다는 클래스 계층구조를 활용하라 태그 달린 클래스(tagged class): 클래스 내부에 특정 "태그" 필드를 두어 객체의 유형을 나타내는 방식. 이러한 클래스는 보통 여러 유형의 객체를 하나의 클래스로 표현하고자 할 때 사용되며, 태그 값에 따라 다른 동작을 수행하도록 메서드들이 조건문(예: if-else, switch)을 사용해 구현된다. // 태그 달린 클래스 public class Shape { enum ShapeType { CIRCLE, RECTANGLE } final ShapeType shapeType; double radius; // 원일 경우 사용 double width; // 직사각형일 경우 사용 double height; // 직사각형일 경우 사용 // 원을 위한 생성자 Shape(double radius) { sh..
[이펙티브 자바] 아이템 22. 인터페이스는 타입을 정의하는 용도로만 사용하라 인터페이스 : 자신을 구현한 클래스의 인스턴스를 참조할 수 있는 타입 역할. 즉, 클래스가 어떤 인터페이스를 구현한다는 것은 자신의 인스턴스로 무엇을 할 수 있는지를 클라이언트에 얘기해주는 것이다. 인터페이스는 위의 지침에 맞지 않는 예로 상수 인터페이스라는 것이 있다. 상수 인터페이스란 메서드 없이, 상수를 뜻하는 static final 필드로만 가득 찬 인터페이스를 말한다. 상수 인터페이스 안티패턴의 예시 // 상수 인터페이스 예시 public interface CarConstants { int MAX_SPEED = 240; String ERROR_MESSAGE = "Operation not allowed"; } // 위의 상수 인터페이스는 이런식으로 사용될 수 있다. public class Spor..