ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • enum
    컴퓨터/Java 2019. 10. 6. 16:33

    - enum(열거형) : enumerated type

    서로 연관된 상수들의 집합(class, interface와 동급의 형식을 가지는 단위, 사실상 class)

    클래스와 그 객체들(상수 하나당 자신의 인스턴스를 하나씩 만든다)

    다음 둘은 같다. 전자를 많이 사용하기 때문에 이를 지원하기 위해 자바 enum이 생겨났다.

    class Fruit{
    	public static final Fruit APPLE = new Fruit();
    	public static final Fruit PEACH = new Fruit();
    	public static final Fruit BANANA = new Fruit();
    }
    enum Fruit {
        APPLE, PEACH, BANANA
    }

     

     

    - enum 효과

    1) 상수가 필요할 때 상수 그룹 생성(상수 저장)

    2) 서로 다른 상수 그룹에 대한 비교를 컴파일 시점에서 차단할 수 있다.

    3) 상수 그룹 별로 클래스를 만든 것의 효과를 enum도 갖는다. (생성자, 필드, 메서드를 가질 수 있다)

    4) 열거형이 가지고 있는 상수들을 .values()로 배열에 담아 하나하나 꺼낼 수 있다.

     

    - enum 사용 이유

    1) 코드가 단순해진다

    2) 인스턴스 생성과 상속을 방지한다

    3) 키워드 enum을 사용하기 때문에 구현의 의도가 열거임을 분명하게 나타낼 수 있다.

     

    - enum이 없다면?

    변수를 지정하고 변수를 final로 처리하면 상수화된다.

    또한 바뀌지 않을 값이므로 인스턴스 변수가 아니라 클래스 변수(static)로 지정한다.

    public class ConstantDemo {
        private final static int APPLE = 1;
        private final static int PEACH = 2;
        private final static int BANANA = 3;
    	
    	public static void main(String[] args) {
    		int type = APPLE;
    		switch(type) {
    			case APPLE:
    				System.out.println(57+" kcal");
    				break;
    			case PEACH:
    				System.out.println(34+" kcal");
    				break;
    			case BANANA:
    				System.out.println(93+ " kcal");
    				break;
    		}
    	}
    }

     

    그러나 한 클래스에서 같은 이름의 상수가 필요할 때가 있다.

    기업이름도 추가해서 APPLE을 추가해야 한다면 컴파일 단계에서 오류가 생긴다. (컴파일 하는 시점에서 문제가 드러남)

    해결법1 : FRUIT_, COMPANY_와 같이 접두사를 붙여줄 수 있다.

    해결법2 : 인터페이스 사용

    인터페스에서 필드를 선언하는 것은 public final static임을 함의한다.

    그러나 문제는 FRUIT.APPLE과 COMPANY.APPLE을 비교하면 같은 것으로 나온다는 점.

    interface FRUIT{
    	int APPLE = 1, PEACH = 2, BANANA = 3;
    }
    interface COMPANY{
    	int GOOGLE = 1, APPLE = 2, ORACLE = 3;
    }
    
    public class ConstantDemo {
    	private final static int APPLE = 1;
    	private final static int PEACH = 2;
    	private final static int BANANA = 3;
    	
    	// 컴파일에서도 문제가 드러나지 않는다.
    	if (FRUIT.APPLE == COMPANY.APPLE) {
    		System.out.println("과일애플과 기업애플은 같습니다.")
    	}
    	public static void main(String[] args) {
    		int type = FRUIT.APPLE;
    		switch(type) {
    			case FRUIT.APPLE:
    				System.out.println(57+" kcal");
    				break;
    			case FRUIT.PEACH:
    				System.out.println(34+" kcal");
    				break;
    			case FRUIT.BANANA:
    				System.out.println(93+ " kcal");
    				break;
    		}
    	}
    }

     

    해결법 3. 클래스 만들기

    class Fruit{
    	public static final Fruit APPLE = new Fruit();
    	public static final Fruit PEACH = new Fruit();
    	public static final Fruit BANANA = new Fruit();
    }
    
    class Company{
    	public static final Company APPLE = new Company();
    	public static final Company PEACH = new Company();
    	public static final Company BANANA = new Company();
    }

    이 경우 컴파일에서 문제가 드러나지 않던 비교 문제가 컴파일 오류로 드러난다.

    if (Fruit.APPLE == Company.APPLE) {
        System.out.println("과일애플과 기업애플은 같습니다.");
    }

    데이터 타입이 Fruit, Company로 다르므로 컴파일시 오류가 생긴다.(서로 비교가 불가능하다) 

    그러나 switch문 사용시 데이터 타입에 제한이 있어 switch문을 사용할 수 없다. 

    따라서 enum을 사용한다. (enum 또한 서로 다른 상수 그룹에 대한 비교를 컴파일 시점에서 차단할 수 있다)

    (상수 그룹 별로 클래스를 만든 것의 효과를 갖는다.

     

    - enum 사용법

    enum Fruit{
    	APPLE, PEACH, BANANA;
    }
    
    enum Company{
    	GOOGLE, APPLE, ORACLE;
    }
    
    public class ConstantDemo {	
    	public static void main(String[] args) {
    		
    		Fruit type = Fruit.APPLE;
    		// switch문은 type이 Fruit이라는 것을 알고 있으므로 case에 Fruit을 적지 않아도 된다.
    		switch(type) {
    			case APPLE:
    				System.out.println(57+" kcal");
    				break;
    			case PEACH:
    				System.out.println(34+" kcal");
    				break;
    			case BANANA:
    				System.out.println(93+ " kcal");
    				break;
    		}
    	}
    }

    enum은 사실상 클래스이기 때문에 생성자를 가질 수 있다.

    (생성자를 밖에서 접근할 수는 없다)

    싱글턴을 일반화한 형태

     

    enum Fruit{
    	// 인자를 전달할 수 있다
    	APPLE("red"), PEACH("pink"), BANANA("yellow");
    	// enum안에 필드와 메서드가 모두 들어갈 수 있다.
    	private String color;
    	public String getColor() {
    		return this.color;
    	}
    	// 상수를 열거하면 new Fruit(), 즉 Fruit가 인스턴스화 되면서 이를 만들기 위한 생성자가 호출된다.
    	Fruit(String color){
    		// this는 인스턴스
    		System.out.println("Call Constructor " + this);
    		this.color = color;// 전역변수 = 매개변수(지역변수-- 전역변수보다 우선순위가 높아서 그냥 color만 쓰면 가리킬 수 있다)
    	}
    }
    
    enum Company{
    	GOOGLE, APPLE, ORACLE;
    }
    
    public class ConstantDemo {	
    	public static void main(String[] args) {
    		
    		Fruit type = Fruit.APPLE;
    		// switch문은 type이 Fruit이라는 것을 알고 있으므로 case에 Fruit을 적지 않아도 된다.
    		switch(type) {
    			case APPLE:
    				System.out.println(57+" kcal, color " + Fruit.APPLE.getColor());
    				break;
    			case PEACH:
    				System.out.println(34+" kcal, color " + Fruit.PEACH.getColor());
    				break;
    			case BANANA:
    				System.out.println(93+ " kcal, color " + Fruit.BANANA.getColor());
    				break;
    		}
    	}
    }
    for (Fruit f : Fruit.values()) {
        System.out.println(f);
    }
    public enum Operation {
        PLUS, MINUS, TIMES, DIVIDE;
        
        // 상수가 못하는 연산 수행
        public duble apply(double x, double y){
            switch(this) {
            	case PLUS: return x+y;
                case MINUS: return x-y;
                case TIMES: return x*y;
                case DIVIDE: return x/y;
            }
            
            throw new AssertionError("알 수 없는 연산 + " + this);
        }
    }

     

    - 출처 : 생활코딩

     

     

    '컴퓨터 > Java' 카테고리의 다른 글

    Optional  (0) 2019.10.06
    switch문  (0) 2019.10.06
    함수  (0) 2019.09.07
    객체지향 원칙 2: 상속보다는 구성을 활용한다.  (0) 2019.09.07
    조건문, 반복문  (0) 2019.09.05

    댓글

Designed by Tistory.