레이블이 지정된 휴식을 사용하는 것이 Java에서 좋은 방법입니까?
나는 2001 년의 오래된 코드를보고 있는데 다음과 같은 진술을 발견했다.
else {
do {
int c = XMLDocumentFragmentScannerImpl.this.scanContent();
if (c == 60) {
XMLDocumentFragmentScannerImpl.this.fEntityScanner.scanChar();
XMLDocumentFragmentScannerImpl.this.setScannerState(1);
break label913;
}
나는 전에 이것을 본 적이 없으며 여기에서 레이블이 지정된 휴식을 발견했습니다.
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html
이것은 본질적으로 다음과 같이 작동하지 goto
않습니까? 그것을 사용하는 것이 좋은 습관입니까? 그것은 나를 불안하게 만든다.
아니요, 제어 흐름의 다른 부분으로 "이동"할 수 없기 때문에 이동과는 다릅니다.
링크 한 페이지에서 :
break 문은 레이블이 지정된 문을 종료합니다. 제어 흐름을 레이블로 전달하지 않습니다. 제어 흐름은 레이블이 지정된 (종료 된) 명령문 바로 다음 명령문으로 전송됩니다.
이는 현재 실행중인 루프 만 중단 할 수 있음을 의미합니다.
이 예를 고려하십시오.
first:
for( int i = 0; i < 10; i++) {
second:
for(int j = 0; j < 5; j ++ )
{
break xxx;
}
}
third:
for( int a = 0; a < 10; a++) {
}
당신은 대체 할 수 xxx
와 first
나 second
모두 루프는 당신이 명중 할 때, 실행되고 있기 때문에, (외부 또는 내부 루프를 중단하기 위해) break
문을하지만, 교체 xxx
로하는 third
컴파일되지 않습니다.
goto
레이블이 지정된 명령문 (일반적으로 루프 구성)의 끝까지 만 제어를 보내기 때문에 그렇게 끔찍하지는 않습니다 . 만드는 것은 goto
unlikeable이 어디에 임의의 지점이라는 것이다 포함한 라벨은 당신이 집에서 재배 반복 동작을 할 수 있습니다 그래서, 방법 원에서 최대 높은 발견했다. Java의 레이블 분리 기능은 제어가 앞으로 만 진행되기 때문에 그런 종류의 광기를 허용하지 않습니다.
약 12 년 전에 한 번만 사용했습니다. 중첩 루프에서 벗어나야하는 상황에서 루프에서 더 복잡한 테스트를 위해 더 구조화 된 대안을 만들었을 것입니다. 나는 그것을 많이 사용하는 것을 권하지는 않지만 자동적 인 나쁜 코드 냄새로 플래그를 지정하지 않을 것입니다.
이 답변의 나머지 부분을 읽기 전에 유해한 것으로 간주되는 문으로 이동을 읽어 보십시오 . 전체를 읽고 싶지 않다면 여기에 핵심 포인트가 있습니다.
go to 문을 자유롭게 사용하면 프로세스 진행 상황을 설명 할 의미있는 좌표 집합을 찾기가 매우 어려워지는 즉각적인 결과가 발생합니다.
또는 다시 말하면, 문제 goto
는 프로그래머가 그 시점에서 프로그램 상태를 이해하지 않고도 프로그램이 코드 블록의 중간에 도착할 수 있다는 것입니다. 표준 블록 지향 구조는 상태 전이를 명확하게 묘사하도록 설계되었으며, 레이블 break
은 프로그램을 특정 알려진 상태 (포함 된 레이블이있는 블록 외부)로 전환 하기위한 것입니다.
실제 명령형 프로그램에서 상태는 블록 경계에 의해 명확하게 묘사되지 않으므로 레이블 break
이 좋은 아이디어 인지 여부는 의문 입니다. 블록이 블록 외부에서 보이는 상태를 변경하고 블록을 종료 할 여러 지점이있는 경우 레이블 break
이있는은 기본 요소와 동일합니다 goto
. 유일한 차이점은 불확정 상태의 블록 중간에 착륙 할 가능성이 아니라 불확정 상태로 새 블록을 시작한다는 것입니다.
따라서 일반적으로 레이블 break
이 위험한 것으로 간주합니다 . 제 생각에는 블록을 둘러싸는 범위에 대한 제한된 액세스와 함께 함수로 변환해야한다는 신호입니다.
그러나이 예제 코드는 분명히 파서 생성기의 산물이었습니다 (OP는 이것이 Xerces 소스 코드라고 언급했습니다). 그리고 파서 생성기 (또는 일반적으로 코드 생성기)는 상태에 대한 완벽한 지식을 가지고 있고 인간이 그것을 이해할 필요가 없기 때문에 생성하는 코드에 자유를 가져다줍니다.
항상 break
새로운 방법 으로 대체 할 수 있습니다 .
두 목록의 공통 요소에 대한 코드 검사를 고려하십시오.
List list1, list2;
boolean foundCommonElement = false;
for (Object el : list1) {
if (list2.contains(el)) {
foundCommonElement = true;
break;
}
}
다음과 같이 다시 작성할 수 있습니다.
boolean haveCommonElement(List list1, List list2) {
for (Object el : list1) {
if (list2.contains(el)) {
return true;
}
}
return false;
}
물론 두 목록 사이의 공통 요소를 확인하려면 list1.retainAll(new HashSet<>(list2))
메서드를 사용 O(n)
하여 O(n)
추가 메모리를 사용하거나 두 목록을 모두에서 정렬 O(n * log n)
한 다음에서 공통 요소를 찾는 것이 O(n)
좋습니다.
This is not like a goto
statement where in you jump the flow control backward. A label merely shows you (the programmer) where the break has occurred. Also, the flow control is transferred to the next statement after the break
.
About using it, I personally think its not of any big use as once you start writing code worth thousands of lines it becomes insignificant. But again, it would depend on the use case.
A cleaner way of expressing the intention could be, at least in my opinion, to put the code fragment that contains the loop into a separate method and simply return
from it.
For example, change this:
someLabel:
for (int j = 0; j < 5; j++)
{
// do something
if ...
break someLabel;
}
into this:
private void Foo() {
for (int j = 0; j < 5; j++)
{
// do something
if ...
return;
}
}
This is also more idiomatic for developers proficient in other languages that might work with your code in the future (or future you).
참고URL : https://stackoverflow.com/questions/14960419/is-using-a-labeled-break-a-good-practice-in-java
'IT Share you' 카테고리의 다른 글
git은 현재 브랜치를 어떻게 가져올 수 있습니까? (0) | 2020.11.07 |
---|---|
Python에 argc 인수가 있습니까? (0) | 2020.11.07 |
Rspec 3 플래시 메시지 테스트 방법 (0) | 2020.11.07 |
집중할 때 Reactjs로 입력의 모든 텍스트를 선택하는 방법은 무엇입니까? (0) | 2020.11.07 |
TypeScript의`keyof`와 유사한`valueof`가 있습니까? (0) | 2020.11.07 |