ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Enum, Java Stream API
    업무 2025. 1. 21. 15:18

    간단히 공부해 본 적 있는 Enum을 실무에서 사용하려고 하니 많이 헷갈렸다

    단순히 Enum을 사용하게 된다면 타입 안정성 향상, 데이터 일관성의 장점이 있다는 것과

    간단한 예제만 만들어 봤으니 당연할 수밖에?

     

     

    @Slf4j
    @Service
    public class TestService{
        ```
        public enum SttlCd {
           INCOME00, // 100
           INCOME01, // 101
           INCOME02, // 102
    	}
        ```
        public List<TestInfoVo> getTestBrdn() {
            ```
            if (SttlCd.INCOME00.equals(TestDto.getTestCd())) {
                ```
            }
            ```
        }
        ```
    }

    외부 Dto에서 코드 값을 가져와서 enum 값과 비교를 통해 로직이 진행되는 대략적인 실무 코드이다

    시간이 없기 때문에 대략적인 가이드라인으로 잡아서 개발을 했는데 하면서 

    1. enum 값과 상수값을 매칭 안 해줬는데 어떻게 처리할 것인가

    2. equals 비교로 했을 때 "Unlikely argument type for equals() : String seems to be unrelated to TestService.SttlCd" 경고 문구 처리하기

    3. enum 관련된 메서드 사용법

    이 정도를 공부할 겸 해당 서비스 코드를 리팩토링해봤다

     

     

    1. enum 상수값 넣기

    public enum SttlCd {
        INCOME00("100"),
        INCOME12("112"),
        INCOME13("113"),
        INCOME14("114"),
        ;
        
        private final String code;
        
        private SttlCd(String code) {
          this.code = code;
        }
    }
    • Dto에서 값을 가져올 때는 "100"과 같은 값이 넘어오기 때문에 생성자를 통해 (INCOME00 - 100) 값을 연결한다
    • 외부에서 임의로 인스턴스를 생성할 수 없게 private으로 막는다

     

    이 정도로 한 뒤 Enum 관련된 주요 메서드를 찾아봤다

    • values() : 모든 ENUM 상수를 포함하는 배열을 반환한다
    • valueOf(String name) : 주어진 이름과 일치하는 ENUM 상수를 반환한다
    • name() : ENUM 상수의 이름을 문자열로 반환한다
    • ordinal() : ENUM 상수의 선언 순서(0부터 시작)를 반환한다

     

    public static void main(String[] args) {
    
        // SttlCd test = new SttlCd();
        // Cannot instantiate the type EnumTest.SttlCd
        
        SttlCd[] values = SttlCd.values();
        System.out.println("values : " + values);
        System.out.println("Arrays.toString(values) : " + Arrays.toString(values));
        // values : [LEnumTest$SttlCd;@372f7a8d
        // Arrays.toString(values) : [INCOME00, INCOME12, INCOME13, INCOME14]
        // Arrays.toString() > 배열의 참조값이 아니라 배열 내부의 값을 출력할 때 사용한다
    
        for (SttlCd cd : values) {
          System.out.println("name : " + cd.name() + ", ordinal : " + cd.ordinal());
          /*
           * name : INCOME00, ordinal : 0
           * name : INCOME12, ordinal : 1
           * name : INCOME13, ordinal : 2
           * name : INCOME14, ordinal : 3
           * name() : ENUM 상수의 이름을 문자열로 반환한다
           * ordinal() : ENUM 상수의 선언 순서(0부터 시작)를 반환한다
          */
        }
    
        // String > Enum type
        String code = "INCOME00";
        SttlCd income00 = SttlCd.valueOf(code);
        System.out.println("income00 : " + income00);
        // income00 : INCOME00
        // valueOf(String name) : 주어진 이름과 일치하는 ENUM 상수를 반환한다
    
    
        System.out.println("SttlCd.INCOME00 : " + SttlCd.INCOME00);
        System.out.println("SttlCd.INCOME00.name() : " + SttlCd.INCOME00.name());
        System.out.println("SttlCd.valueOf(INCOME00) : " + SttlCd.valueOf("INCOME00"));
        // SttlCd.INCOME00 : INCOME00
        // SttlCd.INCOME00.name() : INCOME00
        // SttlCd.valueOf(INCOME00) : INCOME00
    }

     

     

    2. .equal()해결 - 1

    public enum SttlCd {
        INCOME00("100"),
        INCOME12("112"),
        INCOME13("113"),
        INCOME14("114"),
        ;
        
        private final String code;
        
        private SttlCd(String code) {
          this.code = code;
        }
      
        public String getCode() {
          return code;
        }  
    }
    public class EnumTestDto {
        private final String enumTestCd;
    
        EnumTestDto(String enumTestCd) {
          this.enumTestCd = enumTestCd;
        }
    
        public String getEnumTestCd() {
          return enumTestCd;
        }
    }
    public static void main(String[] args) {
        if (SttlCd.INCOME12.getCode().equals(EnumTestDto.getEnumTestCd())) {
            ```			
        }
    }

    getCode() 메서드를 생성하고 main에서 사용했다

    이 경우 " Cannot make a static reference to the non-static method" 에러 메세지가 떴다

    main은 static method로 메서드 영역에서 생성되며 임의로 만든 DTO는 non-static method로 스택 영역에서 생성되기 때문에 static method는 먼저 컴파일되어 non-static method를 참조하지 못해 발생하는 문제였다

     

     

    public static void main(String[] args) {
        String testCode = "112";
        EnumTestDto tmpDto = new EnumTestDto(testCode);
        
        if (SttlCd.INCOME12.getCode().equals(tmpDto.getEnumTestCd())) {
            System.out.println(true);
        } else {
            System.out.println(false);
        } // true    
    }

    main에서 dto를 임의로 만들고 if문을 통해 확인했다

     

     

    if (SttlCd.INCOME12.getCode().equals(EnumTestDto.getEnumTestCd())) {
        ````
    }

    어차피 실무에서는 main이 아닌 service에서 실행되기 때문에 이런 식으로 사용해도 문제가 되지 않았다

    getCode()의 반환값은 String이었고 dto에서 받아오는 값도 String이었기 때문에 equals() 비교를 사용했다

    이렇게 수정하고 나니 " Unlikely argument type for equals() : String seems to be unrelated to TestService.SttlCd"  경고 문구가 사라졌다

     

     

    3. .equal()해결 - 2

    public enum SttlCd {
        INCOME00("100"),
        INCOME12("112"),
        INCOME13("113"),
        INCOME14("114"),
        ;
        
        private final String code;
        
        public String getCode() {
            return code;
        }
        
        private SttlCd(String code) {
            this.code = code;
        } 
        
        public static boolean chkCode(String code, SttlCd sttlCd) {
            if (SttlCd.valueOf(getSttlCd(code))==sttlCd) {
                return true;
            }
            returm false;
        }
        
        public String getSttlCd(String tmpCode) {
            for (SttlCd cd : SttlCd.values()) {
                if (cd.getCode().equals(tmpCode)) {
                    return cd.name();
                }
            }
            return "";
        }
    }

    ** enum 비교는 equals가 아닌 == 

     

     

    public boolean chkSttlCd(String code, SttlCd sttlCd) {
        String sttlCdName = "";
        
        for (SttlCd cd : SttlCd.values()) {
           if (code.equals(cd.getCode()) {
               sttlCdName = cd.name();
           }
        }
        
        if (!sttlCdName.equals("")) {
            if (SttlCd.valueOf(sttlCdName) == sttlCd) {
                return true;
            }
        }
         
        return false;
    }

    최종 메서드는 이렇게 했다

     

     

    public static void main(String[] args) {
        EnumTestDto tmpDto = new EnumTestDto("100");
        Boolean restult = SttlCd.chkCode(tmpDto.getEnumTestCd(), SttlCd.INCOME12);
        System.out.println("result : " + restult);
        // result : false
    }

    확인 완료

     

     

    if (SttlCd.INCOME12.getCode().equals(EnumTestDto.getEnumTestCd())) {
        System.out.println("비즈니스 로직");
    }
    if (SttlCd.chkCode(tmpDto.getEnumTestCd(), SttlCd.INCOME12)) {
        System.out.println("비즈니스 로직");
    }

    결론적으로 Eunm과 자바 Stream API를 통해 코드를 수정할 수 있었다

    확실히 이론으로 배우는 것과 실무에서 직접 사용하는 것은 차이가 있고 배운 만큼 실무에서 사용해 보도록 해야겠다

     

     

    public static boolean hasCode(String code) { 
    	return Arrays.stream(SttlCd.values())
        		.anyMatch(rslt -> rslt == SttlCd.valueOf(getSttlCd(code)));
    }

    Stream API를 사용해보고 싶어 hasCode() 메서드를 생성했다

    INCOME00과 매칭되는 상수값 "100"을 가져오는 방법이 없어 getSttlCd 메서드를 생성했고 해당 메서드를 통해 "100"값으로 들어와도 INCOME00으로 반환값을 출력하도록 했다

    getSttlCd() 또한 Stream API를 활용하고 싶었으니 Arrays.Stream을 어떻게 해결할 방법을 아직 찾지 못했다

     

     

    아쉬운 점은 테스트코드도 함께 작성하면서 공부하고 싶었는데

    프로젝트 기간을 지키는 것도 중요한 만큼 지금은 하지 못했다 

    빠른 시일 내로 테스트 코드도 한 번 작성해 봐야겠다

    728x90

    '업무' 카테고리의 다른 글

    20250207  (0) 2025.02.08
    pull patch 한 번에 뜰 때, commit 오류  (0) 2025.01.13
Designed by Tistory.