[java] Java에 조건부 및 조건부 또는 연산자의 복합 할당 버전이없는 이유는 무엇입니까? (&& =, || =)

그래서 논리 값이 이진 사업자, 자바가 &, |, ^, &&||.

여기에서 그들이하는 일을 간단히 요약 해 보겠습니다.

의 경우 &결과 값은 true두 피연산자 값이 모두 다음 과 같은 경우입니다 true. 그렇지 않으면 결과는 false입니다.

의 경우 |결과 값은 false두 피연산자 값이 모두 다음 과 같은 경우입니다 false. 그렇지 않으면 결과는 true입니다.

의 경우 ^결과 값은 true피연산자 값이 다른 경우입니다. 그렇지 않으면 결과는 false입니다.

&&연산자 비슷 &하지만 좌측의 값이 피연산자는 우측 피연산자 만 평가한다 true.

||연산자 비슷 |하지만, 그 좌측의 값이 피연산자는 우측 피연산자 만 평가한다 false.

자, 모두 5 중, 그 중 3, 즉 화합물 할당 버전을 가지고 |=, &=하고 ^=. 내 질문은 분명하다 그래서 왜 자바는 제공하지 않습니다 &&=||=뿐만 아니라? 나는 그보다 내가 필요한 것보다 필요한 것을 발견 &=하고 |=.

그리고 Java가 .NET을 가지고 있기 때문에 “너무 길기 때문에”가 좋은 대답이라고 생각하지 않습니다 >>>=. 이 누락에 대한 더 나은 이유가있을 것입니다.


15.26 할당 연산자 부터 :

12 개의 할당 연산자가 있습니다. […]= *= /= %= += -= <<= >>= >>>= &= ^= |=


&&=||=구현 된 경우 오른쪽을 먼저 평가하지 않는 유일한 연산자라는 의견이 작성 되었습니다. 복합 할당 연산자가 오른쪽을 먼저 평가한다는이 개념은 실수라고 생각합니다.

가입일 15.26.2 화합물 할당 연산자 :

형태의 복합 대입 식을 E1 op= E2동등 E1 = (T)((E1) op (E2))여기서 T의 타입 E1즉 제외 E1한번만 평가된다.

증거로 다음 스 니펫 NullPointerExceptionArrayIndexOutOfBoundsException.

    int[] a = null;
    int[] b = {};
    a[0] += b[-1];



답변

이유

대부분의 개발자에게 이러한 연산자는 다음과 같기 때문에 연산자 &&=Java||= 에서는 사용할 수 없습니다 .

  • 발생하기 쉬운 오류
  • 쓸모없는

&&=

Java가 &&=연산자를 허용하면 해당 코드는 다음과 같습니다.

bool isOk = true; //becomes false when at least a function returns false
isOK &&= f1();
isOK &&= f2(); //we may expect f2() is called whatever the f1() returned value

다음과 동일합니다.

bool isOk = true;
if (isOK) isOk = f1();
if (isOK) isOk = f2(); //f2() is called only when f1() returns true

이 첫 번째 코드는 많은 개발자 가 항상 f1 () 반환 값이 무엇이든 호출 된다고 생각 하기 때문에 오류가 발생 하기 쉽습니다f2() . 반환 할 때만 호출 bool isOk = f1() && f2();되는 곳 과 같습니다 .f2()f1()true

개발자가 f2()f1()반환 할 때만 호출 되기를 원하는 경우 true위의 두 번째 코드는 오류가 덜 발생합니다.

Else &=는 개발자가 f2()항상 호출 되기를 원하기 때문에 충분합니다 .

같은 예이지만 &=

bool isOk = true;
isOK &= f1();
isOK &= f2(); //f2() always called whatever the f1() returned value

또한 JVM은 위의 코드를 다음과 같이 실행해야합니다.

bool isOk = true;
if (!f1())  isOk = false;
if (!f2())  isOk = false;  //f2() always called

비교 &&&결과

연산자의 결과인가 &&&부울 값을 적용 할 때 같은?

다음 Java 코드를 사용하여 확인해 보겠습니다.

public class qalcdo {

    public static void main (String[] args) {
        test (true,  true);
        test (true,  false);
        test (false, false);
        test (false, true);
    }

    private static void test (boolean a, boolean b) {
        System.out.println (counter++ +  ") a=" + a + " and b=" + b);
        System.out.println ("a && b = " + (a && b));
        System.out.println ("a & b = "  + (a & b));
        System.out.println ("======================");
    }

    private static int counter = 1;
}

산출:

1) a=true and b=true
a && b = true
a & b = true
======================
2) a=true and b=false
a && b = false
a & b = false
======================
3) a=false and b=false
a && b = false
a & b = false
======================
4) a=false and b=true
a && b = false
a & b = false
======================

따라서 YES 우리는 대체 할 수 있습니다 &&에 의해 &부울 값 😉

그래서 더 나은 사용하는 &=대신 &&=.

동일 ||=

와 같은 이유 &&=:
연산자 |=||=.

개발자가 반환 f2()할 때 호출되지 않도록 하려면 다음 대안을 조언합니다.f1()true

// here a comment is required to explain that 
// f2() is not called when f1() returns false, and so on...
bool isOk = f1() || f2() || f3() || f4();

또는:

// here the following comments are not required 
// (the code is enough understandable)
bool isOk = false;
if (!isOK) isOk = f1();
if (!isOK) isOk = f2(); //f2() is not called when f1() returns false
if (!isOK) isOk = f3(); //f3() is not called when f1() or f2() return false
if (!isOK) isOk = f4(); //f4() is not called when ...


답변

아마도 뭔가

x = false;
x &&= someComplexExpression();

할당 x하고 평가 해야하는 것처럼 보이지만someComplexExpression() 평가가의 값에 달려 있다는 사실 x은 구문에서 명확하지 않습니다.

또한 Java의 구문은 C를 기반으로하기 때문에 아무도 이러한 연산자를 추가해야하는 절박한 필요성을 느끼지 못했습니다. 어쨌든 if 문을 사용하는 것이 더 나을 것입니다.


답변

Java에서는 이런 방식입니다. C에서는 이런 방식이기 때문입니다.

이제 C에서 왜 그렇게 되는가에 대한 질문은 &와 &&가 다른 연산자가되었을 때 (때로는 B에서 C의 하강 이전에) & = 다양한 연산자를 간과했기 때문입니다.

그러나 내 대답의 두 번째 부분에는이를 뒷받침 할 출처가 없습니다.


답변

Java 구문은 C (또는 적어도 C 계열)를 기반으로하고 C에서 이러한 모든 할당 연산자는 단일 레지스터의 산술 또는 비트 어셈블리 명령어로 컴파일되기 때문입니다. 할당 연산자 버전은 임시를 피하고 초기 비 최적화 컴파일러에서 더 효율적인 코드를 생성했을 수 있습니다. 논리 연산자 (C로 표시됨) 등가물 ( &&=||=)은 단일 어셈블리 명령에 대한 명백한 대응이 없습니다. 일반적으로 테스트 및 분기 명령 시퀀스로 확장됩니다.

흥미롭게도, 루비 같은 언어는 않습니다 및 && = || 있습니다.

편집 : Java와 C의 용어가 다릅니다.


답변

Java의 원래 목표 중 하나는 “단순하고 객체 지향적이며 친숙한”것이 었습니다. 이 경우에 적용하면 & =는 익숙합니다 (C, C ++는이 두 가지를 알고있는 사람에게 친숙 함을 의미하며이 컨텍스트에서 익숙 함을 의미합니다).

&& =는 익숙하지 않을 것이며, 언어 설계자들이 언어에 추가 할 수있는 모든 연산자를 생각하지 않기 때문에 간단하지 않을 것입니다. 따라서 추가 연산자가 덜 간단합니다.


답변

부울 변수의 경우 && 및 || & 및 | 동안 단락 평가를 사용합니다. 그렇지 않으면 && = 및 || =도 단락 평가를 사용할 것으로 예상됩니다. 이에 대한 좋은 사용 사례가 있습니다. 특히 루프를 반복하는 경우 빠르고 효율적이며 간결해야합니다.

쓰는 대신

foreach(item in coll)
{
   bVal = bVal || fn(item); // not so elegant
}

나는 쓰고 싶다

foreach(item in coll)
{
  bVal ||= fn(item);    // elegant
}

bVal이 참이면 나머지 반복에 대해 fn ()이 호출되지 않습니다.


답변

&‘와 ‘ &&‘는 같지 않습니다. ‘ &&‘는 첫 번째 피연산자가 거짓이면 수행하지 않는 바로 가기 연산이며 ‘ &‘는 어쨌든 수행합니다 (숫자 및 부울 모두에서 작동).

나는 존재하는 것이 더 합리적이라는 데 동의하지만 그것이 존재하지 않아도 그렇게 나쁘지는 않습니다. C가 가지고 있지 않기 때문에 거기에 없었던 것 같아요.

정말 이유를 생각할 수 없습니다.