Como é chamado o operador Java?: E o que ele faz?


161

Trabalho com Java há alguns anos, mas até recentemente não encontrei essa construção:

int count = isHere ? getHereCount(index) : getAwayCount(index);

Esta é provavelmente uma pergunta muito simples, mas alguém pode explicar isso? Como eu o leio? Tenho certeza de que sei como isso funciona.

  • se isHerefor verdade, getHereCount()é chamado,
  • se isHerefor falso getAwayCount()é chamado.

Corrigir? Como se chama essa construção?


2
Consulte também stackoverflow.com/questions/795286/what-does-do-in-c para a versão C ++ desta pergunta (feita ontem, na verdade).
Michael Myers

2
Lembre-se de que o mundo C / C ++ / Java é bastante dividido entre as pessoas que a consideram feia e confusa e a evitarão como uma praga, e as pessoas que pensam que você não pode realmente afirmar conhecer C, C ++ ou Java se você não pode reconhecê-lo e usá-lo sem parar para pensar.
21119 Paul Tomblin

3
Geralmente, é considerado uma má forma no Java usá-lo além dos casos mais claros e simples. Se você estiver aninhando-os, estará fora. Por outro lado, na cultura C, em que o código rápido e inteligente é avaliado acima da clareza, é considerado aceitável.
218 Yishai

17
answer_to_question = (reconhecer_operador)? (social_acceptance): (condescending_finger_wag)
Dan

Você pode consultar este recurso para obter mais informações.
Shiva

Respostas:


189

Sim, é uma forma abreviada de

int count;
if (isHere)
    count = getHereCount(index);
else
    count = getAwayCount(index);

É chamado de operador condicional . Muitas pessoas (erroneamente) o chamam de operador ternário , porque é o único operador ternário (três argumentos) em Java, C, C ++ e provavelmente muitas outras linguagens. Mas, teoricamente, poderia haver outro operador ternário, enquanto que só pode haver um operador condicional .

O nome oficial é fornecido na Java Language Specification :

§15.25 Operador condicional? :

O operador condicional ? :usa o valor booleano de uma expressão para decidir qual das outras duas expressões deve ser avaliada.

Observe que os dois ramos devem levar a métodos com valores de retorno:

É um erro em tempo de compilação para a segunda ou terceira expressão do operando ser uma invocação de um método nulo.

De fato, pela gramática das declarações de expressão ( §14.8 ), não é permitido que uma expressão condicional apareça em qualquer contexto em que uma invocação de um método nulo possa aparecer.

Portanto, se doSomething()e doSomethingElse()são métodos nulos, você não pode compactar isso:

if (someBool)
    doSomething();
else
    doSomethingElse();

nisso:

someBool ? doSomething() : doSomethingElse();

Palavras simples:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 

Eu não entendo o que está fazendo de errado. Eu acredito em você e tudo. Parece-me o mesmo que o original. É porque eles apenas chamam outra função que pode ou não retornar um valor e permitir que o próximo código seja executado?
319 johnny

8
Estou assumindo que doSomething () e doSomethingElse () são métodos nulos. O que esse último bit da especificação diz é que o operador ternário deve retornar um valor, para que nenhum dos operandos possa ser um método nulo.
Michael Myers

Diz um pouco mais que isso. Diz que o operador condicional não é permitido onde um método nulo PODE aparecer. Portanto, por exemplo, as seguintes instruções: VALID: String x = (false)? "X": "Y"; NÃO É VÁLIDO: (falso)? "X": "Y";
precisa saber é o seguinte

4
Não é errado chamá-lo de "operador ternário", assim como não é errado (em 2016) referir-se a Obama como "o presidente", mesmo que seja possível que haja outros presidentes no futuro.
Dawood ibn Kareem

2
@DawoodibnKareem Acho que Michael foi incluído deliberadamente thena itálica de the ternary operator, e é isso que ele quer dizer com erro, não com ternary operatorerro. O operador ternário implica que, como Michael diz, é o único, que por sua vez poderia levar a supor não pode haver outros operadores ternários, que é o que Michael está dizendo é errônea, e eu concordo, ele iria ser uma suposição errônea.
Ghoti and Chips

32

Outros responderam isso em extensão razoável, mas geralmente com o nome "operador ternário".

Sendo o pedante que sou, gostaria de deixar claro que o nome do operador é o operador condicional ou "operador condicional?:". É um operador ternário (na medida em que possui três operandos) e é o único operador ternário em Java no momento.

No entanto, a especificação é bastante clara de que seu nome é operador condicional ou "operador condicional?:" Para ser absolutamente inequívoco. Eu acho que é mais claro chamá-lo com esse nome, pois indica o comportamento do operador até certo ponto (avaliando uma condição) e não apenas quantos operandos ele possui.


3
Esta resposta está tecnicamente correta. No entanto, como existe apenas um operador ternário, você costuma vê-lo referido como operador ternário. Mesmo que esse nome não transmita o significado completo do operador, é um nome que ficou preso. Se você mencionar o nome "operador ternário", os programadores sabem do que você está falando. As especificações mencionadas também se referem a esse operador como o "Condicional ternário", que parece mais informativo. java.sun.com/docs/books/jls/third_edition/html/…
Gary

17
Só acho que vale a pena chamar algo pelo nome definido. Em particular, se o Java conseguir outro operador ternário, as pessoas que usarem o termo "operador condicional" ainda serão corretas e inequívocas - ao contrário das que acabam de dizer "operador ternário". Sim, a frase "operador ternário" ficou presa - minha resposta faz parte de um esforço para "desparafusá-la", assim como tento corrigir a afirmação de que "objetos são passados ​​por referência".
31909 Jon Skeet

1
Posso direcioná-lo para esta página da Oracle, que fala de três "operadores condicionais", mas apenas de um "operador ternário"? Se você quiser deixar claro qual operador você quer dizer, provavelmente é melhor usar o nome que a maioria das pessoas usa. (Sim, eu sei que estou aparecendo na festa no momento em que o anfitrião lava a última louça).
Dawood ibn Kareem

@ DavidWallace: Usar "operador condicional?:" É melhor, IMO - irá editar para esclarecer isso. Mas acho que vale a pena convencer as pessoas a usar o nome real do operador, em vez de focar em um aspecto dele (quantos operandos ele possui) que não tem nada a ver com seu comportamento. (Também não é incomum que os tutoriais sejam menos precisos que a especificação, que chama &&o operador condicional - e o operador ||condicional - ou, mas usa apenas "o operador condicional" para ?:.)
Jon Skeet,

Eu não sei. Se alguém me disser "operador condicional", não terei certeza do que eles significam. De onde eu venho (do outro lado do mundo), as pessoas simplesmente não chamam isso. Se eles dizem "operador ternário" ou "operador de gancho", então eu entendo. Admiro sua ambição, querendo mudar a maneira como as pessoas falam. Se alguém pode fazer isso, é você. Mas não tenho muita esperança nem vejo muito sentido.
Dawood ibn Kareem

17

De acordo com a Sun Java Specification , é chamado de Operador Condicional. Veja a seção 15.25. Você está certo quanto ao que faz.

O operador condicional? : usa o valor booleano de uma expressão para decidir qual das outras duas expressões deve ser avaliada.

O operador condicional é sintaticamente associativo à direita (agrupa da direita para a esquerda), de modo que a? B: c? D: e? F: g significa o mesmo que a? B: (c? D: (e? F : g)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

O operador condicional possui três expressões de operando; ? aparece entre a primeira e a segunda expressões e: aparece entre a segunda e a terceira expressões.

A primeira expressão deve ser do tipo booleano ou booleano, ou ocorre um erro em tempo de compilação.


5
int count = isHere ? getHereCount(index) : getAwayCount(index);

significa :

if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}

5

Não exatamente correto, para ser preciso:

  1. se isHere for true, o resultado de getHereCount () será retornado
  2. otheriwse o resultado de getAwayCount () é retornado

Que "retornou" é muito importante. Isso significa que os métodos devem retornar um valor e esse valor deve ser atribuído em algum lugar.

Além disso, não é exatamente sintaticamente equivalente à versão if-else. Por exemplo:

String str1,str2,str3,str4;
boolean check;
//...
return str1 + (check ? str2 : str3) + str4;

Se codificado com if-else sempre resultará em mais bytecode.


Acredito que javac tem liberdade para gerar o mesmo bytecode. Embora você esteja certo de que existem casos de canto obscuros onde eles não são equivalentes.
Tom Hawtin - tackline

Sim, claro. Para mim, o verdadeiro mérito do operador condicional é o exemplo que eu dei. As alternativas são: // suspiro !! Temp da string = str1; if (verifique) temp + = str2; senão temp + = str3; temp + = str4; temperatura de retorno; ou codificar manualmente a operação de acréscimo de StringBuilder. O primeiro sofre um sério problema de eficiência, enquanto o segundo é muito detalhado e é um esforço meticuloso, sem muito ganho.
RichN

4

Ternário, condicional; tomate, tomate. O que é realmente valioso é a inicialização variável. Se (como eu) você gosta de inicializar variáveis ​​onde elas são definidas, o operador ternário condicional (pois são os dois) permite que você faça isso nos casos em que há condicionalidade sobre seu valor. Particularmente notável nos campos finais, mas útil em outros lugares também.

por exemplo:

public class Foo {
    final double    value;

    public Foo(boolean positive, double value) {
        this.value = positive ? value : -value;
    }
}

Sem esse operador - por qualquer nome - você teria que tornar o campo não final ou escrever uma função simplesmente para inicializá-lo. Na verdade, isso não está certo - ele ainda pode ser inicializado usando if / else, pelo menos em Java. Mas acho esse limpador.



3

Esse construto é chamado Operador Ternário de Ciência da Computação e técnicas de Programação.
E a Wikipedia sugere a seguinte explicação:

Na ciência da computação, um operador ternário (às vezes chamado incorretamente de operador terciário) é um operador que recebe três argumentos. Os argumentos e o resultado podem ser de tipos diferentes. Muitas linguagens de programação que usam sintaxe do tipo C apresentam um operador ternário,?:, Que define uma expressão condicional.

Não apenas em Java, esta sintaxe também está disponível no PHP, Objective-C.

No link a seguir , fornece a seguinte explicação, que é muito boa de entender:

Um operador ternário é uma operação que opera em 3 entradas. É um atalho para uma instrução if-else e também é conhecido como um operador condicional.

No Perl / PHP, ele funciona como:
boolean_condition ? true_value : false_value

Em C / C ++, ele funciona como:
logical expression ? action for true : action for false

Isso pode ser legível para algumas condições lógicas que não são muito complexas, caso contrário, é melhor usar o bloco If-Else com a combinação pretendida de lógica condicional.

Podemos simplificar os blocos If-Else com este operador Ternary para uma linha de instrução de código.
Por exemplo:

if ( car.isStarted() ) {
     car.goForward();
} else {
     car.startTheEngine();
}

Pode ser igual ao seguinte:

( car.isStarted() ) ? car.goForward() : car.startTheEngine();

Portanto, se nos referirmos à sua declaração:

int count = isHere ? getHereCount(index) : getAwayCount(index);

Na verdade, é o equivalente a 100% do seguinte bloco If-Else :

int count;
if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}

É isso aí!
Espero que isso tenha sido útil para alguém!
Felicidades!



2

Seu operador ternário (? :)

The ternary operator is an operator that takes three arguments. The first 
argument is a comparison argument, the second is the result upon a true 
comparison, and the third is the result upon a false comparison.

1

Você pode estar interessado em uma proposta para alguns novos operadores semelhantes ao operador condicional. Os operadores com segurança nula habilitarão códigos como este:

String s = mayBeNull?.toString() ?: "null";

Seria especialmente conveniente onde ocorre o desembaraço automático.

Integer ival = ...;  // may be null
int i = ival ?: -1;  // no NPE from unboxing

Foi selecionado para uma análise mais aprofundada no "Project Coin" do JDK 7.


Esse operador não é um dos meus favoritos do Project Coin. Utilidade limitada, não é intuitiva de ler e é simplesmente feia como todos. Talvez isso crescesse em mim, no entanto.
Michael Myers

Também não sou um grande fã. É uma proposta de Neal Gafter, e ele tende a ver as coisas de maneira muito diferente do seu programador Java comum, que tende a ver as coisas de maneira diferente do seu ser humano comum. Os únicos lugares em que gostaria de obter uma pequena ajuda com valores nulos são em um loop foreach, testando se o iterável é nulo e com o unboxing automático.
28610 erickson

IIRC <Neal não a propôs. Ele apenas o usou como um exemplo simples de como escrever uma proposta. Mais detalhes sobre o arquivo da lista de endereçamento de moedas do projeto.
Tom Hawtin - tackline

Acabei de ler a introdução da proposta e você está certo. É Stephen Colebourne, da Joda, e "não há Java 7".
22699

1

Na verdade, pode levar mais de 3 argumentos. Por exemplo, se queremos verificar se um número é positivo, negativo ou zero, podemos fazer o seguinte:

String m= num > 0 ? "is a POSITIVE NUMBER.": num < 0 ?"is a NEGATIVE NUMBER." :"IT's ZERO.";

o que é melhor do que usar if, else if, else.


0

É o operador condicional e é mais do que apenas uma maneira concisa de escrever declarações if.

Como é uma expressão que retorna um valor, pode ser usada como parte de outras expressões.


0

Sim você está correto. ?: normalmente é chamado de "operador condicional ternário", geralmente chamado de "operador ternário". É uma versão abreviada do padrão if / else condicional.

Operador condicional ternário


0

Eu realmente gosto deste operador, mas o leitor deve ser levado em consideração.

Você sempre precisa equilibrar a compactação do código com o tempo gasto na leitura e com algumas falhas bastante graves.

Primeiro de tudo, existe o caso do Asker Original. Ele passou uma hora postando sobre isso e lendo as respostas. Quanto tempo levaria o autor a escrever cada um?: Como um se / então ao longo de toda a sua vida. Nem uma hora para ter certeza.

Em segundo lugar, em idiomas do tipo C, você tem o hábito de simplesmente saber que os condicionais são a primeira coisa na linha. Percebi isso quando eu estava usando Ruby e me deparei com linhas como:

callMethodWhatever(Long + Expression + with + syntax) if conditional

Se eu fosse usuário Ruby há muito tempo, provavelmente não teria problemas com essa linha, mas vindo de C, quando você vê "callMethodWhatever" como a primeira coisa na linha, espera que seja executado. O?: É menos enigmático, mas ainda incomum o suficiente para deixar um leitor de fora.

A vantagem, no entanto, é uma sensação muito legal em sua barriga quando você pode escrever uma declaração if de 3 linhas no espaço de 1 das linhas. Não posso negar isso :) Mas, honestamente, não é necessariamente mais legível por 90% das pessoas por aí simplesmente por causa de sua raridade.

Quando é realmente uma atribuição baseada em um valor booleano e em valores, não tenho problema com isso, mas pode ser facilmente abusada.


0

Expressões condicionais estão em um estilo completamente diferente, sem explícito se na instrução.

A sintaxe é: expressão booleana? expressão1: expressão2;

O resultado dessa expressão condicional é

expression1 se expressão booleana for verdadeira;

caso contrário, o resultado será expressão2.

Suponha que você queira atribuir o número maior de variáveis ​​num1 e num2 a max. Você pode simplesmente escrever uma declaração usando a expressão condicional: max = (num1> num2)? num1: num2;

Nota: Os símbolos? e: aparecem juntos em uma expressão condicional. Eles formam um operador condicional e também chamado de operador ternário porque ele usa três operandos. É o único operador ternário em Java.

citado em: Introdução à Programação Java 10ª edição por Y. Daniel Liang página 126 - 127

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.