Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
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
Tags
more
Archives
Today
Total
관리 메뉴

forDevLife

[생활코딩-자바입문] 핵심 요약 5 본문

Java

[생활코딩-자바입문] 핵심 요약 5

JH_Lucid 2020. 11. 15. 16:26

생활코딩 41. 상수와 enum

 

1) 상수에 대한 복습

 

서로 다른 데이터 타입을 가지고 비교가 필요하다. 각 데이터를 숫자인 int로 정의하게 되면, 결국 비교 시 int의 특성을 가지는 숫자로 비교가 되기 때문에 여러 부분에서 문제가 생긴다. 

 

뭐 여러 가지 시행착오 이후에, 아래와 같이 Fruit와 Company를 class로 구분하여 정의해 두면, 과일에서의 APPLE과 회사 이름으로의 APPLE이 확실히 구분이 된다.

하지만 아래의 코드는 switch 내의 type에서 오류가 발생하는데, 이는 switch 내의 조건에는 제한된 데이터 타입만 사용이 가능하다.

따라서 enum이라는 type을 이용하여 이 문제를 개선한다.

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

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

public class ConstantDemo {
	
	public static void main(String[] args) {
		Fruit type = Fruit.APPLE;
		
		switch (type) { // switch 문의 조건에는 제한된 데이터 타입만 사용 가능
		case Fruit.APPLE:
			System.out.println(57);
			break;
		case Fruit.PEACH:
			System.out.println(34);
			break;
		case Fruit.BANANA:
			System.out.println(342);
			break;
		}
	}
}

 

2) enum 의 문법

 

enum은 서로 연관된 상수의 집합이라는 의도로 생겨났다. 따라서 enum 상속은 불가능하다. 

아래와 같이 enum으로 변경하여 정의하였다. 적은 코드만으로 긴 코드의 효과를 낼 수 있도록 문법적으로 지원하기 때문에 enum이란 키워드를 사용해 분명히 표현한 것이라고 한다. 

enum의 Fruit 역시 class이므로, 컴파일 - 실행 후에 bin에 Fruit.class가 생성됨을 알 수 있다.

또한, switch에 type으로 Fruit라는 데이터 타입이 전달되므로 알고 있기 때문에 case에 Fruit.APPLE로 쓰면 안된다. 그냥 APPLE로만 작성해야 에러가 발생하지 않는다. 

 

장점은, 코드가 매우 단순해진다. 그리고 인스턴스의 생성과 상속을 방지할 수 있다.

enum Fruit {
	APPLE, PEACH, BANANA;
}

enum Company {
	APPLE, PEACH, BANANA;
}


public class ConstantDemo {
	
	public static void main(String[] args) {
		Fruit type = Fruit.APPLE;

		switch (type) {
		case APPLE:
			System.out.println(57);
			break;
		case PEACH:
			System.out.println(34);
			break;
		case BANANA:
			System.out.println(342);
			break;
		}
	}
}

 

3) enum 의 활용

 

enum은 위에서 말한 것 처럼 class이다. 따라서 생성자 및 추가 메소드를 포함할 수 있는 온전한 class이다.

아래에서는, 생성자 Fruit를 가지며, 메소드인 getColor를 정의해봤다. color는 private로 두어, 외부에서 접근 불가능하고 getColor를 통해서만 볼 수 있도록 정의하였다.

 

+ APPLE("red"), PEACH("pink") .. 정의될 때 생성자가 실행된다. 따라서 3번 call constructor가 출력된다.

+ 생성자를 먼저 쓰고, APPLE등을 열거하면 오류가 발생한다. enum의 특징인 듯 하다.

enum Fruit {
//    APPLE, PEACH, BANANA;
	APPLE("red"), PEACH("pink"), BANANA("yellow");
	private String color;	
	
	Fruit(String color) {
		System.out.println("call constructor " +this);
		this.color = color;
	}
	public String getColor() {
		return this.color;
	}
}

enum Company {
	APPLE, PEACH, BANANA;
}


public class ConstantDemo {
	
	public static void main(String[] args) {
		Fruit type = Fruit.APPLE;

		switch (type) {
		case APPLE:
			System.out.println(57 + " kcal, " +Fruit.APPLE.getColor());
			break;
		case PEACH:
			System.out.println(200 + " kcal, " +Fruit.PEACH.getColor());
			break;
		case BANANA:
			System.out.println(32 + " kcal, " +Fruit.BANANA.getColor());
			break;
		}
	}
}

 

추가로, values라는 메소드를 통해 배열처럼 열거형 안에 있는 데이터를 하나씩 꺼내어 처리할 수 있다.

for문에 ":"가 있는 것은 foreach 구문이다. 뒤에는 어떤 데이터 집합이 오고, 이를 하나씩 꺼내서 f라는 변수에 할당한다.

values()에서 Fruit에 담긴 데이터를 하나씩 f로 전달해주고, 이들을 출력해준다.

Fruit.value 자체를 출력하면 그냥 패키지 name이랑 hex 값이 나온다.

enum Fruit {
//    APPLE, PEACH, BANANA;
	APPLE("red"), PEACH("pink"), BANANA("yellow");
	private String color;	
	
	Fruit(String color) {
		System.out.println("call constructor " +this);
		this.color = color;
	}
	public String getColor() {
		return this.color;
	}
}

enum Company {
	APPLE, PEACH, BANANA;
}


public class ConstantDemo {
	
	public static void main(String[] args) {
		for (Fruit f : Fruit.values()) {
			System.out.println(f+", "+f.getColor());
		}
	}
}

Comments