본문 바로가기

코딩/JAVA 공부

[JAVA] 자바의 정석 _ 열거형(enum) / 애너테이션

 * 열거형(enum)

- 관련된 상수들을 같이 묶어 놓은 것. 

Java의 열거형은 타입과 값 모두 체크 가능!

class Card{
    static final int  CLOVER = 0;
    static final int HEART = 1;
    static final int DIAMOND = 2;
    static final int SPADE = 3;
    
    static final int TWO = 0;
    static final int THREE = 1;
    static final int FOUR = 2;
    
    final int kind;
    final int num;
}
----------------------------
class Card{
    enum Kind {CLOVER, HEART, DIAMOND, SPADE}
    enum Value {TWO, THREE, FOUR}
    
    final Kind kind; // 타입이 int가 아닌 Kind임
    final Value value;
}

- 정의하는 방법

enum 열거형 이름{상수명 1, 상수명 2,...} 기본적으로 0부터 차례대로 값이 부여됨

- 사용 방법

열거형 타입의 변수 선언하고 사용.

enum Direction {EAST, SOUTH, WEST, NORTH}

class Unit{
    int x,y;
    Direction dir;
    
    void init(){
    	dir = Direction.EAST; // 방향 EAST초 초기화
    }
}

- 특징

열거형 상수의 비교에 == 와 compareTo() 사용 가능

if (dir == Direction.EAST){
    x++;
} else if (dir > Direction.WEST){ // 에러, 비교연산자는 사용 불가
...
} else if (dir.compareTo(Direstion.WEST) > 0 { // compareTo() 는 가능

 

- 열거형의 조상 : java.lang.Enum                                       

Enum의 메서드
메서드 설명
Class<E> getDeclaringClass() 열거형의 Class객체를 반환
String name() 열거형 상수의 이름을 문자열로 반환
int ordinal() 열거형 상수가 정의된 순서를 반환 (0부터 시작)
T-valueOf(Class<T> enumType.String name) 지정된 열거형에서 name과 일치하는 열거형 상수 반환

values(), valueOf()는 컴파일러가 자동으로 추가.

static E[] values()
static E valueOf(String name)

Direction[] dArr = Direction.values();
for(Direction d : dArr)
    System.out.printf("%s=%d%n", d.name(), d.ordinal());

 ** 열거형 상수의 정체는 객체이다!?

 

 * 열거형에 멤버 추가하기

- 불연속적인 열거형 상수의 경우, 원하는 값을 괄호() 안에 적는다.

enum Direction{ EAST(1), SOUTH(5), WEST(-1), NORTH(10)}
// 괄호 안에 여러개 가능

- 괄호 사용하려면, 인스턴스 변수와 생성자를 새로 추가해 줘야 한다.

enm Direction{
    EAST(1), SOUTH(5), WEST(-1), NORTH(10);
    
    private final int value;			// 정수를 저장할 필드(인스턴스 변수) 추가
    Direction(int value){ this.value = value;}	// 생성자 추가
    
    public int getValue() return value;}
}

열거형의 생성자는 묵시적으로 private이므로 외부에서 객체 생성 불가.

 

 * 애너테이션

- 주석처럼 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공

 특정 프로그램에게 정보 제공. 

 ** /** ~ */ : Javadoc.exe 를 위한 주석

- 애너테이션의 사용 예

@Test // JUnit 에 정보를 전달! 
public void method(){
    ...
}

  * 표준 애너테이션

@Override

- 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다. (메서드 이름 잘못 적는 실수 방지)

- 오버라이딩 할 때는 메서드 선언부 앞에 @Override를 붙이자! (실수하면 에러가 떠 확인 가능)

 

@Deprecated

- 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙임.

- 안 쓰는 거 하위 호환성을 위해 없애진 않고 Deprecated 사용 에러가 생기진 않고 경고만 뜸.

@Deprecated
public int getDate(){
    return normalize().getDayOfMonth();
}

 

@FunctionalInterface

- 함수형 인터페이스에 붙이면 올바르게 작성했는지 컴파일러가 체크.

  함수형 인터페이스는 하나의 추상메서드만 가져야 한다는 제약 있음. 이게 제대로 됐는지 체크해줌.

- 함수형 인터페이스 작성 시 @FunctionalInterface를 작성하는 게 좋다.

 

@SuppressWarnings

- 컴파일의 경고 메시지가 나타나지 않게 억제한다. () 안에 억제하고자 하는 경고의 종류를 문자열로 지정

@SuppressWarnings("unckecked")	  // 지네릭스 관련된 경고 억제
ArrayList list = new ArrayList(); // 지네릭 타입을 지정하지 않아 경고 발생해야함
list.add(obj);

- 경고를 내가 체크했다는 의미!

 

 * 메타 애너테이션

- 애너테이션을 위한 애너테이션, java.lang.annotation 패키지에 포함, 애너테이션을 만들 때 사용

 

@Target

- 애너테이션을 정의할 때 적용대상 지정에 사용

@Target({FIELD, TYPE, TYPE_USE})    // MyAnnotation의 적용 대상을 {} 안으로 지정
public @interface MyAnnotation{  }  // MyAnnotation 정의 (@interface 사용)

@MyAnnotation		// 적용대상이 TYPE
class MyClass{
	
    @MyAnnotation	// 적용대상이 FIELD
    int i;
    
    @MyAnnotation	// 적용대상이 TYPE_USE
    MyClass mc;

 

@Retention

- 애너테이션이 유지되는 기간을 지정

SOURCE : 소스 파일에만 존재, 클래스 파일에는 존재 X (ex @Override)

CLASS     : 클래스 파일에 존재. 실행 시에는 사용 불가. 기본값.

RUNTIME : 클래스 파일에 존재, 실행시에 사용 가능 (ex @FunctionalInterface)

 

@Documented

- javadoc으로 작성한 문서에 포함시키려면 @Documented 붙임

 

@Ingerited

- 애너테이션을 자손 클래스에 상속하고자 할 때

 

@Repeatable

- 반복해서 붙일 수 있는 애너테이션을 정의할 때

 

 * 애너테이션 요소의 규칙

- 요소의 타입은 기본형, String, enum, 애너테이션, Class 만 허용

- 괄호() 안에 매개변수를 선언할 수 없다.

- 타입 매개변수 사용 불가

- 예외를 선언할 수 없다