[java] switch 문에서 instanceof 연산자를 사용할 수 있습니까?

instanceof객체에 스위치 케이스를 사용하는 것에 대한 질문이 있습니다 .

예를 들어, 내 문제는 Java로 재현 될 수 있습니다.

if(this instanceof A)
    doA();
else if(this instanceof B)
    doB();
else if(this instanceof C)
    doC():

switch...case?를 사용하여 어떻게 구현할 수 있습니까?



답변

이것은 하위 유형 다형성이 도움이되는 일반적인 시나리오입니다. 다음을 수행하십시오

interface I {
  void do();
}

class A implements I { void do() { doA() } ... }
class B implements I { void do() { doB() } ... }
class C implements I { void do() { doC() } ... }

그런 다음 간단히 전화하면 do()됩니다 this.

당신은 자유롭게 변경할 수없는 경우 A, B그리고 C, 당신은 동일을 달성하기 위해 방문자 패턴을 적용 할 수 있습니다.


답변

인터페이스에 코드를 작성할 수 없다면 열거 형을 중개자로 사용할 수 있습니다.

public A() {

    CLAZZ z = CLAZZ.valueOf(this.getClass().getSimpleName());
    switch (z) {
    case A:
        doA();
        break;
    case B:
        doB();
        break;
    case C:
        doC();
        break;
    }
}


enum CLAZZ {
    A,B,C;

}


답변

클래스가 핵심이고 기능, 즉 람다 등이 값인 맵을 작성하십시오.

Map<Class,Runnable> doByClass = new HashMap<>();
doByClass.put(Foo.class, () -> doAClosure(this));
doByClass.put(Bar.class, this::doBMethod);
doByClass.put(Baz.class, new MyCRunnable());

// 물론 한 번만 초기화하도록 리팩터링

doByClass.get(getClass()).run();

예외를 발생시키고 Runnable 대신 예외를 사용하는 FunctionalInterface를 구현하는 것보다 확인 된 예외가 필요한 경우.


답변

누군가가 그것을 읽을 경우를 대비하여 :

자바에서 가장 좋은 해결책은 다음과 같습니다.

public enum Action {
    a{
        void doAction(...){
            // some code
        }

    },
    b{
        void doAction(...){
            // some code
        }

    },
    c{
        void doAction(...){
            // some code
        }

    };

    abstract void doAction (...);
}

이러한 패턴의 큰 장점은 다음과 같습니다.

  1. 당신은 그것을 좋아합니다 (아무것도 스위치 없음) :

    void someFunction ( Action action ) {
        action.doAction(...);
    }
  2. “d”라는 새로운 액션을 추가하는 경우 반드시 doAction (…) 메소드를 구현해야합니다.

참고 :이 패턴은 Joshua의 Bloch “Effective Java (2 판)”에 설명되어 있습니다.


답변

당신은 할 수 없습니다. switch문은 포함 할 수 있습니다 case컴파일 시간 상수 및 정수 (자바 6까지 자바 7의 문자열)에 대한 평가 문을.

함수형 프로그래밍에서 찾고있는 것을 “패턴 일치”라고합니다.

참조 자바 instanceof를 방지


답변

최고의 답변에서 논의 된 바와 같이, 전통적인 OOP 방식은 스위치 대신 다형성을 사용하는 것입니다. 이 트릭에는 잘 문서화 된 리팩토링 패턴이 있습니다 : 조건부를 다형성으로 바꾸기 . 이 접근법에 도달 할 때마다 기본 동작을 제공하기 위해 Null 객체 를 구현하고 싶습니다 .

Java 8부터는 람다와 제네릭을 사용하여 함수형 프로그래머에게 익숙한 패턴 매칭을 제공 할 수 있습니다. 핵심 언어 기능은 아니지만 Javaslang 라이브러리 는 하나의 구현을 제공합니다. javadoc의 예 :

Match.ofType(Number.class)
    .caze((Integer i) -> i)
    .caze((String s) -> new BigDecimal(s))
    .orElse(() -> -1)
    .apply(1.0d); // result: -1

Java 세계에서 가장 자연스러운 패러다임이 아니므로주의해서 사용하십시오. 일반적인 메소드는 일치하는 값을 타입 캐스트하지 않아도되지만, 우리는 스칼라의 사례 클래스 와 같이 일치하는 객체를 분해하는 표준 방법이 없습니다 .


답변

나는 이것이 매우 늦었지만 장래 독자들을 위해 …

A , B , C … 클래스의 이름 에만 기반한 위의 접근 방식에주의하십시오 .

당신은 보장 할 수없는 한 A는 , B , C가 … (모든 서브 클래스 또는 구현 자료가 ) 있습니다 마지막 의 다음 서브 클래스 , B , C가 … 처리되지 않습니다.

많은 수의 서브 클래스 / 구현자가 if, elseif, elseif .. 접근 방식이 느리 더라도 더 정확합니다.