break를 사용하여 Java에서 루프를 종료하는 것이 나쁜 습관입니까? [닫은]


79

break루프 조건을 충족하는 대신 문을 사용 하여 루프를 종료하는 것이 "나쁜 습관"인지 궁금합니다 .

루프가 어떻게 처리되는지 알기에는 Java와 JVM에 대한 충분한 통찰력이 없기 때문에 그렇게함으로써 중요한 것을 간과하고 있는지 궁금합니다.

이 질문의 초점 : 특정 성능 오버 헤드가 있습니까?


13
'휴식'은 그 목적만을위한 것이므로 나쁜 습관이라고 생각하지 않습니다.
Android Killer

19
나쁜 습관은 5 번의 반복 후에 종료 할 수 있더라도 백만 번 반복하는 것입니다 ...
assylias

2
개인적으로는 가끔 코드의 가독성을 높일 수 있습니다 휴식을 사용하고 내가 그 상황에서 당신이 그것을 호출 나쁜 연습을 수 있다고 생각하지 않습니다, 상황에 따라 생각
user902383

2
스트림을 생성하고 닫지 않은 후 루프 / 메소드를 종료하는 등 원치 않는 상황이 많이 발생할 수 있으므로 나쁜 습관으로 간주됩니다. 그러나 신중하게 사용하면 괜찮습니다.
Pshemo 2013-08-12

3
기본적으로, 당신은 어떤을 대체 할 수 breakif코드의 약 전체 나머지. 이것이 "구조화 된 프로그래밍"패러다임을 파 시적으로 따르는 다른 언어로 수행되는 방법입니다. 코드가 끔찍해 보입니다.
Marko Topolnik 2013-08-12

답변:


134

맙소사. 때로는 논리적 루프 조건을 만족하지 않고 전체 요구 사항을 충족하는 루프에서 무언가가 발생할 수 있습니다. 이 경우, break루프 주위를 무의미하게 순환하는 것을 막기 위해 사용됩니다.

String item;

for(int x = 0; x < 10; x++)
{
    // Linear search.
    if(array[x].equals("Item I am looking for"))
    {
       //you've found the item. Let's stop.
       item = array[x];
       break; 
    }
}

이 예에서 더 의미있는 것은 무엇입니까? 발견 한 후에도 매번 10 개까지 계속 반복 하시겠습니까? 아니면 항목을 찾아 멈출 때까지 반복 하시겠습니까? 또는 실제 용어로 표현할 수도 있습니다. 열쇠를 찾으면 계속 찾으세요?

댓글에 대한 응답으로 수정

왜 설정되지 않은 x위해 11루프를 깰? 무의미합니다. 우리는 있어요 break! 코드가 나중에 x보다 확실히 더 큰 가정을하지 않는 한 10(아마도 그렇게해서는 안됨) break.

완전성을 위해 편집

시뮬레이션하는 다른 방법이 있습니다 break. 예를 들어 루프의 종료 조건에 추가 로직을 추가합니다. 무의미하게 루프이거나 사용한다고 말하는 break것은 공정하지 않습니다. 지적했듯이 while 루프는 종종 유사한 기능을 수행 할 수 있습니다. 예를 들어, 위의 예를 따르면 ..

while(x < 10 && item == null)
{
    if(array[x].equals("Item I am looking for"))
    {
        item = array[x];
    }

    x++;
}

break간단히 사용 하면 for루프를 통해이 기능을 수행 할 수 있습니다 . 또한 루프가 다르게 동작하기를 원할 때마다 종료 로직에 조건을 계속 추가 할 필요가 없음을 의미합니다. 예를 들면.

for(int x = 0; x < 10; x++)
{
   if(array[x].equals("Something that will make me want to cancel"))
   {
       break;
   }
   else if(array[x].equals("Something else that will make me want to cancel"))
   {
       break;
   }
   else if(array[x].equals("This is what I want"))
   {
       item = array[x];
   }
}

while loop다음과 같은 종료 조건 이있는 대신 :

while(x < 10 && !array[x].equals("Something that will make me want to cancel") && 
                !array[x].equals("Something else that will make me want to cancel"))

영업 이익은 루프 / 휴식을 1000으로 설정 X에 가깝다 뭔가에 대해 질문
나노 패럿

5
휴식 대신 while 루프는 어떻습니까? 그러면 모든 루프 완료 조건이 루프 시작 부분에 있습니다. while(x < 10 && item == null)마음에 드는 경우 반복자를 사용하십시오.
Freiheit

@Freiheit : 당신은 그것을 사용하거나 심지어 당신이 그것을 개선 할 수 있습니다. 그러나에서 주어진 예 Chris는 OP의 이해를위한 것이라고 생각 합니다.
Nandkumar Tekale 2013-08-12

1
@hexafraction : x루프 아래의 코드에서 인덱스 를 사용하려면 어떻게해야 합니까? 예found string at index x
Nandkumar Tekale 2013-08-12

@NandkumarTekale 그런 다음 외부에 선언하고 손상되지 않은 상태로 루프를 빠져 나가야합니다.
nanofarad

18

break실제로 다른 언어 기능과 마찬가지로를 사용 하는 것은 분명히 오용하는 특정 컨텍스트 내에서 나쁜 습관이 될 있습니다. 그러나 일부 매우 중요한 관용구는 그것 없이는 코딩 할 수 없거나 적어도 가독성이 훨씬 떨어지는 코드가됩니다. 이 경우 break갈 길입니다.

다시 말해서, 담요 나 자격이없는 조언, break또는 그 밖의 어떤 것도 듣지 마십시오 . 문자 그대로 "좋은 관행"을 시행하기 위해 코드가 완전히 쇠약해진 것을 본 적이 한 번이 아닙니다.

성능 오버 헤드에 대한 우려는 전혀 없습니다. 어쨌든 바이트 코드 수준에서는 명시적인 루프 구조가 없습니다. 모든 흐름 제어는 조건부 점프 측면에서 구현됩니다.


6

JLS는 중단이 루프의 비정상 종료임을 지정합니다. 그러나 비정상으로 간주된다고해서 다양한 코드 예제, 프로젝트, 제품, 우주 왕복선 등에서 사용되지 않는다는 의미는 아닙니다. JVM 사양은 성능 손실의 유무를 명시하지 않습니다. 명확한 코드 실행은 루프 후에도 계속됩니다.

그러나 코드 가독성은 이상한 중단으로 인해 어려움을 겪을 수 있습니다. 부작용과 이상한 정리 코드로 둘러싸인 복잡한 if 문에서 중단을 고수하고 레이블이있는 다단계 중단 (또는 이상한 종료 조건 집합이 차례로 있음)이있을 수 있습니다. 누구나 쉽게 읽을 수 있습니다.

반복 변수를 반복 범위를 벗어나도록 강제하거나 불필요하게 직접 종료하는 방법을 도입하여 루프를 중단하려면 break.

그러나 빈 방식으로 추가 시간을 반복하는 것은 추가 반복이 필요하고 명확하지 않을 수 있으므로 거의 항상 나쁜 습관입니다.


5

제 생각에는 For고정 된 양의 반복이 수행되고 모든 반복이 완료되기 전에 중지되지 않을 때 루프를 사용해야합니다. 이전에 종료하려는 다른 경우에는 While루프 를 사용하는 것을 선호합니다 . 이 두 개의 작은 단어를 읽더라도 더 논리적으로 보입니다. 몇 가지 예 :

for (int i=0;i<10;i++) {
    System.out.println(i);
}

이 코드를 빨리 읽으면 10 줄을 인쇄 한 다음 계속 진행할 것입니다.

for (int i=0;i<10;i++) {
    if (someCondition) break;
    System.out.println(i);
}

이것은 이미 나에게 덜 명확합니다. 먼저 10 번의 반복을 수행 할 것이라고 말한 다음 루프 내부에 더 빨리 중지 할 추가 조건을 추가하는 이유는 무엇입니까?

나는 이런 식으로 작성된 이전 예제를 선호합니다 (조금 더 장황하지만 한 줄만 더있는 경우에도 마찬가지입니다).

int i=0;
while (i<10 && !someCondition) {
    System.out.println(i);
    i++;
}

이 코드를 읽는 모든 사람은 루프를 일찍 종료 할 수있는 추가 조건이 있음을 즉시 알 수 있습니다.

물론 매우 작은 루프에서 모든 프로그래머가 break 문을 알아 차릴 것이라고 항상 토론 할 수 있습니다. 그러나 내 경험을 통해 더 큰 루프에서 이러한 휴식을 감독 할 수 있음을 알 수 있습니다. (그리고 더 작은 덩어리로 코드 분할을 시작하는 또 다른 주제로 이동합니다)


2
이것은 for 또는 while 루프 중에 조건에 도달하는 상황을 고려하지 않습니다. for / while 루프가 조건 (또는 다른 스레드에서 실행중인 항목)을 트리거하면 일찍 중단해야 할 수 있습니다. 작성한 while 루프는 반복 시작시 조건 만 확인하면된다고 가정합니다.
Doc

나는 이것에 전적으로 동의합니다. for 루프가있는 경우 초기화, 조건 및 증분을위한 논리가 한 곳에 함께있는 것이 의도입니다. 이것은 무슨 일이 일어나고 있는지 정확히 찾기 위해 여기 저기 어디에서나 볼 필요가 없습니다. 반복 할 횟수를 모르는 경우 "while"을 반복하는 것이므로 while 루프 여야합니다. 무언가가 될 때까지 반복한다면 잠시 동안해야합니다. 나는 휴식이 나쁜 관행이라고 전혀 제안하지 않지만, 시간과 장소가 있습니다.
ThePerson

4

break in loop를 사용하는 것은 완벽하게 합법적 일 수 있으며 일부 문제를 해결하는 유일한 방법 일 수도 있습니다.

그러나 이는 새로운 프로그래머가 일반적으로이를 악용하여 코드를 혼란스럽게 만들고, 특히 처음에 루프 조건문에 작성되었을 수있는 조건에서 break를 사용하여 루프를 중지한다는 사실에서 비롯된 것입니다.


나는 이런 식으로 너무 자주 본다. 루핑 변수를 초기화하고으로 루프를 연 while(true)다음 break어떤 조건에서 s를 실행하는 코드를 볼 때마다 개그를 합니다.
John

@John 가끔 남용되는 동안 그게 잘못된 것은 아니지만 일부 관용구는 while (true) ... break를 요구합니다. 예를 들어, 종료 조건이 조건에 정확히 맞지 않는 이벤트 루프는 중단되기 전에 신호에 따라 다른 처리를 수행 할 수 있습니다.
crasic 2013-08-12

4

아니요, 원하는 특정 조건에 도달하면 (예 : 일치 항목이 발견 된 경우) 루프에서 벗어나는 것은 나쁜 습관이 아닙니다 . 원하는 것을 이미 달성했고 더 이상 반복하는 포인트가 없기 때문에 반복을 중지 할 수 있습니다. 그러나 실수로 무언가를 놓치거나 필요하지 않을 때 이탈하지 않도록주의하십시오.

이것은 또한 수있는 성능 향상에 추가 대신 루프의 목적이 완료된 경우라도 수천 개의 레코드 반복의 루프를 중단하는 경우 (즉, 이미 수행에 필요한 레코드와 일치 할 수 있음).

예 :

for (int j = 0; j < type.size(); j++) {
        if (condition) {
            // do stuff after which you want 

            break; // stop further iteration
        }

}

레이블이 지정된 중단을 사용하여 두 루프를 종료 할 수 있습니다.search: for (int i = 0; i < s; i++) { for (int j = 0; j < t.size(); j++) { if (condition) { break search; } } }
Michael Konietzka 2013-08-12

네, 이미 알고 있습니다. 실수로 게시했습니다.
Ankur Shanbhag 2013-08-12

2

나쁜 습관은 아니지만 코드의 가독성을 떨어 뜨릴 수 있습니다. 이 문제를 해결하기위한 유용한 리팩토링 중 하나는 루프를 별도의 메서드로 이동 한 다음 break 대신 return 문을 사용하는 것입니다. 예를 들면 다음과 같습니다 (@Chris의 답변에서 가져온 예제).

String item;

for(int x = 0; x < 10; x++)
{
    // Linear search.
    if(array[x].equals("Item I am looking for"))
    {
        //you've found the item. Let's stop.
        item = array[x];
        break; 
    }
}

다음과 같이 리팩토링 할 수 있습니다 ( extract method 사용 ).

public String searchForItem(String itemIamLookingFor)
{
    for(int x = 0; x < 10; x++)
    {
        if(array[x].equals(itemIamLookingFor))
        {
            return array[x];
        }
    }
}

주변 코드에서 호출하면 더 읽기 쉽게 증명 될 수 있습니다.


2

이와 같은 일을 시작하면 조금 이상해지기 시작 returns하고 matchedCondition에 따른 결과를 별도의 메서드로 옮기는 것이 좋습니다.

boolean matched = false;
for(int i = 0; i < 10; i++) {
    for(int j = 0; j < 10; j++) {
        if(matchedCondition) {
            matched = true;
            break;
        }
    }
    if(matched) {
        break;
    }
}

위의 코드를 정리하는 방법을 자세히 설명하기 위해 리팩터링 returns하여 breaks. 이것은 일반적으로 complex / messy를 더 잘 처리 breaks합니다.

public boolean  matches()
    for(int i = 0; i < 10; i++) {
        for(int j = 0; j < 10; j++) {
            if(matchedCondition) {
                return true;
            }
        }
    }
    return false;
}

그러나 아래 예제와 같은 간단한 것을 위해. 꼭 이용하십시오 break!

for(int i = 0; i < 10; i++) {
    if(wereDoneHere()) { // we're done, break.
        break;
    }
}

위의 경우 ij의 값 에서 조건을 변경하면 코드를 읽기가 정말 어려워집니다. 또한 상한 (예제에서 10)이 변수 인 경우가있을 수 있으므로 루프를 종료하기 위해 설정할 값을 추측하기가 더 어려울 수 있습니다. 당신은 물론 단지 설정할 수 ij는 Integer.MAX_VALUE로,하지만 난 당신이 매우 빠르게 혼란을 얻기 위해이 시작을 볼 수 있다고 생각합니다. :)


"별도의 방법"리팩토링이 강조 될 만합니다. 어떤 이유로 든 코드 섹션을 읽기가 어려워지는 것이 염려되는 경우 자체 메서드로 추출하는 것이 도움이 될 수 있습니다. 이 질문의 맥락에서 break진술을 return진술 로 변환 할 수도 있습니다 .
Russell Silva

1
@RussellSilva 감사합니다. 강조를 추가하기 위해 편집하겠습니다.
Kenny Cason

첫 번째 사례는 레이블을 중단하여 단순화 할 수 있습니다. 어떤 사람들은 그것이라고 느껴지기 때문에 그것을 좋아하지 goto않지만 이것은 특히 유용한 경우 중 하나입니다.
Darrel Hoffman

@DarrelHoffman 당신은 확실히 그것을 할 수 있지만, 나는 그것을 별도의 메소드로 만들고 반환하는 것이 적어도 자바에서 이것을 처리하는 더 "표준적인"방법이라고 생각합니다.
Kenny Cason 2013-08-12

2

break알고리즘을 표현하는 가장 자연스러운 방법 인 여러 가지 일반적인 상황 이 있습니다. 이를 "반복형"구조라고합니다. 패러다임의 예는

while (true) {
    item = stream.next();
    if (item == EOF)
        break;
    process(item);
}

break이것을 사용할 수 없다면 대신 자신을 반복해야합니다.

item = stream.next();
while (item != EOF) {
    process(item);
    item = stream.next();
}

일반적으로 이것이 더 나쁘다는 데 동의합니다.

마찬가지로 continue에는 다음과 같은 일반적인 패턴이 있습니다.

for (item in list) {
    if (ignore_p(item))
        continue;
    if (trivial_p(item)) {
        process_trivial(item);
        continue;
    }
    process_complicated(item);
}

이것은 종종 하나 이상의 함수 호출이 else if있을 때 chained를 사용하는 대안보다 더 읽기 쉽습니다 process_complicated.

추가 읽기 : 루프 종료 및 구조화 프로그래밍 : 토론 재개


1

아니요, 나쁜 습관이 아닙니다. 가장 쉽고 효율적인 방법입니다.


4
그러나 가독성이 가장 떨어지는 방법 일 수도 있습니다. 이 같은 담요 문은 보통 거짓 중요한 부분 집합 의 경우.
Stephen C

귀하의 logic. 때로는 일부 플래그 또는 무언가를 기반으로 루프를 비정상적으로 종료하고 싶습니다. 이 경우 break좋은 옵션입니다.
user2550754 2013-08-12

1

break를 사용하는 것이 나쁘지 않고 훌륭한 용도가 많이 있지만, 이것이 당신이 의지하는 전부는 아닙니다. 거의 모든 break 사용이 루프 조건에 기록 될 수 있습니다. 실제 조건을 사용하면 코드를 훨씬 더 쉽게 읽을 수 있지만 장기 실행 또는 무한 루프의 경우 중단이 완벽하게 의미가 있습니다. 위와 같이 데이터를 검색 할 때도 의미가 있습니다.


1

루프가 중지해야합니다 위치를 미리 알고 있다면, 그것은 아마의 조건 상태 코드의 가독성을 향상시킬 것 for, while또는 `do-while루프.

그렇지 않으면 break.


1

break그리고 continue종종 유용하지만, 독자의 가독성을 나누기. "goto"개념 만큼은 아니지만 거의.

당신이 (OCaml이 같은 자바와 함수형 프로그래밍 언어에서 영감) 스칼라 같은 몇 가지 새로운 언어를 가지고가는 경우에 게다가, 당신은 것을 볼 수 breakcontinue간단하게 사라졌다.

특히 함수형 프로그래밍에서 이러한 스타일의 코드는 피합니다.

스칼라가 중단 및 계속을 지원하지 않는 이유는 무엇입니까?

요약하면 : breakcontinue널리 필수적 스타일 자바에서 사용되지만 함수형 프로그래밍을 연습하기 위해 사용 된 코더를 위해, 그것은 .. 이상한 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.