분류 전체보기
-
[Effective Java] 아이템29: 이왕이면 제네릭 타입으로 만들라Language/Java 2022. 8. 6. 09:32
아이템7에서 다룬 스택 코드는 원래 제네릭 타입이어야 마땅하다. 다음과 같이 타입 매개변수 E를 추가하고, Object를 적절한 타입 매개변수로 바꾸어준다. public class Stack { private E[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { // 컴파일 오류. 실체화 불가 타입으로는 배열을 만들 수 없다. elements = new E[DEFAULT_INITIAL_CAPACITY]; } public void push(E e) { ensureCapacity(); elements[size++] = e; } public E pop() { if (si..
-
[Effective Java] 아이템28: 배열보다는 리스트를 사용하라Language/Java 2022. 7. 30. 02:29
✔️ 배열 vs 제네릭 타입 1. 배열은 공변(covariant)인 반면, 제네릭은 불공변(invariant)이다. Sub가 Super의 하위 타입이라면 배열 Sub[]는 배열 Super[]의 하위 타입이 되지만, List은 List의 하위 타입도 아니고 상위 타입도 아니다. 2. 배열은 실체화(reify)된다. 배열은 런타임에도 원소의 타입을 확인한다. 즉, 런타임에 예외가 발생할 수 있다. 반면, 제네릭은 타입 정보가 런타임에는 소거된다. 원소 타입을 컴파일타임에만 검사하며 런타임에는 알 수조차 없다. 💡 위와 같은 차이로 인해, 배열과 제네릭은 잘 어우러지지 못한다. 예를 들어, 배열은 제네릭 타입(new List[]), 매개변수화 타입(new List[]), 타입 매개변수(new E[])로 사용할..
-
[Effective Java] 아이템27: 비검사 경고를 제거하라Language/Java 2022. 7. 29. 19:08
✔️ 할 수 있는 한 모든 비검사 경고를 제거하라. 모두 제거한다면 그 코드는 타입 안전성이 보장된다. 즉, 런타임에 ClassCastException이 발생할 일이 없다. ✔️ 경고를 제거할 수는 없지만 타입 안전하다고 확신할 수 있다면 @SuppressWarning("unchecked") 애너테이션을 달아 경고를 숨기자. 안전하다고 검증된 비검사 경고를 숨기지 않고 그대로 두면, 진짜 문제를 알리는 새로운 경고가 나와도 눈치채지 못할 수 있다. 단, 경고를 무시해도 안전한 이유를 항상 주석으로 남겨야 한다. ✔️ @SuppressWarning 애너테이션은 항상 가능한 한 좁은 범위에 적용하자. @SuppressWarning 애너테이션은 개별 지역변수 선언부터 클래스 전체까지 어떤 선언에도 달 수 있다..
-
[Effective Java] 아이템26: 로 타입(raw type)은 사용하지 말라Language/Java 2022. 7. 29. 16:29
✔️ 제네릭 타입과 로 타입 클래스와 인터페이스 선언에 타입 매개변수가 쓰이면 제네릭 클래스 혹은 제네릭 인터페이스라고 하며, 두 가지를 통틀어 제네릭 타입(generic type)이라고 한다. 로 타입(raw type)이란 타입 매개변수가 없는 제네릭 타입을 말한다. 예를 들어, List의 로 타입은 List다. 로 타입은 타입 선언에서 제네릭 타입 정보를 전부 지워진 것처럼 동작하는데, 제네릭이 도래하기 전 코드와 호환되도록 하기 위한 궁여지책이라 할 수 있다. ✔️ 컬렉션의 로 타입 컬렉션 로 타입을 사용할 경우, 엉뚱한 타입을 넣어도 오류 없이 컴파일되고 실행될 수 있다. 이 경우, 형변환 시 ClassCastException을 던지게 된다. 📍 컬렉션의 로 타입 → 좋지 않은 예! private..
-
[Effective Java] 아이템25: 톱레벨 클래스는 한 파일에 하나만 담으라Language/Java 2022. 7. 23. 00:06
소스 파일 하나에 여러 개의 톱레벨 클래스를 선언하더라도 자바 컴파일러는 불평하지 않는다. 하지만 아무런 득이 없을 뿐더러 심각한 위험을 감수해야 한다. 한 클래스를 여러 가지로 정의할 수 있으며, 그 중 어느 것을 사용할지는 어느 소스 파일을 먼저 컴파일하느냐에 따라 달라지기 때문이다. 💡 예제 Main.java public class Main { public static void main(String[] args) { System.out.println(Utensil.NAME + Dessert.NAME); } } Utensil.java // 두 클래스가 한 파일(Utensil.java)에 정의되었다. - 따라 하지 말 것! class Utensil { static final String NAME = "..
-
[Effective Java] 아이템24: 멤버 클래스는 되도록 static으로 만들라Language/Java 2022. 7. 22. 23:42
✔️ 중첩 클래스(nested class)란? 중첩 클래스는 '다른 클래스 안에 정의된 클래스'를 말한다. 자신을 감싼 바깥 클래스에서만 사용되어야 하며, 그 외의 쓰임새가 있다면 톱레벨 클래스로 만들어야 한다. 💡 종류 (4가지) 정적 멤버 클래스 비정적 멤버 클래스 익명 클래스 지역 클래스 첫 번째를 제외한 나머지(비정적 멤버 클래스, 익명 클래스, 지역 클래스)는 모두 내부 클래스(inner class)에 해당한다. ✔️ 정적 멤버 클래스 다른 클래스 안에 선언되고, 바깥 클래스의 private 멤버에도 접근할 수 있다. 흔히 바깥 클래스와 함께 쓰일 때만 유용한 public 도우미 클래스로 쓰인다. private 정적 멤버 클래스는 흔히 바깥 클래스가 표현하는 객체의 한 부분, 즉 구성요소로 나타..
-
[Effective Java] 아이템23: 태그 달린 클래스보다는 클래스 계층구조를 활용하라Language/Java 2022. 7. 18. 12:10
✔️ 태그 달린 클래스 📍 예시 class Figure { enum Shape { RECTANGLE, CIRCLE }; // 태그 필드 - 현재 모양을 나타낸다. final Shape shape; // 다음 필드들은 모양이 사각형(RECTANGLE)일 때만 쓰인다. double length; double width; // 다음 필드는 모양이 원(CIRCLE)일 때만 쓰인다. double radius; // 원용 생성자 Figure(double radius) { shape = Shape.CIRCLE; this.radius = radius; } // 사각형용 생성자 Figure(double length, double width) { shape = Shape.RECTANGLE; this.length = len..
-
[Effective Java] 아이템22: 인터페이스는 타입을 정의하는 용도로만 사용하라Language/Java 2022. 7. 16. 01:10
인터페이스는 자신을 구현할 클래스의 인스턴스를 참조할 수 있는 타입 역할을 한다. 인터페이스는 오직 이 용도로만 사용해야 한다. ✔️ 상수 인터페이스 - 잘못된 사용 예시 인터페이스를 타입을 정의하는 용도로 사용하지 않은 대표적인 예로 상수 인터페이스를 들 수 있다. 상수 인터페이스란, 메서드 없이 상수를 뜻하는 static final 필드로만 가득 찬 인터페이스를 말한다. 📍 상수 인터페이스 안티패턴 // 상수 인터페이스 안티패턴 - 사용금지! public interface PhysicalConstants { // 아보가드로 수 (1/몰) static final double AVOGADROS_NUMBER = 6.022_140_857e23; // 볼츠만 상수 (J/K) static final double..