Java 7에서 문자열을 켜면 어떤 이점이 있습니까?


19

Java로 프로그래밍을 시작했을 때 switch 문이 문자열을 사용하지 않는다는 사실 때문에 좌절했습니다. 그런 다음 Enum을 사용하면 유형 안전 (쉽게 리팩토링을 제공함) 및 다른 개발자에게 명확함을 제공하는 대신 원시 값을 전달하지 않고 얻을 수있는 이점을 깨달았습니다.

SE7에서는 이제 열거 형이 아닌 입력으로 문자열이있는 스위치를 사용하기로 결정하는 상황을 생각하기 위해 고심하고 있습니다. 전체 문자열 (예 : 부분 또는 정규식 일치가 아닌)을 전환하여 구현하면 코드를 변경할 이유가 적지 않은 것 같습니다.

그리고 IDE 도구와 코딩의 읽기 / 쓰기 비율을 사용하면 문자열 값을 전달하는 것보다 추가 Enum을 자동 생성하는 것이 훨씬 더 좋습니다.

프로그래머로서 우리에게 어떤 이점이 있습니까? 보일러 플레이트가 적습니까?

언어가이 기능에 대해 울부 짖는 느낌이 들지 않습니다. 어쩌면 내가 간과하는 유스 케이스가있을 수 있습니다.


문자열은 이미 스위치 문에서 이미 많이 사용되었지만 사람들이 직접 사용할 수 없기 때문에 다른 트리 또는 열거 형으로 변환하는 경우 거인과 같은 해결 방법을 사용했습니다. 두 가지 해결 방법 모두 코드를 읽기 어렵게 만듭니다. 두 가지 방법 모두 해결 방법이며 기본적으로 구현 된 솔루션이 프로그래머의 의도를 더 잘 보여주는 경우 해결 방법을 사용해야하는 이유입니다.
Pieter B

@PieterB 그러나 Enum은 해결 방법이 아닌 의미 론적 가치를 추가하여 유형 안전성을 제공합니다 (예 : 오타가 버그가 아닌 컴파일 타임에 잡힐 수 있음). 또한 문자열의 다른 사용법 (도메인 객체에서 자주 발생할 수 있음)에 영향을주지 않고 해당 컨텍스트에서 사용되는 모든 문자열 인스턴스를 리팩터링 할 수 있습니다.
anotherdave

답변:


12

내가 알 수있는 한, 질문은 문자열 상수를 열거 형으로 래핑하는 것이 언어 사용자의 요구를 충족시키기에 충분하지 않은 이유입니다. 이는 JDK 7 (프로젝트 코인) 메일 링리스트에서 발표 된 공식 기능 제안 에서 다루어졌습니다 .

제안서를 읽은 결과 열거 형을 사용하는 대안이 유형 팽창을 소개한다는 근거로 기각되었습니다. 사용자의 편의를 위해 제안의 관련 부분에서 인용 열거 형 주소 지정 문 아래 인용 대담한 :

주요 장점 : 제안이 유리한 변화를 만드는 것은 무엇입니까?

더 일정한 코딩 패턴은 일정한 문자열 값 세트에 기초하여 선택된 연산에 사용될 수있다. 새로운 구조의 의미는 Java 개발자에게 분명해야합니다.

주요 혜택 : 제안이 채택되면 플랫폼이 더 나은 이유는 무엇입니까?

문자열 기반 디스패치 코드의 성능이 향상 될 수 있습니다.

주요 단점 : 항상 비용이 있습니다.

컴파일러의 구현 및 테스트 복잡성이 일부 증가했습니다.

대안 : 언어 변경없이 혜택과 장점을 얻을 수 있습니까?

아니; 문자열 동등성에 대한 체인 if-then-else 테스트는 잠재적으로 비싸며 관심있는 문자열 값 당 하나의 전환 가능한 상수에 대한 열거 형을 도입하면 좋은 원인없이 프로그램에 다른 유형을 추가합니다 ...


대담한 부분은 놀랍습니다
Simon Bergot

1
@Simon 개인적으로 "간접적 인 대우로 읽습니다."우리가 Java와 같은 고려 사항을 다루는 Java5 이전의 방법을 계속 고수한다면 C #에 대한 경쟁을 완화 할 것입니다. " :) " Java 5 이전 방법"의 예는 JDK-1223179를 참조하십시오 . 문자열 켜기-1995 년에 제출되고 수정되지 않음 으로 빠르게 닫힘 : "숨을 쉬지 마십시오.이 계획과 비슷한 것은 없습니다. "
gnat

감사합니다. 제안서에 제시된 이유를 보는 것은 매우 흥미 롭습니다. "좋은 이유없이"프로그램에 유형을 도입한다고 말하는 것은 여전히 ​​잘못된 생각입니다. 우리는 OO 프로그래머입니다! :)
anotherdave

5
@anotherdave "객체 지향"은 의미있는 목적에 부합하는 유형 만 도입하는 것을 정당화합니다. 분명히 JCP에 대한 일반적인 의견은 스위치에서 문자열 상수에 대한 무뇌 래퍼로 열거 형을 사용하는 것이 의미가 없다고 밝혀졌습니다.
gnat

1
와우, 나는 공식적인 제안이 적극적으로 유형의 부풀림을 반대하는 것을보고 (좋은 방법으로) 놀랐습니다. 상쾌합니다. 유형 팽창은 Java에서 큰 문제입니다.
벤 리

7

코드를 더 읽기 쉽게 만드는 것 외에도 if/else if비교에 비해 잠재적 인 성능 향상이 있습니다 . 변경이 가치가 있는지 여부는 비교할 횟수에 따라 다릅니다. 스트링 스위치는 두 개의 개별 스위치 명령으로 방출됩니다. 첫 번째는 해시 코드에서 작동하므로 lookupswitch궁극적으로 O(log n)복잡성을 초래 하는 경향이 있습니다 . 두 번째는 항상 완벽 O(1) tableswitch하므로 결합 된 복잡성은 여전히 ​​그렇습니다 O(log n). 하나의 선형 if/else if문 문장은 약간 더 O(n)복잡합니다.

예를 들어, 3 개 이상의 문자열을 비교하는 경우 a switch가 더 읽기 쉽고 컴팩트합니다. 핫 코드 경로에서 많은 수의 비교를 수행하지 않는 한 차이가 눈에 띄지 않지만 성능이 더 우수 할 수 있습니다.


1
왜 열거 형의 스위치 대신 문자열의 스위치를 사용 해야하는지 더 많이 묻고있었습니다. 나는 큰 if/else블록 나쁜 연습을 고려할 것이지만, 지금은 그것을 사용할 이유가별로 없습니다.
anotherdave

명령의 추가 유형이 있기 때문에 그러나 명령 패턴과 함께지도는 심지어 같은 복잡성을 더 가독성을 얻을 것이다
SpaceTrucker

3

enum값을 외부에서 가져올 때 ( 예 : 데이터베이스에 저장) 문자열 전환을 사용할 수 있습니다 .

JDK 7의 또 다른 주목할만한 점은 구성 switch보다 성능이 훨씬 뛰어납니다 if-else.

빠른 문자열 switches 의 좋은 사용 사례는 노드 및 속성 유형을 많이 전환해야 할 때 JSON / XML 스트림 구문 분석 일 수 있습니다. 더 좋은 옵션을 생각할 수 없습니다.


1
"열쇠 값은 열거 형 값이 외부에서 온 경우 (예 : 데이터베이스에 저장 될 때) 대체 할 수 없습니다.": 이에 대해 자세히 설명 할 수 있습니까? switch 문의 문자열은 하드 코딩됩니다. 데이터베이스의 문자열이 변경 되 자마자 코드가 오래되었습니다.
조르지오

글쎄요, 당신은 맞습니다 enum.이 경우 자바의 정적 특성 때문에 사용할 수 있습니다. 이 글을 쓸 때 나는 Role보통 클래스로 제공되며에 넣을 수없는 보안 라이브러리에서 생각 했습니다 enum. 또 다른 경우는 동적으로 컴파일 된 Java / Groovy 코드입니다.이 경우 드물지만 문자열 스위치가 더 나은 옵션 일 수 있습니다.
Andrey Chaschev

2

간단

Switch in String 지원은 열거 형 또는 if-else논리로 변환하지 않고 데이터를 처리하는 데 유용합니다 . 때로는 문자열을 켜는 것이 더 쉽습니다.

에서 JDK 7 (프로젝트 동전) 메일 링리스트에서 기능 제안 ( @gnat 대답 )

관심있는 문자열 값 당 하나의 전환 가능한 상수에 대한 열거 형을 도입하면 좋은 원인없이 프로그램에 다른 유형을 추가 할 수 있습니다 ...

그렇지 않은 경우 버전

이것은 짧지 만 많은 사람들 if's이 읽기가 어렵습니다. 그리고 이것은 느립니다.

if (color.equals("red")) {
    System.out.println("Color is Red");
} else if (color.equals("green")) {
    System.out.println("Color is Green");
} else {
    System.out.println("Color not found");
}

열거 형 버전

열거 형을 정의해야하며, 이것은 좋지만 때로는 필요하지 않습니다.

enum Color {RED, GREEN}

평소와 같이 처리

try {
    switch (Color.valueOf(color)) {
        case RED:
            System.out.println("Color is Red");
            break;
        case GREEN:
            System.out.println("Color is Green");
            break;
    }
} catch (IllegalArgumentException e) {
    System.out.println("Color not found");
}

JDK 7-스위치 명령문 버전의 문자열

추가 유형을 변환하고 정의하지 않고도 처리 할 수 ​​있습니다.

switch (color) {
    case "red":
        System.out.println("Color is Red");
        break;
    case "green":
        System.out.println("Color is Green");
        break;
    default:
        System.out.println("Color not found");
}

7
그러나 이것은 질문을 다루지 않습니다. 왜 열거 형 대신 문자열을 사용합니까?
Dave Newton

0

모든 언어에서 개선 된 부분은 코드를보다 쉽게 ​​읽을 수 있도록하는 것입니다. 나는 언젠가 공상보다 읽기 쉬운 코드를 선호합니다.

이것을 믿을 수는 없지만 시도해보십시오.

public enum JettStaff {
  ADRIAN("Adrian German") {
    public String toString() {
      return name + " (dgerman@indiana.edu)";
    }
  },
  ARJIT("Arjit Sengupta") {
    public String toString() {
      return name + " (asengupt@indiana.edu)";
    }
  },

  // and on for the rest...

  private String name;

  public JettStaff(String n) { this.name = n; }
}

JettStaff x = JettStaff.SUZANNE;
System.out.println(x);

위의 코드 예제와 귀하의 의견이 확실하지 않습니다. 읽기 어려운 무언가의 예로 Enum을 의미합니까?
anotherdave


2
이것은 매우 고안되었습니다. 열거 형에 전자 메일 필드가 없거나 클래스가 아닌 것으로 가장하고 있습니다.
Dave Newton

4
@ user2860598 지적하려는 점이 있다면 관련된 예를 사용하십시오. 또한 팻 핑거링 문자열 상수를 다루지 않습니다.
Dave Newton

1
@ user2860598 당신이 연결 한 대답은 소개되었고 이전에 Enum으로 "대략적"일 수 있다는 것입니다. 내 요점은 Enum 사용이 소개에도 여전히 선호되는 것 같습니다.
anotherdave

0

열거 형은 훌륭하므로 가능하면 문자열 대신 사용해야합니다. 그러나 Java 외부에서 오는 외부 객체로 작업 해야하는 경우와 같이 때로는 불가능한 경우가 있습니다. 무언가를 파싱해야한다고 상상해보십시오. 서버 응답, 구성, 로그 파일 또는 이와 유사한 것 : 찾고있는 많은 옵션이 있으며 열거 형이 될 수있는 방법이 없습니다. Java <7에서는 여러 가지 문제가 발생합니다.

  if (something.equals("foo")) {
    // foo processing
  } else 
  if (something.equals("bar")) {
   // bar processing
  }

이 경우 이름으로 가져 오거나 사용자 정의 문자열-> 열거 루틴을 제공하여 열거 형을 계속 사용할 수 있지만 때로는 불가능하거나 실용적이지 않습니다 (예 : 너무 많은 열거 형을 만들어야 할 때)

TLDR : 순수하게 Java 코드로 작업 할 때 반드시 Enum 을 사용해야하지만 항상 외부 객체로 가능하지는 않습니다. 내 설명이 이해되기를 바랍니다.


외부 데이터를 처리하고 있고 if명령문에 필요한 내용을 이미 알고있는 경우 어쨌든 랩핑해야합니다. 즉, 열거 형이나 명령 패턴 등을 계속 사용할 수 있습니다.
Dave Newton

@DaveNewton 예, 여전히 열거 형을 사용할 수는 있지만 대답에서 언급했듯이 구문 분석 중에 코드에서 한 번만 사용되도록 중단 된 열거 형을 만드는 경우와 같이 실용적이지 않은 경우가 있습니다.

@dimoniy 그러나 100의 Enum 값을 만들어야한다면 스위치 대안으로 100의 경우를 진술해야한다는 의미가 아닙니까? 변수가 많으면 열거 형의 형식 안전성을 확실히 선호합니다.
anotherdave

0

Stringsswitch 문에 사용할 때 코드가 깨끗하고 읽기 쉽다는 의견에 동의하지 않으며 프로그래밍이 잘못되었다고 생각합니다. 저장하는 데 사용하는 값을 변경하면 모든 스위치 또는 if-elseif 발생마다 값을 변경해야합니다. 하드 코드 된 값을 코드의 모든 Bir에 넣기 때문에 좋지 않습니다. 언젠가이 하드 코딩 된 값 중 하나를 변경하기로 결정한 경우 어떻게 하시겠습니까? 모든 사본을 검색하고 교체 하시겠습니까?

if-elseif 문을 수행하는 일부 하드 코딩 된 값이있는 경우 상수 안전 값을 사용하는 것이 Java 1.5 이전에는 유형 안전성을 가져 오기 때문에 훨씬 좋습니다.

좋아, HTTP 요청, 파일 등에서 String 값을 얻는 상황이있을 수 있으며 원시 값으로 변환하는 것은 많은 고통입니다. 그러나이 Enum시점에서 좋은 일을한다. Enum에 저장 한 값을 변경하려면 선언 할 때 변경하면됩니다. 코드에서 다른 것을 변경할 필요가 없습니다. (물론 다른 곳에 저장된 값을 변경해야합니다).

더럽고 게으른 코드를 구현하는 것만으로도 완벽합니다. 많은 코드를 작성하고 싶지는 않지만 Enum대규모의 복잡한 소프트웨어를 사용하면 죽일 수 있습니다.


-1

어떤 정보가 들어오는 지 알고 5 개 상태 일 수 있다는 것을 알고 있다면 Enum. 그러나 가능한 상태가 9000 이상이고 42 만 찾으면 스위치를 사용하는 것이 좋습니다. 모든 상태를 입력하고 싶지 않기 때문입니다.

Enum은 가능한 상태를 알 수 없거나 많지 않고 몇 가지만 신경 쓰지 않는 한 대부분의 환경에서 대부분 선택하는 경향이 있습니다.

그런데 왜 그들이 지금 소개 했습니까? 더 깨끗한 코드를 허용 한 변경 일뿐입니다.

1.5에서는 Enum에 대한 사용자 지정 본문을 만들 수도 있습니다.


그러나 다른 8958 가능한 값을 하나의 Enum 상태에 할당하지 않겠습니까?
anotherdave

곳입니다 @anotherdave default에서이 switch놀이에 온다. 나는 당신이 기본 상태 Enum를 만들지 않으면 기본 상태를 가질 수 있다는 것을 모른다. 하지만이 코드는 부풀어 오르지 만 사용하는 switch것이 훨씬 깨끗합니다.

3
UNKNOWNEnum 의 상태가 부풀어 오른다는 것은 이상한 일이지만 default스위치 의 경우는 그렇지 않습니다.
anotherdave
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.