반응형

자바에서 열거형이 무엇인지 알려드릴게요.


먼저 열거란 무엇인지 사전을 볼까요???



열거 : 여러 가지 예나 사실을 낱낱이 죽 늘어놓음.



죽~ 늘어놓음.


열거형마찬가지예요.




관련된 상수들을 죽 늘어놓은 거예요.


여기서 중요한 것은 모두 상수!!라는 점~





어쩔 때 쓰이냐면


달력을 만든다고 할 때


월요일 화요일 수요일 목요일 ...


이렇게 쓰는 것보다




월요일 = 1

화요일 = 2

수요일 = 3

...



 

이런 식으로 코드화해 놓는 게 효과적일 거예요.




이런 상수들을 모아놓아서 활용하기 쉽게 해주는 것이 열거형이에요.


열거형이라고 하니 자료형과 비슷한 것 같죠?


맞아요!!


자료형처럼 열거형 안에 있는 상수들은 열거형으로 선언돼요!


int a;와 같이


열거형명 데이터;표현돼요.


먼저 열거형을 살펴보기 전에


열거형이 없을 때 어떻게 상수들을 선언했을지 살펴볼게요.



우선 변수로 상수를 선언!!



private final static int MONDAY = 1;

private final static int TUESDAY = 2;

private final static int WEDNESDAY = 3;

private final static int THURSDAY = 4;

private final static int FRIDAY = 5;

private final static int SATURDAY = 6;

private final static int SUNDAY = 7;


이런 식으로 사용하기도 해요.


이때의 문제점은 한번 선언된 변수명을 중복 사용할 수 없다는 것과


상수를 추가해야 할 경우 내용이 많아지며 메모리 공간을 많이 차지한다는 점이에요.



그래서


public final static이 생략되어있는


인터페이스를 이용하거나 class를 이용해요.



interface Day{

    int MONDAY = 1;

    int TUESDAY = 2;

    int WEDNESDAY = 3;

    int THURSDAY = 4;

    int FRIDAY = 5;

    int SATURDAY = 6;

    int SUNDAY = 7;

}


여기서 interface를 이용할 경우에 문제가 있어요.


A1과 A2라는 인터페이스를 만들었을 때


두 인터페이스는 서로 다른 타입이기 때문에 비교가 불가능해야 해요.


그런데 if(A1 == A2) 를 했을 경우 경고 메시지를 볼 수 없다는 것이 문제에요.



그래서


Class를 정의해 사용합니다.



class Day{

   public final static Day MONDAY = new Day();

   public final static Day TUESDAY = new Day();

   public final static Day WEDNESDAY = new Day();

   public final static Day THURSDAY = new Day();

   public final static Day FRIDAY = new Day();

   public final static Day SATURDAY = new Day();

   public final static Day SUNDAY = new Day();

}


마찬가지로 class를 이용할 때도 문제가 있는데


switch 문에서 사용이 불가능하다는 것이에요.


switch(조건)


여기서 조건에 들어가는 데이터 타입이 제한적이라


class를 정의해서 사용할 경우 에러가 발생해요.




이런 문제점을 해결해 주는 것이 enum이에요.



enum Day{

           MONDAY,TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

}


public class EnumStudy {


           public static void main(String[] args) {

                     // TODO Auto-generated method stub

                     System.out.println("월요일 : " + Day.MONDAY);

                     System.out.println("화요일 : " + Day.TUESDAY);

                     System.out.println("수요일 : " + Day.WEDNESDAY);

                     System.out.println("목요일 : " + Day.THURSDAY);

                     System.out.println("금요일 : " + Day.FRIDAY);

                     System.out.println("토요일 : " + Day.SATURDAY);

                     System.out.println("일요일 : " + Day.SUNDAY);

           }

}




또한 숫자를 사용하고 싶다면 아래처럼 해주면 됩니다.




enum Code{

           ONE(1), TWO(2), THREE(3);

          

           Code(int num){//생성자

                     CodeNum = num;

           }


           int CodeNum;

           public int getCodeNum(){

                     return CodeNum;

           }

}


public class EnumStudy {


           public static void main(String[] args) {

                     // TODO Auto-generated method stub

                     System.out.println(Code.ONE + " : " + Code.valueOf("ONE").getCodeNum());

                     System.out.println(Code.TWO + " : " + Code.valueOf("TWO").getCodeNum());

                     System.out.println(Code.THREE + " : " + Code.valueOf("THREE").getCodeNum());

           }

}





enum을 이용할 때 생성자는 자동으로 private선언돼요.


그래서 타입의 안정성이 보장돼요.


외부에서 접근이 불가능하며 new 키워드로 생성할 수도 없어요.


물론 clone(복사)도 하지 못한답니다~ 

[출처] 자바 :: 열거형 (enum)|작성자 프로

 

 

1.열거형이란?

열거형은 C와 C++에서도 썼던타입으로 특정의 정수와 그 정수를 의미하는 단어로 되어 자료형이였죠.

저의 C언어 12강에서 1번째로 소개했던게 열거형인데요 C와 C++의형태는 뭐 다음과 같습니다.


 

enum은 각각 순서대로 0부터 시작해서 배정되며 원한다면 자기가 다른 숫자를 배정할 수 있습니다.

그리고 enum형에서 정의된 토큰들은 전부 상수이며 값의 수정은 불가능합니다.


원래는 자바에서도 없던 기능이였으나 JDK1.5부터 열거형이 사용이 가능합니다.

사용방식은 C와 유사하게 사용할 수 있으나 자바의 열거형은 이미 하나로 훌륭한 객체입니다.

따라서 C와는 차원이 다르게 높은 레벨로 프로그래밍을 할 수 있습니다.


사용방식은 기존의 Class를 사용하는것 처럼 쓸수도 있고 따로 Enum전용으로 만들 수 있습니다.

뭐 차이라면 public class를 쓰냐 package class를 쓰냐의 차이 처럼 public enum을 쓰고싶으면

전용으로 만들어서 쓰고 package enum을 써도 상관없다면 그냥 아무 class,intefrface,enum등에 같이써도 됩니다.


2.열거형의 사용

java에서 열거형은 기본적인 스탠다드한 형식은 다음과 같습니다.

 

public enum이므로 소스파일을 따로 만들어줘야합니다.

위의 구문의 의미는 Trump라는 열거형은 그 값으로 SPADE,HEART,CLUB,DIAMOND밖에 가지지 못함을 의미합니다.

즉 제일 윗줄에 쓰는 토큰의 나열은 그 열거형이 가질수 있는 값의 전부라고 보시면됩니다.


이번에는 main메소드를 보도록하죠.

 

같은 패키지내에있는 TestMain클래스의 main함수에서 Trump형으로 t를 선언하고 그 값으로 Trump.CLUB을 넣은 모습입니다.

Trump enum은 이미 그 하나로도 interface나 class, abstract class의 객체이지만 생성자를 호출하진 않습니다.

정확히 말하면 생성자를 호출하지 않는건 아니지만 저희가 호출할 일은 없습니다.

enum은 이미 제가 정의해 놓은 값만 소유하는게 가능하며 다른 값을 소유하는건 불가능합니다.

따라서 Tump t형은 CLUB과 SPADE,HEART,DIAMOND만 가지는게 가능합니다.


enum 상수의 호출은 enum_name.enum_const 와 같은 형태로만 접근할 수 있습니다.

위 처럼 Trump.CLUB;같은 형태만 쓸 수 있다는 것이죠.


그리고 위의 예를 봐서 알겠지만 enum형을 그 이름으로 출력할경우에는 문자열로 출력이 됩니다.

따라서 System.out.println(Trump.CLUB);의 구문은 Trump.CLUB은 문자열로 취급되서 출력하게 되는 것이죠.


이미 이 정도만해도 enum의 존재가치는 충분하지만 enum은 여기서 더더욱 나아가서

훨씬 클래스에 근접하게 사용할 수 있습니다. 이는 C와 C++은 누리지 못했던 특권이죠.


 

이 코드는 일반적인 클래스구조와 굉장히 유사합니다. 이 코드하나로 enum의 성질을 대부분알 수 있습니다.

각각의 상수 토큰에는 그 의미를 부여할 수 있습니다.

위의 예시는 SPADE에는 3을 HEART에는 7을 같은 방식으로 나머지에도 값을 부여했습니다.


이렇게 사용하려면

Token(value)

와 같은 형태로 사용해야 합니다.


만약 이런식으로 사용한다면 이제는 명시적으로 생성자를 지정해저야합니다.

위의 SPADE(3)이라는 구문은 생성자의 매개변수가 1개짜리은 생성자를 호출해야만 하겠다 라는 뜻입니다.

따라서 이제는 생성자를 명시적으로 선언해줄 필요가 생깁니다.

단 이 생성자는 저희가 직접쓰는건 아니라 자바가 알아서 적절한 타이밍에서 사용하게 됩니다.

애당초 사용하고싶어도 사용하는것도 불가능 합니다. 이게 불가능한 이유는


보시면 아시겠지만 생성자는 private가 디폴트로 설정되며 이 디폴트를 바꾸는건 불가능합니다.

즉 enum의 생성자는 모두 private입니다.


 

생성자의 호출타이밍은 우리가 정확하게 예측하기는 힘들지만 확실한건

저희가 호출하는건 불가능하고 이미 Trump가 필요한 순간에 생성자가 자동으로 호출하게됩니다.


 

생성자의 호출타이밍을 알기위해서 한줄의 코드를 추가했습니다.

main메소드는 위의 클럽을 출력하는 메소드를 그대로 토시하나 바꾸지 않고 사용했습니다.

저희가 사용한건 클럽 하나였지만 이미 생성자는 4번 호출이되고 더이상 호출되지 않습니다.


저 생성자가 값으로 정수를 받았지만 사실 정수를 받았다고 끝이 난게 아닙니다.

이 정수를 식별자중 하나로 쓰고싶다면 그 정수를 각각의 enum이 가지고 있어야합니다.

그러기 위해서 존재하는게 int val입니다.

각각의 생성자는 정수를 받으며 그 정수를 멤버로 사용할 수 있습니다.

또한 set과 get을 사용해서 실행시간동안 바꾸거나 값을 확인하는것 역시 가능합니다.


여기서 궁금한점이 만약 실행시간에서 값을 변경하게 되면 어떻게 될까요?

그 궁금증을 풀기위해서 아래의 예제를 한번 실행해보도록합시다.

보시면 처음에는 CLUB이 15였지만  한번 2로 수정하면 어디에서 접근을 하던 새로만들던 간에

무조건 값이 2로 고정이 됩니다.



 


enum은 더 나아가서 각각의 토큰마다 파라메터 갯수를 다르게 줄 수도 있습니다.

그 경우 생성자를 그 파라메터 수에 맞게 늘려주면 장땡입니다.

전부다 두개씩을 줄 수도 있지만 한개만 두개를 줄 수도 있고 한개만 3개를 줄 수도 있는 것이죠.


 

또한 enum은 class와 interface등과는 다르게 ==연산자를 사용해서 비교할 수 있습니다.

equals만 써야하는 다른 객체형들과달리 enum객체는 ==연산을 사용할 수 있는 것이죠.


3.java.lang.Enum

이 패키지는 모든 enum의 조상입니다.

모든 class의 조상이 java.lang.Object이듯이 모든 enum의 조상은 java.lang.Enum이죠.

또 신기하게도 Enum은 abastract class로 구현되어 있으므로 Enum클래스는 Object의 후손이기도 합니다.

모든 enum의 조상은 Object이며 또한 Enum이므로 Obeject클래스가 지원하는 메소드들을 모조리 사용가능하며

또한 Enum이 지원해주는 메소드 역시 사용기 가능합니다. 그 목록은 아래와 같습니다.


3-1.getDeclaringClass

 

이 메소드는 열거형의 클래스 자체를 반환하는 메소드입니다.

Class 클래스로 반환하는데 아직 Class 클래스는 하지 않았으므로 이런 기능이 있다만 알아 두시면 됩니다.


3-2.name()

 

이 메소드는 상수의 토큰 그 자체를 반환합니다. 즉 Trump.CLUB이 있다면 CLUB을 반환하는거죠.

보통 name 메소드를 안쓰고 토큰만써도 name이 반환되기에 잘 사용되진 않습니다/


3-3.ordinal()

 

이 메소드는 사용하면 지금 사용중인 토큰이 몇번째 토큰인지를 알아낼 수 있습니다.


3-4.valueOf(String name)

 

이 메소드는 열거형을 쓰게된다면 굉장히 많이 쓰는 메소드인데 토큰의 이름으로 해당 상수를 추적할 수 있습니다.


 

보시다시피 Trump형 enum에서 CLUB에 해당하는 값의 숫자를 알고싶을경우 다음과 같은 방법을 사용할 수 있습니다.


4.열거형 추상 메소드

열거형에도 추상메소드를 적용할 수 있습니다. 또한 열거형에도 익명 enum을 사용할 수 있습니다.

이 방식은 조금만 생각해보면 어떻게 할지 쉽게 감을 잡을 수 있습니다.


 

보시면 마지막으로 PrintTrump를 추상메소드로 선언한것을 알 수 있습니다.

추상메소드로 선언즉시 모든 열거형 토큰들에 빨간줄이 끄입니다.

왜냐하면 추상메소드를 구현해줘야하기 때문이죠.

따라서 이들은 모두 익명클래스를 써서 구현해줘야합니다.


 

이런식으로 모두 구현해주면 되겠습니다.


5.마치며

이번엔 열거형을 했는데요, 자바에서 열거형있으면 좋겠다고 빼애액거려서

JDK1.5버전에서 기껏해서 만들어줬는데 이미 사람들은 class로만드는게 익숙한지

사실 코드 보다보면 잘 보이진 않습니다.

그러나 enum도 써보면 많은 도움이 될것 같애요.

반응형

'Study > Java' 카테고리의 다른 글

열거형 enums  (0) 2018.03.19
Collection Framwork 1.3 LinkedList  (0) 2018.03.05
Collection Framework 1.2 ArrayList  (0) 2018.03.05
java.time 패키지를 이용하여 달력 만들기  (0) 2018.03.05
Collection Framework 1.7 Comparator, Comparable  (0) 2018.02.26
반응형

1.6 Arrays

 

* Arrays 클래스 : 배열을 다루는데 유용한 메서드가 정의되어 있음. 아래 정의된 toString(), 모든 기본형 배열, 참조형 배열 별로 하나씩 정의됨.

 

static String toString(boolean[ ]a)

static String toString(byte[ ] a)

static String toString(char[ ] a)

static String toString(short[ ] a)

static String toString(int[ ] a)

static String toString(long[ ] a)

static String toString(float[ ] a)

static String toString(double[ ] a)

static String toString(object[ ] a)

 

------------------------------------------------------------------------------------------------------------------------------------------------------------

 

* 배열의 복사

- copyOf() : 배열 전체 복사

- copyOfRange() : 배열의 일부를 복사

하여 새로운 배열을 만들어 반환.

 

int[ ] arr = {0,1,2,3,4,};

int[ ] arr2 = Arrays.copyOf(arr, arr.length);

int[ ] arr3 = Arrays.copyOf(arr, 3);

int[ ] arr4 = Arrays.copyOf(arr, 7);

 

int[ ] arr5 = Arrays.copyOfRange(arr,2,4);

int[ ] arr6 = Arrays.copyOfRange(arr,0,7);

 

 

// 배열의 복사

package Collection_Framework;
import java.util.*;
public class Arrays1 {
 public static void main(String[]arge) {

  int[ ] arr = {0,1,2,3,4,};
  int[ ] arr2 = Arrays.copyOf(arr, arr.length);
  int[ ] arr3 = Arrays.copyOf(arr, 3);
  int[ ] arr4 = Arrays.copyOf(arr, 7);

  int[ ] arr5 = Arrays.copyOfRange(arr,2,4);
  int[ ] arr6 = Arrays.copyOfRange(arr,0,7);

  System.out.println(Arrays.toString(arr));
  System.out.println(Arrays.toString(arr2));
  System.out.println(Arrays.toString(arr3));
  System.out.println(Arrays.toString(arr4));
  System.out.println(Arrays.toString(arr5));
  System.out.println(Arrays.toString(arr6));
 }
}

 

출력결과 :

[0, 1, 2, 3, 4]
[0, 1, 2, 3, 4]
[0, 1, 2]
[0, 1, 2, 3, 4, 0, 0]
[2, 3]
[0, 1, 2, 3, 4, 0, 0]


 

* 배열 채우기

- fil() : 배열의 모든 요소를 지정된 값으로 채운다.

- setAll() : 배열을 채우는데 사용할 함수형 인터페이스를 매겨변수로 받는다.

 

package Collection_Framework;
import java.util.*;
public class Arrays2 {

 public static void main(String[] args) {

  int[]arr = new int[5];
  Arrays.fill(arr, 9);
  Arrays.setAll(arr, () -> (int)(Math.random()*5)+1); // 람다식을 지정해야 함.

 System.out.println(Arrays.toString(arr));
 }

}

 

출력 결과 :

[9, 9, 9, 9, 9]

* 배열의 정렬과 검색

- sort() : 배열을 정렬할 때 사용

- binarySearch() : 저장된 요소를 검색 할 때 사용, 배열에서 지정된 값이 저장된 위치(index)를 찾아서 반환하는데, 반드시 배열이 정렬된 상태이어야 올바른 결과를 얻음.

 

package Collection_Framework;
import java.util.*;
public class Arrays3 {

 public static void main(String[] args) {
  int[] arr = {3,2,0,1,4};
  int idx = Arrays.binarySearch(arr, 2);
  System.out.println(Arrays.toString(arr));
 
  Arrays.sort(arr);
  System.out.println(Arrays.toString(arr));
  int idx2 = Arrays.binarySearch(arr,2);
 
  
 }

}

 

출력 결과 :

[3, 2, 0, 1, 4]
[0, 1, 2, 3, 4] 
<- 올바른 결과.
 

 

 

* 문자열의 비교와 출력

- equals() : 두 배열에 저장된 모든 요소를 비교해서 같으면 true, 다르면 false를 반환. 일차원 배열에서만 사용가능

- toString() : 일차원 배열에서 문자열로 편하게 출력함.

 

다차원 배열에서

- deepToString(), deepToEquals() 사용

 

package Collection_Framework;
import java.util.*;
public class Arrays4 {

 public static void main(String[] args) {
  int[] arr = {0,1,2,3,4};
  int[] [] arr2D = {{11,12},{21,22}};
  
  System.out.println(Arrays.toString(arr));
  System.out.println(Arrays.deepToString(arr2D));
  
  String[] [] str2D = new String [] [] {{"aaa","bbb"},{"AAA","BBB"}};
  String[] [] str2D2 = new String [] [] {{"aaa","bbb"},{"AAA","BBB"}};
  System.out.println(Arrays.equals(str2D, str2D2));
  System.out.println(Arrays.deepEquals(str2D, str2D2));
 }

}

출력결과 :

[0, 1, 2, 3, 4]
[[11, 12], [21, 22]]
false
true

* 배열을 List로 변환 // 이해가 잘 안감...

- asList(Object... a)

 

package Collection_Framework;
import java.util.*;
public class Arrays5 {

 public static void main(String[] args) {
  List list = Arrays.asList(new Integer[] {1,2,3,4,5,});
  List<Integer> list = Arrays.asList(1,2,3,4,5);
  list.add(6);
  
 }

}

 

 

* parallel로 시작하는 메서드(), spliterator(), tream()등등

 

 

 

반응형

+ Recent posts