(JAVA) enum
우리가 int형인 i 란 변수를 선언할때
int i;
이렇게 작성하였다. 이후 i 값에 어떤 값을 넣으면 i 값은 항상 변하였다. 그래서 우리는 이걸 변수라고 불렀다.
상수는 무엇일까?
상수란 변하지 않는 값을 말한다.
final int PI = 3.1415;
final을 사용하면 쉽게 상수를 만들수 있었다.
그런데 만약 상수의 이름이 겹치면 어떨까?
final int mouse =1;
final int keyboard =2;
final int monitor =3;
final int mouse =1;
final int cat=2;
final int dog=3;
나중에 코드가 몇 만줄 일때 구분하기 편하게 1번 항목 2번 항목 처럼 숫자를 1,2,3 을 주었다.
그런데 첫번째 상수들은 컴퓨터 주변기기를 쓰고 싶었고 두번째 상수들은 동물들을 쓰고 싶었다.
그런데 당연히 mouse라는 이름이 겹치니 오류가 날것이다.
그럼 인터페이스를 써보면 어떨까?
public class Main {
interface computer{
int mouse =1, keyboard =2, monitor =3;
}
interface animal{
int mouse =1, cat=2, dog=3;
}
public static void main(String[] args) {
if (computer.mouse == animal.mouse){
System.out.println("쥐는 다 같은 쥐야");
}
}
}
인터페이스로 나눠줬으니 의도한 것처럼 만들수 있겠지만 mouse값이 둘다 int 타입의 상수 1로 같아 버려서 자바는 이들이 같은 놈들이라고 인식을 해버린다.(이유는 자바는 타입과 값을 둘다 비교해서 판단을 한다.)
당장은 당연히 이게 눈에 보이고 오류가 예상이 가지만 프로그램이 엄청 커지면 이후에 치명적인 결과를 발생시킬것이다. (혹시 왜 final을 안붙였냐고 헷갈리실까봐 설명하면 인터페이스의 고유 특성은 무조건 상수 형태가 기본이자 강제이다.)
클래스는 다를까?
public class Main {
class computer{
public static final int mouse =1, keyboard =2, monitor =3;
}
class animal{
public static final int mouse =1, cat=2,dog=3;
}
public static void main(String[] args) {
if (computer.mouse == animal.mouse){
System.out.println("쥐는 다 같은 쥐야");
}
}
}
생각할 필요도 없이 당연히 같은 결과가 나온다. (다시 강조하면 타입과 값이 핵심이다.)
그럼 어떻할까? 그냥 각각 하나씩 독립된 객체로 만들어 버릴까? 그러면 타입을 computer, animal로 만들까?
int에서 computer, animal로 타입을 바꿔 버리니 드디어 오류로 인식한다. 그런데 여기에는 단점이 있다.
스위치문을 사용하지 못한다.(응 if문 쓰고 swich 안쓰면 그만이야 라고 하면 안된다 ㅠ)
스위치는 byte, short, char, int, enum, String, Character, Byte, Short, Integer 타입만 사용이 가능한데 위의 예제는 우리가 만든 타입을 정의 했기 때문이다.
이 모든 고민을 해결할수 있는게 무엇이 있을까? 그게 바로 enum(열거형이랑 같은말) 이다.
배열이 값의 모임이면 enum은 상수들의 모임이다. 사용법은 다음과 같다.
public class Main {
enum computer{
mouse,keyboard,monitor
}
enum animal{
mouse,cat,dog
}
public static void main(String[] args) {
computer name = computer.mouse;
switch (name){
case mouse:
System.out.println("마우스");
break;
case keyboard:
System.out.println("키보드");
break;
case monitor:
System.out.println("모니터");
break;
}
}
}
enum을 사용하니 딱봐도 코드가 매우 간결해 졌고 swich도 사용이 가능해 졌다.
그리고 앞서 우리는 mouse에다 1을주고 keyboard에다2 , monitor에다 3을 줬었다.
그런데 enum이 상수들의 집합이라 하지 않았는가? 배열처럼 mouse에다 0 keyboard 에1 , monitor 에 2 라는 값이 부여가 된다.
public class Main {
enum computer{
mouse,keyboard,monitor
}
public static void main(String[] args) {
computer[] arr = computer.values();
for(computer i : arr){
System.out.printf("제품명 %s = 순번%d %n",i.name(),i.ordinal());
}
computer c1 = computer.valueOf("mouse");
computer c2 = computer.valueOf("keyboard");
computer c3 = computer.valueOf("monitor");
System.out.println("valueOf 를 사용한 결과는 "+c1);
System.out.println("compareTo 를 사용하면 "+(c2.compareTo(c3)));
}
}
출력결과는 다음과 같다.
제품명 mouse = 순번0
제품명 keyboard = 순번1
제품명 monitor = 순번2
valueOf 를 사용한 결과는 mouse
compareTo 를 사용하면 -1
생소할 것이다. 다른건 몰라도 name()은 무엇이며 ordinal() , values(), valueof, compareTo는 무엇인지 말이다.
열거형에서 사용이 가능한 메서드 들이 있는데 그건 위의 예제와 같다. 어렵게 생각할것 없다 간단하다.
name()은 열거형의 이름을 가져온다.
ordinal()은 열거형의 순번(값)을 가져온다.
values()는 열거형을 배열에 넣어준다.
valueof 는 열거형의 객체를 가져오고 String 타입 으로 리턴한다.(굳이 이렇게 안써도 사용 가능함 이런 메서드가 있다는걸 보여주기위해 써봤음)
compareTo는 순번 값을 비교해서 차이를 리턴(표시)한다. (c2가 keyboard라서 숫자 1이 들어가고 c3가 monitor라서 숫자 2가 들어간다. 1-2는 -1이라서 -1을 출력한다.)
간단하다.
그런데 추가로 enum은 클래스 취급을 받아서 생성자를 만드는 행위가 가능하다. 그럼 무슨 일을 할수 있냐면..
enum Computer{
mouse("13000원",6),keyboard("55000원",5),monitor("360000원",3);
public String price;
public int remain;
Computer(String price, int remain){
this.price = price; this.remain = remain;
}
}
public class Main {
public static void main(String[] args) {
Computer name = Computer.mouse;
switch (name){
case mouse:
System.out.printf("마우스 가격 %s, 잔여개수 %d 개" , Computer.mouse.price,Computer.mouse.remain);
break;
case keyboard:
System.out.printf("키보드 가격 %s, 잔여개수 %d 개" , Computer.keyboard.price,Computer.keyboard.remain);
break;
case monitor:
System.out.printf("모니터 가격 %s, 잔여개수 %d 개" , Computer.monitor.price,Computer.monitor.remain);
break;
}
}
}
결과 : 마우스 가격 13000원, 잔여개수 6 개
생성자를 만들어서 값을 추가 할수 있게 된 것이다.
추가로 get을 사용하면 이렇게 된다.
enum Computer{
mouse("13000원",6),keyboard("55000원",5),monitor("360000원",3);
private String price;
public String getPrice() {
return this.price;
}
private int remain;
public int getRemain(){
return this.remain;
}
Computer(String price, int remain){
this.price = price; this.remain = remain;
}
}
public class Main {
public static void main(String[] args) {
Computer name = Computer.mouse;
switch (name){
case mouse:
System.out.printf("마우스 가격 %s, 잔여개수 %d 개" , Computer.mouse.getPrice(),Computer.mouse.getRemain());
break;
case keyboard:
System.out.printf("키보드 가격 %s, 잔여개수 %d 개" , Computer.keyboard.getPrice(),Computer.keyboard.getRemain());
break;
case monitor:
System.out.printf("모니터 가격 %s, 잔여개수 %d 개" , Computer.monitor.getPrice(),Computer.monitor.getRemain());
break;
}
}
}
이렇게 상수들을 관리하기 쉽게 만드는 enum에 대해 알아보았다.
enum은 코드를 간결하게 만들고, 타입을 맞춰주고, 이름 중복도 피해주는 훌륭한 녀석이다.