티스토리 뷰

728x90
반응형

열거형(enum)

 

열거형(enum)은 Enumerated Type에서 왔다. 말 그대로 열거형.

 

열거형은 변하지 않는 한정된(연관된) 상수 데이터를 다루는 데 최적화된 타입이다.

 

<동, 서, 남, 북> 이나 <봄, 여름, 가을, 겨울>처럼 말이다.

 

enum 타입을 정의하는 방법은 간단하다.

enum Seasons { SPRING, SUMMER, FALL, WINTER }
enum Frameworks { DJANGO, SPRING, NEST, EXPRESS }

자바에서 상수는 관례적으로 대문자로 표기하도록 되어 있고,

 

배열의 경우와 비슷하게 자동으로 0부터 시작하는 정수값이 할당된다.

enum Seasons { 
SPRING,  //정수값 0 할당
SUMMER,  //정수값 1 할당
FALL,    //정수값 2 할당
WINTER   //정수값 3 할당
}

또한 열거형은 기본 타입들과 함께 switch문에서 사용 가능하다는 특징이 있다.

enum Seasons {SPRING, SUMMER, FALL, WINTER}

public class Main {
    public static void main(String[] args) {
        Seasons seasons = Seasons.SPRING;
        switch (seasons) {
            case SPRING:
                System.out.println("봄");
                break;
            case SUMMER:
                System.out.println("여름");
                break;
            case FALL:
                System.out.println("가을");
                break;
            case WINTER:
                System.out.println("겨울");
                break;
        }
    }
}

//출력 결과 
봄

열거형의 상수에 접근하는 방법은 위의 코드에서도 볼 수 있듯이 열거형 이름. 상수명이다.

 

static 필드와 접근 방법이 동일하다고 할 수 있다.

 

이어서 열거형에서 사용 가능한 메서드를 보자.

 

메서드가 사용된 예제는 아래와 같다.

enum Level {
    LOW,    // 0
    MEDIUM, // 1
    HIGH    // 2
}

public class EnumTest {
    public static void main(String[] args) {
        Level level = Level.MEDIUM;

        Level[] allLevels = Level.values();
        for(Level x : allLevels) {
            System.out.printf("%s=%d%n", x.name(), x.ordinal());
        }

        Level findLevel = Level.valueOf("LOW");
        System.out.println(findLevel);
        System.out.println(Level.LOW == Level.valueOf("LOW"));

        switch(level) {
            case LOW:
                System.out.println("낮은 레벨");
                break;
            case MEDIUM:
                System.out.println("중간 레벨");
                break;
            case HIGH:
                System.out.println("높은 레벨");
                break;
        }
    }
}

//출력 결과
LOW=0
MEDIUM=1
HIGH=2
LOW
true
중간 레벨

 


애너테이션(Annotation)

 

애너테이션(Annotation)은 해석하면 '주석'이다.

 

자바에서 이미 사용하던 Comment(주석)과 구분하기 위해 애너테이션이라 부른다.

 

주석(Comment)이 사람이 알아보기 위한 것이라면, 프로그램에게 정보를 전달하는 것을 애너테이션이라 부른다.

 

자바의 역사에서 일종의 관리방법으로 발달한 것이 애너테이션이라 할 수도 있겠다.

 

애너테이션의 주요한 역할은 다음과 같다.

 

  • 컴파일러에게 문법 에러 체크시키기
  • 프로그램 빌드시 자동으로 코드 생성
  • 런타임에 특정 기능을 실행하도록 정보 제공

또한, 애너테이션에는 총 세가지 종류가 있는데,

 

  • 표준 애너테이션
표준 애너테이션 설명
@Override 컴파일러에게 메서드를 오버라이딩하는 것이라고 알림
@Deprecated 앞으로 사용하지 않을 대상을 알릴 때 사용
@FunctionalInterface 함수형 인터페이스라는 것을 알림
@SuppressWarning 컴파일러가 경고메세지를 나타내지 않음

 

  • 메타애너테이션 - 애너테이션에 붙이는 애너테이션
메타 애너테이션 설명
@Target 애너테이션을 정의할 때 적용 대상을 지정하는데 사용한다.
@Documented 애너테이션 정보를 javadoc으로 작성된 문서에 포함시킨다.
@Inherited 애너테이션이 하위 클래스에 상속되도록 한다.
@Retention 애너테이션이 유지되는 기간을 정하는데 사용한다.
@Repeatable 애너테이션을 반복해서 적용할 수 있게 한다.

 

  • 사용자 정의 애너테이션

이 그것이다. 짧게 하나씩 살펴보자.


표준 애너테이션

 

@Override - 오버 라이딩을 올바로 했는지 컴파일러가 체크

class Super {
	void run() {}
}
class Sub extends Super {
	@Override
	void rnu() {} // 컴파일 에러 발생, 오타가 난 것을 발견할 수 있음.
}

 

@Deprecated - 앞으로 사용하지 않을 것을 권장

class OldClass {
	@Deprecated
	int oldField;

	@Deprecated
	int getOldField() { return oldField; };
}

호환성 때문에 유지는 하지만 사용하지 않을 것을 권장할 때 쓰인다.

 

@FunctionalInterface - 함수형 인터페이스를 올바로 작성했는지 컴파일러가 체크

 

함수형 인터페이스는 단 하나의 추상 메서드만을 가진 인터페이스이다.

@FunctionalInterface
public interface Runnable {
	public abstract void run (); // 하나의 추상 메서드
}

 

@SuppressWarning - 컴파일러가 경고 메시지를 나타내지 않음

 

경고가 많이 뜰 때, 이미 확인한 경고를 제외하고 새로운 경고를 보기 위해 사용한다.

 

한 번에 두 개 이상의 경고를 묵인할 수도 있다.

 


메타 애너테이션

 

@Target - 애너테이션을 적용할 대상을 지정

import static java.lang.annotation.ElementType.*; 
//import문을 이용하여 ElementType.TYPE 대신 TYPE과 같이 간단히 작성할 수 있다.

@Target({FIELD, TYPE, TYPE_USE})	// 적용대상이 FIELD, TYPE
public @interface CustomAnnotation { }	// 사용자 정의 애너테이션을 정의

@CustomAnnotation	// 적용대상이 TYPE인 경우
class Main {
    
		@CustomAnnotation	// 적용대상이 FIELD인 경우
    int i;
}

사용자 정의 애너테이션을 정의할 때 사용자가 정의한 애너테이션이 어디까지 적용되는지 설정할 수 있다.

 

@Documented - 애너테이션의 정보가 javadoc으로 작성한 문서에 포함

 

@Inherited - 하위 클래스가 애너테이션을 상속받도록 함

@Inherited // @SuperAnnotation이 하위 클래스까지 적용
@interface SuperAnnotation{ }

@SuperAnnotation
class Super { }

class Sub extends Super{ } // Sub에 애너테이션이 붙은 것으로 인식

 

@Retention - 애너테이션의 지속 기간을 설정

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE) 
//오버라이딩이 제대로 되었는지 컴파일러가 확인하는 용도 
//클래스 파일에 남길 필요 없이 컴파일시에만 확인하고 사라짐
public @interface Override(){ }

 

@Repeatable - 애너테이션을 여러번 붙일 수 있도록 허용

@Repeatable(Works.class) // ToDo 애너테이션을 여러 번 반복해서 쓸 수 있게 한다.  
@interface Work{  
    String value();  
}

@Work("코드 업데이트")  
@Work("메서드 오버라이딩")  
class Main{  
	... 생략 ...
}

Work 애너테이션을 하나의 대상에 여러번 적용한 것을 볼 수 있다.

 


사용자 정의 애너테이션

 

사용자 정의 애너테이션을 만드는 방법은 매우 쉽다.

 

위에 잠깐 예시가 나왔듯이 @interface를 이용해 작성하면 된다.

@interface 애너테이션명 { // @interface를 이용해 애너테이션 정의 
	타입 요소명(); // 애너테이션 요소를 선언
}

한 가지 유의할 점은 애너테이션은 이미 java.lang.annotation을 상속받고 있기 때문에

 

다른 클래스나 인터페이스를 상속받을 수 없다.

 


추가) 마커 애너테이션 - 요소가 하나도 정의되지 않은 애너테이션

 

@Test - 테스트 프로그램에게 테스트 대상임을 알리는 애너테이션

public void run() {...생략...}

@Test // 아래 메서드가 테스트 대상임을 테스트 프로그램에게 알리는 애너테이션
public void stop() {...생략...}
반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/06   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함