[java] Java의 바로 가기 “또는 할당”(| =) 연산자

Java에서 수행 할 긴 비교 세트가 있으며 그중 하나 이상이 사실로 나오는지 알고 싶습니다. 비교 문자열이 길고 읽기 어려웠 기 때문에 가독성을 위해 분리했고 자동으로 . |=대신 단축키 연산자를 사용했습니다 negativeValue = negativeValue || boolean.

boolean negativeValue = false;
negativeValue |= (defaultStock < 0);
negativeValue |= (defaultWholesale < 0);
negativeValue |= (defaultRetail < 0);
negativeValue |= (defaultDelivery < 0);

negativeValuedefault <something> 값이 음수이면 true가 될 것으로 예상 합니다. 이것이 유효합니까? 내가 기대하는대로 작동할까요? Sun의 사이트 또는 stackoverflow에서 언급 된 것을 볼 수 없었지만 Eclipse에는 문제가없는 것 같고 코드가 컴파일되고 실행됩니다.


마찬가지로 여러 논리적 교차를 수행하려면 &=대신 &&?를 사용할 수 있습니다 .



답변

|=복합 할당 연산자이다 ( JLS 15.26.2 부울 논리 연산자) |( JLS 15.22.2 ); conditional-or ||( JLS 15.24 ) 와 혼동하지 마십시오 . 또한 거기 &=^=논리적 부울의 화합물 할당 버전에 대응 &하고 ^, 각각.

즉,의 boolean b1, b2경우이 두 가지는 동일합니다.

 b1 |= b2;
 b1 = b1 | b2;

논리 연산자의 차이 ( &|그 조건 대응 (비교) &&과는 ||) 전자는 “단락”을하지 않는 것입니다; 후자는합니다. 그건:

  • &그리고 | 항상 두 피연산자를 평가
  • &&그리고 ||우측 피연산자를 평가 조건부 ; 오른쪽 피연산자는 해당 값이 이진 연산의 결과에 영향을 미칠 수있는 경우에만 평가됩니다. 즉, 다음과 같은 경우 오른쪽 피연산자가 평가되지 않습니다.
    • 의 왼쪽 피연산자는 다음과 같이 &&평가됩니다.false
      • (오른쪽 피연산자가 무엇으로 평가 되든 전체 표현식이이므로 false)
    • 의 왼쪽 피연산자는 다음과 같이 ||평가됩니다.true
      • (오른쪽 피연산자가 무엇으로 평가 되든 전체 표현식이이므로 true)

그래서 원래의 질문으로 돌아가서, 예, 그 구조는 유효하며 |==||에 대한 바로 가기는 아니지만 원하는 것을 계산합니다. |=사용 하는 연산자 의 오른쪽 은 간단한 정수 비교 연산이므로 |단락되지 않는 사실 은 중요하지 않습니다.

단락이 필요하거나 필요한 경우가 있지만 시나리오는 그중 하나가 아닙니다.

다른 언어와 달리 Java에는 &&=||=. 이것은 왜 Java에 conditional-and and conditional-or 연산자의 복합 할당 버전이 없습니까? 라는 질문에서 논의되었습니다 . (&& =, || =) .


답변

그런 식으로 “단축”(또는 단락) 연산자가 아닙니다 || &&는 (LHS를 기반으로 한 결과를 이미 알고있는 경우 RHS를 평가하지 않는다는 점에서) 작업 측면에서 원하는 작업을 수행 합니다.

차이점의 예로서이 코드 text는 null이면 괜찮습니다 .

boolean nullOrEmpty = text == null || text.equals("")

그러나 이것은 :

boolean nullOrEmpty = false;
nullOrEmpty |= text == null;
nullOrEmpty |= text.equals(""); // Throws exception if text is null

(분명히 당신은 "".equals(text)그 특정한 경우에 대해 할 수 있습니다 -나는 단지 원리를 보여주기위한 것입니다.)


답변

당신은 단지 하나의 진술을 가질 수 있습니다. 여러 줄로 표현하면 샘플 코드와 거의 똑같이 읽습니다.

boolean negativeValue
    = defaultStock < 0
    | defaultWholesale < 0
    | defaultRetail < 0
    | defaultDelivery < 0;

가장 간단한 표현식의 경우 using 이 비교를 피하더라도 암시 적으로 분기를 사용하는 것을 의미하며 훨씬 더 많은 비용이들 수 있기 때문에 사용 |이 더 빠를 ||수 있습니다.


답변

그것은 당신의 문제에 과잉 일 수 있지만, Guava 라이브러리는 Predicates와 함께 멋진 구문을 가지고 있으며 or / and Predicates에 대한 단락 평가를 수행 합니다.

기본적으로 비교는 객체로 변환되고 컬렉션으로 패키징 된 다음 반복됩니다. 또는 술어의 경우 첫 번째 실제 적중이 반복에서 리턴되고 and의 경우 그 반대의 경우도 마찬가지입니다.


답변

가독성에 관한 경우 테스트 논리에서 테스트 데이터를 분리한다는 개념이 있습니다. 코드 샘플 :

// declare data
DataType [] dataToTest = new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
}

// define logic
boolean checkIfAnyNegative(DataType [] data) {
    boolean negativeValue = false;
    int i = 0;
    while (!negativeValue && i < data.length) {
        negativeValue = data[i++] < 0;
    }
    return negativeValue;
}

코드가 더 장황하고 자명 해 보입니다. 다음과 같이 메서드 호출에서 배열을 만들 수도 있습니다.

checkIfAnyNegative(new DataType[] {
    defaultStock,
    defaultWholesale,
    defaultRetail,
    defaultDelivery
});

‘비교 문자열’보다 읽기 쉽고 단락 (배열 할당 및 메서드 호출 비용)이라는 성능 이점도 있습니다.

편집 :
varargs 매개 변수를 사용하면 더 많은 가독성을 얻을 수 있습니다.

메소드 서명은 다음과 같습니다.

boolean checkIfAnyNegative(DataType ... data)

그리고 호출은 다음과 같이 보일 수 있습니다.

checkIfAnyNegative( defaultStock, defaultWholesale, defaultRetail, defaultDelivery );


답변

오래된 게시물이지만 초보자에게 다른 관점을 제공하기 위해 예를 들어보고 싶습니다.

비슷한 복합 연산자의 가장 일반적인 사용 사례는 +=. 나는 우리 모두가 다음과 같이 썼다고 확신합니다.

int a = 10;   // a = 10
a += 5;   // a = 15

이것의 요점은 무엇입니까? 요점은 상용구를 피하고 반복적 인 코드를 제거하는 것이 었습니다.

따라서 다음 줄은 b1동일한 줄에 변수를 두 번 입력하는 것을 피하면서 정확히 동일합니다.

b1 |= b2;


답변

List<Integer> params = Arrays.asList (defaultStock, defaultWholesale,
                                       defaultRetail, defaultDelivery);
int minParam = Collections.min (params);
negativeValue = minParam < 0;