Por que essa instrução if, com uma atribuição e verificação de igualdade, é avaliada como falsa?

105

Como uma instrução Java if funciona quando tem uma atribuição e uma verificação de igualdade OR-d juntas ??

public static void test() {
    boolean test1 = true; 
    if (test1 = false || test1 == false) {
        System.out.println("TRUE");
    } else {
        System.out.println("FALSE");
    }       
}

Por que esta impressão é FALSA?

RoHaN
fonte
1
Execute e verifique. Veja qual valor booleano é impresso se você atribuir falso e se você atribuir verdadeiro. Em seguida, leia sobre como funciona o OR.
Pratik
2
Gostaria de dizer que este código no modo de depuração dá valor TRUE e no modo Running dá valor FALSE ... Por que é assim ??? ... (coloquei meu ponto de interrupção na condição if) ...
CoderNeji
test1=false, test1==falseé false, false || falseé o false or falseque é false.
Jared Burrows,
Eu sei que você não estava pedindo conselhos, mas como as respostas abaixo identificam um problema de precedência, aqui estão algumas práticas que me ajudaram a evitar problemas (quando eu as mantenho): (1) sempre use parênteses quando não 100% certeza da precedência ou para facilitar a legibilidade para ajudar outros desenvolvedores. Não assuma que os outros se lembrarão das regras de precedência para todos os operadores (2) atribuições if devem geralmente ser evitadas para reduzir a confusão, exceto para condições if muito simples. Existem algumas exceções comuns (especialmente com verificações simples de E / S, rede, etc.). Apenas meus dois centavos.
Rimsky
porquetest1 = true
jono

Respostas:

189

A expressão não é analisada da maneira que você pensa. Não é

(test1=false) || (test1 == false)

nesse caso, o resultado teria sido true, mas

test1 = (false || test1 == false)

O valor da false || test1 == falseexpressão é calculado primeiro, e é false, porque test1está definido para trueentrar no cálculo.

O motivo pelo qual ele é analisado dessa maneira é que a precedência do ||é menor do que a do ==operador, mas maior do que a precedência do operador de atribuição =.

dasblinkenlight
fonte
2
+1 @RohanFernando, observe também que se você adicionar colchetes ao redor da atribuição da seguinte forma: ((test1 = false) || test1 == false)o valor geral seria true.
Arnon Zilca,
1
Por favor, escreva a razão pela qual a análise acontece assim ... É por causa da ordem de prioridade dos operadores?
kondu
3
@kondu Essa é uma pergunta de acompanhamento justa, editei para adicionar um link para uma tabela de precedência, que mostra que ==está acima ||, mas =está abaixo ||.
dasblinkenlight
O parágrafo final é enganoso, no sentido de que para entender por que a segunda análise é escolhida em vez da primeira, basta conhecer a regra (facilmente lembrada) de que a atribuição tem precedência inferior a qualquer operador de não atribuição (aqui ||). A precedência relativa de ||e ==só é relevante para mostrar que a análise não é como em test1 = ((false || test1) == false), o que eu não acho que alguém esperaria razoavelmente (a propósito que a precedência relativa, ou mais geralmente isso ||, &&tem precedência inferior às relações, também é fácil de lembre-se, uma vez que usado o tempo todo).
Marc van Leeuwen
1
@MarcvanLeeuwen A precedência relativa de ||e ==vs ||e =explica por que isso se comporta de maneira diferente do caso (comum) de a == b || c == d.
Aaron Dufour
83

Esta é uma questão de precedência, basicamente. Você está assumindo que seu código é equivalente a:

if ((test1 = false) || (test1 == false))

... Mas isso não. Na verdade, é equivalente a:

if (test1 = (false || test1 == false))

... que é equivalente a:

if (test1 = (false || false))

(porque test1é truepara começar)

... que é equivalente a:

if (test1 = false)

que atribui o valor falsea test1, com o resultado da expressão sendo false.

Consulte o tutorial Java sobre operadores para obter uma tabela útil de precedência de operadores.

Jon Skeet
fonte
2

por favor, dê uma olhada na precedência de operadores

A expressão test1 = false || test1 == falseserá avaliada na etapa seguinte.

ETAPA: 1- test1 = false || test1 == false // a precedência de ==é mais alta

ETAPA: 2- test1 = false || false // Operador ||tem maior precedência

ETAPA 3- test1 = false

PASSO 4- false

Já que o valor booleano da expressão torna-se falso. Então, a instrução está sendo executada.


fonte
-11

(test1 = false || test1 == false)retorna falso, porque ambos são falsos. (test1 = false || test1 == true)isso é verdade porque um deles é verdadeiro

Den
fonte
1
Completamente errado. Por que você responderia com essas informações incorretas dias depois que a pergunta recebeu duas respostas de alta qualidade que descrevem o que acontece?
l4mpi
5
Duas respostas de tão baixa qualidade não merecem comentários escritos individualmente. Você percebe que sua resposta é um absurdo, certo? Se não, leia com atenção as duas respostas de Jon e pisque a luz.
l4mpi