[java] Java switch 문 여러 경우

Java switch 문에 여러 사례를 사용하는 방법을 알아 내려고합니다. 다음은 내가하려는 작업의 예입니다.

switch (variable)
{
    case 5..100:
        doSomething();
    break;
}

해야 할 일과 비교 :

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}

이것이 가능하다면 어떤 아이디어 나 좋은 대안은 무엇입니까?



답변

슬프게도 Java에서는 불가능합니다. if-else문 사용에 의지해야 합니다.


답변

두 번째 옵션은 완전히 괜찮습니다. 응답자가 왜 불가능하다고 말했는지 모르겠습니다. 이것은 괜찮습니다. 저는 항상 이것을합니다.

switch (variable)
{
    case 5:
    case 6:
    etc.
    case 100:
        doSomething();
    break;
}


답변

public class SwitchTest {
    public static void main(String[] args){
        for(int i = 0;i<10;i++){
            switch(i){
                case 1: case 2: case 3: case 4: //First case
                    System.out.println("First case");
                    break;
                case 8: case 9: //Second case
                    System.out.println("Second case");
                    break;
                default: //Default case
                    System.out.println("Default case");
                    break;
            }
        }
    }
}

밖:

Default case
First case
First case
First case
First case
Default case
Default case
Default case
Second case
Second case

서버 : http://docs.oracle.com/javase/tutorial/java/nutsandbolts/switch.html


답변

이전 답변만큼 우아하지는 않지만 큰 범위가 거의없는 스위치 케이스를 얻으려면 미리 범위를 단일 케이스로 결합하십시오.

// make a switch variable so as not to change the original value
int switchVariable = variable;

//combine range 1-100 to one single case in switch
if(1 <= variable && variable <=100)
    switchVariable = 1;
switch (switchVariable)
{
    case 0:
        break;
    case 1:
        // range 1-100
        doSomething();
        break;
    case 101:
        doSomethingElse();
        break;
    etc.
} 


답변

옵션을 지향 한 개체 과도하게 큰 교체 switchif/else구조는을 사용하는 Chain of Responsibility Pattern의사 결정을 모델링 할 수 있습니다.

책임의 사슬 패턴

책임 체인 패턴을 사용하면 요청에 대해 잠재적으로 많은 수의 핸들러 중 어느 것이 조치를 취해야하는지 결정하는 것으로부터 요청 소스를 분리 할 수 ​​있습니다. 체인 역할을 나타내는 클래스는 핸들러가 요청을 수락하고 조치를 취할 때까지 핸들러 목록을 따라 소스의 요청을 채널링합니다.

다음은 Generics를 사용하는 Type Safe 인 구현의 예입니다.

import java.util.ArrayList;
import java.util.List;

/**
* Generic enabled Object Oriented Switch/Case construct
* @param <T> type to switch on
*/
public class Switch<T extends Comparable<T>>
{
    private final List<Case<T>> cases;

    public Switch()
    {
        this.cases = new ArrayList<Case<T>>();
    }

    /**
     * Register the Cases with the Switch
     * @param c case to register
     */
    public void register(final Case<T> c) { this.cases.add(c); }

    /**
     * Run the switch logic on some input
     * @param type input to Switch on
     */
    public void evaluate(final T type)
    {
        for (final Case<T> c : this.cases)
        {
            if (c.of(type)) { break; }
        }
    }

    /**
     * Generic Case condition
     * @param <T> type to accept
     */
    public static interface Case<T extends Comparable<T>>
    {
        public boolean of(final T type);
    }

    public static abstract class AbstractCase<T extends Comparable<T>> implements Case<T>
    {
        protected final boolean breakOnCompletion;

        protected AbstractCase()
        {
            this(true);
        }

        protected AbstractCase(final boolean breakOnCompletion)
        {
            this.breakOnCompletion = breakOnCompletion;
        }
    }

    /**
     * Example of standard "equals" case condition
     * @param <T> type to accept
     */
    public static abstract class EqualsCase<T extends Comparable<T>> extends AbstractCase<T>
    {
        private final T type;

        public EqualsCase(final T type)
        {
            super();
            this.type = type;
        }

        public EqualsCase(final T type, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.type = type;
        }
    }

    /**
     * Concrete example of an advanced Case conditional to match a Range of values
     * @param <T> type of input
     */
    public static abstract class InRangeCase<T extends Comparable<T>> extends AbstractCase<T>
    {
        private final static int GREATER_THAN = 1;
        private final static int EQUALS = 0;
        private final static int LESS_THAN = -1;
        protected final T start;
        protected final T end;

        public InRangeCase(final T start, final T end)
        {
            this.start = start;
            this.end = end;
        }

        public InRangeCase(final T start, final T end, final boolean breakOnCompletion)
        {
            super(breakOnCompletion);
            this.start = start;
            this.end = end;
        }

        private boolean inRange(final T type)
        {
            return (type.compareTo(this.start) == EQUALS || type.compareTo(this.start) == GREATER_THAN) &&
                    (type.compareTo(this.end) == EQUALS || type.compareTo(this.end) == LESS_THAN);
        }
    }

    /**
     * Show how to apply a Chain of Responsibility Pattern to implement a Switch/Case construct
     *
     * @param args command line arguments aren't used in this example
     */
    public static void main(final String[] args)
    {
        final Switch<Integer> integerSwitch = new Switch<Integer>();
        final Case<Integer> case1 = new EqualsCase<Integer>(1)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.type.equals(type))
                {
                    System.out.format("Case %d, break = %s\n", type, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        integerSwitch.register(case1);
        // more instances for each matching pattern, granted this will get verbose with lots of options but is just
        // and example of how to do standard "switch/case" logic with this pattern.
        integerSwitch.evaluate(0);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(2);


        final Switch<Integer> inRangeCaseSwitch = new Switch<Integer>();
        final Case<Integer> rangeCase = new InRangeCase<Integer>(5, 100)
        {
            @Override
            public boolean of(final Integer type)
            {
                if (super.inRange(type))
                {
                    System.out.format("Case %s is between %s and %s, break = %s\n", type, this.start, this.end, super.breakOnCompletion);
                    return super.breakOnCompletion;
                }
                else
                {
                    return false;
                }
            }
        };
        inRangeCaseSwitch.register(rangeCase);
        // run some examples
        inRangeCaseSwitch.evaluate(0);
        inRangeCaseSwitch.evaluate(10);
        inRangeCaseSwitch.evaluate(200);

        // combining both types of Case implementations
        integerSwitch.register(rangeCase);
        integerSwitch.evaluate(1);
        integerSwitch.evaluate(10);

    }
}

이것은 내가 몇 분 만에 채찍질 한 빠른 짚 맨일 뿐이다. 좀 더 정교한 구현은 콜백 IoC 스타일로 만들기 위해 구현 인스턴스 에 어떤 종류의 Command Pattern주입을 허용 할 수 있다 Case.

이 접근 방식에 대한 좋은 점은 Switch / Case 문이 모두 부수적 영향에 관한 것이라는 점입니다. 이것은 부수 효과를 클래스에 캡슐화하여 관리하고 더 잘 재사용 할 수 있도록합니다. 결국 기능적 언어의 패턴 일치와 비슷해집니다. 그것은 나쁜 것이 아닙니다.

Gist 에 대한 업데이트 나 개선 사항을 Github에 게시하겠습니다 .


답변

이 질문 에 따르면 전적으로 가능합니다.

동일한 논리를 포함하는 모든 케이스를 함께 배치하고 break뒤에 배치하지 마십시오 .

switch (var) {
    case (value1):
    case (value2):
    case (value3):
        //the same logic that applies to value1, value2 and value3
        break;
    case (value4):
        //another logic
        break;
}

case없이는 또는 까지 break다른 것으로 점프하기 때문 입니다.casebreakreturn

편집하다:

댓글에 답장하면 논리가 동일한 95 개의 값이 있지만 논리가 다른 케이스 수가 훨씬 적다면 다음과 같이 할 수 있습니다.

switch (var) {
     case (96):
     case (97):
     case (98):
     case (99):
     case (100):
         //your logic, opposite to what you put in default.
         break;
     default:
         //your logic for 1 to 95. we enter default if nothing above is met. 
         break;
}

더 세밀한 제어가 필요한 경우 if-else선택합니다.


답변

원래:

if (variable >= 5 && variable <= 100)
{
    doSomething();
}

정말 스위치를 사용해야한다면 특정 범위에 대해 다양한 작업을해야하기 때문일 것입니다. 이 경우, 예, 당신은 복잡한 코드를 갖게 될 것입니다. 왜냐하면 상황이 복잡해지고 패턴을 따르는 것만 잘 압축 될 것이기 때문입니다.

전환의 유일한 이유는 숫자 전환 값을 테스트하는 경우 변수 이름 입력을 절약하기위한 것입니다. 당신은 100 가지를 켜지 않을 것이고, 그들은 모두 같은 일을하지 않을 것입니다. 그것은 ‘if’청크처럼 들립니다.