엄범


enum을 쓰기 전에 체크해봐야 할 것

  • [Languages & Frameworks/Kotlin Java] - [Effective Java] 6장 열거 타입과 애너테이션
  • 아래 예제 코드에서 코드 1번은 현금, 코드 2번은 카드라는 정보가 DB의 "결제 코드" 테이블에 따로 있는 경우, 아래와 같이 소스코드 단에서 코드를 변환해버리면 DB layer와의 의존성이 생겨버린다. 
    • 아예 코드 매핑을 enum으로 옮기든지, 아니면 매번 DB의 결제 코드 테이블을 읽어서 처리하든지 둘 중 하나만 하는게 좋다.
    • 매번 그냥 조인하는 식으로 처리해도 되지만 그 보다는 다음 방식이 낫다
      • DBMS function을 이용해 코드 변환하는 방식
      • Redis같은걸로 코드 테이블을 메모리에 올려두고 이를 참조해서 사용하는 방식
  • enum도 결국 소스코드이기 때문에, 변경이 발생한다면 다시 컴파일해야 한다. 
  • enum은 extends는 불가하지만, implements는 가능하다.
    • 공통 interface를 만들 때는, getter의 선언부가 인터페이스에 들어가줘야 해당 인터페이스 타입으로 접근했을 때 .getCode() 같은 메서드를 호출할 수 있다. (클래스 구현부에서는 @Getter를 써도 된다.)


```java

// @AllArgsConstructor를 써도 좋다.

// Getter가 정의되어 있어야 .getCode()같은 것으로 내부 값을 가져올 수 있다. interface를 쓰는 경우는 추가적으로 인터페이스 쪽에 getter를 선언해야 할 수 있다.

@Getter

public enum PaymentCode {

    CASH(1, "현금", "cash"),    // 여기서 세번째 인자는 별로 필요없지만 이렇게도 가능하다는 것을 보여주기 위해.

    CARD(2, "카드", "card");


    private final int code;

    private final String koName;

    private final String enName;


    PaymentCode(int code, String koName, String enName) {

        this.code = code;

        this.koName = koName;

        this.enName = enName;

    }


    public static PaymentCode fromKoName(String text){

        for (PaymentCode code :values()){

            if (code.getKoName().equals(text)) {

                return code;

            }

        }

        throw new IllegalArgumentException();

    }

}

```

```java

    /**

     * 위 코드와는 관련 없지만 함수형으로 쓰면 이런 식이 된다.

     */

    public static PaycoResponseCode from(int _code) {

        return Stream.of(values())

            .filter(responseCode -> responseCode.getCode() == _code)

            .findAny()

            .orElseThrow(NoSuchElementException::new);

    }

```


```java

/* 기본 제공 */

log.info("{}", Payment.PaymentCode.valueOf("CARD"));     // CARD 아래와 같다. 이름 문자열 받아서 enum찾을 때 말고는 쓸일 없는 듯.

log.info("{}", Payment.PaymentCode.CARD);                // CARD 위와 같다.

log.info("{}", Payment.PaymentCode.CARD.name());         // CARD

// Payment.PaymentCode.values() 이 것도 있다.


/* @Getter */

log.info("{}", Payment.PaymentCode.CARD.getEnName());    // card

log.info("{}", Payment.PaymentCode.CARD.getKoName());    // 카드

log.info("{}", Payment.PaymentCode.CARD.getCode());      // 2


/* 직접 정의. */

log.info("{}", Payment.PaymentCode.fromKoName("현금"));   // CASH

```


JSON Mapping은 다음과 같이 보내면 매핑된다.

```js

{

    "PaymentCode타입의 필드명" : "CASH"

}

```


EnumConstant 하나를 fieldName-fieldValue 형식으로 매핑

사실 생각해보면 jackson같은걸 쓰고 있다면 ObjectMapper를 사용하면 되니 굳이 이렇게 구현 안해도 될 듯.


enum 전체를 key-value 형식의 Map으로 만드는건 values()를 사용하면 되니 그리 어렵지 않은데, 

EnumConstant 하나를 fieldName-fieldValue 형식으로 매핑해야 하는 경우가 있다 ( 주로 뷰로 전달해야 할 때. )

그냥 ``java map.put("koName", this.koName);`` 이런 식으로 해도 되지만, 아래는 reflection을 이용해 한방에 처리하는 코드.

```java

public Map<String, String> toMap() {

    return Arrays.stream(this.getDeclaringClass().getDeclaredFields())

        .filter(field -> !field.isSynthetic() && !field.isEnumConstant())

        .collect(Collectors.toMap(

            field -> field.getName(),

            field -> getFieldValue(field)));

}


private String getFieldValue(Field field) {

    try {

        return (String)field.get(this);

    } catch (IllegalAccessException e) {

        throw new RuntimeException(e);

    }

}

```

```

{

    code=1,

    koName=현금,

    enName=cash

}

```


'Languages & Frameworks > Java' 카테고리의 다른 글

[Effective Java] 2장 객체 생성과 파괴  (0) 2019.12.02
[java] 날짜 시간 처리 관련  (0) 2019.07.10
[Java] Enum  (0) 2019.06.06
[Gradle] build, jar 배포, IntelliJ 설정  (0) 2019.04.10
[Java] Stream API 노트  (0) 2017.03.09
[Java] lambda 기본 개념  (0) 2017.02.07