java
ordinal 인덱싱 대신 EnumMap을 사용하라 - [6장. 열거 타입과 애너테이션(아이템37)]
배열의 인덱스를 얻기 위해 ordinal을 쓰는 거은 일반적으로 좋지 않으니, 대신 EnumMap을 사용하도록 하자. 아래의 2가지 상황(일차원 관계, 다차원 관계)을 통해 왜 EnumMap을 사용해야 하는지 알아보도록 하자. 1. 1차원 관계에서의 EnumMap 아래의 Plant 클래스를 통해 식물의 이름(name)과 생애주기(lifeCycle)를 간단히 나타낼 수 있다. public class Plant { enum LifeCycle { ANNUAL, PERENNIAL, BIENNIAL } // 한해살이, 여러해살이, 두해살이 final String name; final LifeCycle lifeCycle; public Plant(String name, LifeCycle lifeCycle) { thi..
비트 필드 대신 EnumSet을 사용하라 - [6장. 열거 타입과 애너테이션(아이템36)]
📙 1. 비트 필드 열거한 값들이 주로 집합으로 사용될 경우, 예전에는 각 상수에 서로 다른 2의 거듭제곱 값을 할당한 정수 열거 패턴을 사용했었다. (비트마스킹을 이용했다고 할 수 있다.) public class Text { public static final int STYLE_BOLD = 1
ordinal 메서드 대신 인스턴스 필드를 사용하라 - [6장. 열거 타입과 애너테이션(아이템35)]
대부분의 열거 타입 상수는 자연스럽게 하나의 정숫값에 대응된다. 그리고 모든 열거 타입은 해당 상수가 그 열거 타입에서 몇 번째 위치인지를 반환하는 ordinal이라는 메서드를 제공한다. 그래서 열거 타입 상수와 연결된 정숫값이 필요하다면 ordinal 메서드를 사용하면 되지 않을까라는 생각을 할 수 있다. 결론부터 말하자면 그렇게 사용하면 안 된다. '왜 그렇게 사용하면 안 되는지'와 '그러면 언제 ordinal을 사용해야 하는지'에 대해서 알아보자. 📙 1. 열거 타입 상수와 연결된 정숫값을 얻기 위해 ordinal 메서드를 사용하면 안 되는 이유 public enum Ensemble { SOLO, DUET, TRIO, QUARTET, QUINTET, SEXTET, SEPTET, OCTET, NONE..
자바의 컴파일 과정
자바는 JVM(Java Virtual Machine) 덕분에 OS에 독립적인 특징을 가지고 있다. JVM의 어떠한 기능 때문에 OS에 독립적으로 실행시킬 수 있는지 자바의 컴파일 과정을 통해 알아보자. 📙 1. 컴파일 과정 자바의 컴파일 과정은 다음과 같다. 개발자가 작성한 자바 소스파일(*. java)을 자바 컴파일러(Java Compiler)가 바이트파일(*.class)로 컴파일한다. (CPU가 이해할 수 있는 언어인 바이너리 코드가 아니라 JVM이 이해할 수 있는 바이트 코드를 가진 바이트 파일로 변환한다.) 클래스 로더(Class Loader)를 통해 바이트 파일(*.class)들을 JVM에 올린다. JVM에 있는 바이트 파일(*.class)들은 실행 엔진(Execution Engine)의 인터프..
인터페이스(Interface)
JDK1.8부터 디폴트 메서드와 static 메서드도 인터페이스에서 사용할 수 있게 되었다. 일단은 JDK1.8 이전의 인터페이스에 대해서 먼저 살펴보고, 그리고 JDK1.8에서 추가된 기능(디폴트 메서드, static 메서드)과 Java9부터 사용할 수 있는 private 메서드에 대해서 살펴보는 것으로 하자. 📙 1. 인터페이스란 인터페이스란 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없다. 오직 추상메서드와 상수만을 멤버로만 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않는다. 인터페이스도 추상클래스처럼 완성되지 않은 불안전한 것이기 때문에 그 자체..
추상 클래스(Abstract Class)
📙 1. 추상클래스란? public abstract class Player { abstract void play(); abstract void stop(); } 클래스를 설계도라고 한다면, 추상클래스(Abstract Class)는 미완성 설계도라고 할 수 있다. 여기서 말하는 미완성은 단지 미완성 메서드(추상 메서드)를 포함하고 있다는 의미이다. 미완성 설계도로 완성된 제품을 만들 수 없듯이 추상 클래스로 인스턴스를 생성할 수 없다. 추상 클래스는 상속을 통해서 자손클래스에 의해서만 완성될 수 있다. 추상 클래스 자체로는 클래스로서의 역할을 다 못하지만, 새로운 클래스를 작성하는 데 있어서 바탕이 되는 조상 클래스로서 중요한 의미를 갖는다. 추상 클래스는 클래스에 추상화를 접목시켜 보다 구조적이게 객체를..
배열(Array)
📙 1. 배열이란? 배열(Array)이란 같은 타입의 여러 변수를 하나의 묶음으로 다루는 것을 말한다. 배열을 구성하는 각각의 값을 배열 요소(Element)라고 하며, 배열에서의 위치를 가리키는 숫자를 인덱스(Index)라고 한다. 📙 2. 배열 선언 & 생성 & 초기화 📌 1. 배열 선언 배열을 선언하는 방법은 원하는 타입의 변수를 선언하고 변수 또는 타입에 배열임을 의미하는 대괄호를 붙이면 된다. public static void main(String[] args) { int[] numbers; String[] names; } 📌 2. 배열 생성 배열을 선언한 다음에는 배열을 생성해야 한다. 배열을 선언하는 것은 단지 생성된 배열을 다루기 위한 참조변수를 위한 공간이 만들어질 뿐이고, 배열을 생성해..
제네릭과 가변인수를 함께 쓸 때는 신중하라 - [5장. 제네릭(아이템32)]
1. 가변인수 & 제네릭 💪 가변인수(varargs)란 매개변수로 들어오는 값의 개수와 상관없이 동적으로 인수를 받아서 기능하도록 해주는 문법을 말한다. public PrintStream printf(String format, Object ... args) { return format(format, args); } 가변인수 메서드를 호출하면 가변인수를 담기 위한 배열이 자동으로 하나 만들어진다. 만약 다음과 같이 제네릭과 가변인수를 함께 사용하면 어떻게 될까? static void dangerous(List... stringLists) { } 이 경우에도 가변인수 메서드가 호출되기 때문에 가변인수를 담기 위한 배열이 자동으로 만들어진다. 즉, 제네릭 배열이 만들어지는 것이다. 일반적으로는 제네릭 배열을 ..
한정적 와일드카드를 사용해 API 유연성을 높이라 - [5장. 제네릭(아이템31)]
1. PECS 🌞 PECS(Producer-Extends, Consumer-Super)란 매개변수화 타입 T가 생산자라면 에는 null 외에는 어떤 값도 넣을 수 없기 때문이다. 그래서 아래와 같이 도우미 메서드를 따로 작성해서 사용해야 한다. public class Swap { public static void swap(List list, int i, int j) { swapHelper(list, i, j); } private static void swapHelper(List list, int i, int j){ list.set(i, list.set(j, list.get(i))); } } 해당 글은 백기선 님의 '이펙티브 자바 완벽 공략'을 참고하였습니다.
이왕이면 제네릭 타입으로 만들라 - [5장. 제네릭(아이템29)]
1. 들어가기 전 🏄♀️ 아래의 Object 기반으로 만들어진 Stack 클래스를 살펴보자. public class Stack { private Object[] elements; private int size = 0; private static final int DEFAULT_INITIAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITIAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if(size == 0) throw new EmptyStackException(); Object resu..
배열보다는 리스트를 사용하라 - [5장. 제네릭(아이템28)]
1. 배열과 제네릭 타입의 차이 🦗 📗 1. 배열은 공변이고, 제네릭은 불공변이다. 배열은 공변(Convariant)이다. Sub가 Super의 하위 타입이라면 Sub[]는 배열 Super[]의 하위 타입이다. 제네릭은 불공변(Invariant)이다. 서로 다른 타입 Type1과 Type2가 있을 때, List은 List의 하위 타입도 아니고 상위 타입도 아니다. 공변과 불공변 중 어느 쪽이 문제가 있을까? 코드를 통해 알아보자. public static void main(String[] args) { // 배열 Object[] objectArray = new Long[1]; objectArray[0] = "타입이 달라서 넣을 수 없다."; // ArrayStoreException (런타임에 발생) //..
비검사 경고를 제거하라 - [5장. 제네릭(아이템27)]
1. 비검사 경고 개념 🦜 '비검사(unchecked) 경고'란 컴파일러가 타입 안전성을 확인하는데 필요한 정보가 충분하지 않을 때 발생시키는 경고이다. 비검사 경고의 예시 중에 하나로 다음과 같이 로 타입을 사용하는 경우를 들 수 있다. public static void main(String[] args) { // 비검사 경고 발생 // Raw use of parameterized class 'Set' Set names = new HashSet(); // 비검사 경고 발생 // Raw use of parameterized class 'HashSet' Set strings = new HashSet(); } 2. 비검사 경고를 제거해야 하는 이유 🦚 이번 아이템에서는 '비검사 경고를 제거하라'라고 말하고 ..