¿Cómo se llama el operador Java?: ¿Y qué hace?

161

He estado trabajando con Java un par de años, pero hasta hace poco no me había encontrado con esta construcción:

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

Esta es probablemente una pregunta muy simple, pero ¿alguien puede explicarla? ¿Cómo lo leo? Estoy bastante seguro de saber cómo funciona.

  • si isHerees verdad, getHereCount()se llama
  • si isHerees falso getAwayCount()se llama

¿Correcto? ¿Cómo se llama esta construcción?

cuerdas principales
fuente
2
Consulte también stackoverflow.com/questions/795286/what-does-do-in-c para la versión C ++ de esta pregunta (de hecho, se hizo ayer).
Michael Myers
2
Tenga en cuenta que el mundo C / C ++ / Java está dividido de manera bastante equitativa entre las personas que piensan que es feo y confuso y lo evitarán como la peste, y las personas que piensan que realmente no pueden afirmar que conocen C, C ++ o Java si no puedo reconocerlo y usarlo sin hacer una pausa para pensar.
Paul Tomblin
3
Generalmente se considera mala forma en Java usarla más allá de los casos más claros y simples. Si te encuentras anidándolos, estás lejos. Por otro lado, en la cultura C, donde el código rápido e inteligente se valora por encima de la claridad, se considera aceptable.
Yishai
17
answer_to_question = (reconoce_operador)? (social_acceptance): (condescending_finger_wag)
Dan
Puede consultar este recurso para obtener más información.
Shiva

Respuestas:

189

Sí, es una forma abreviada de

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

Se llama el operador condicional . Muchas personas (erróneamente) lo llaman el operador ternario , porque es el único operador ternario (tres argumentos) en Java, C, C ++ y probablemente muchos otros lenguajes. Pero teóricamente podría haber otro operador ternario, mientras que solo puede haber un operador condicional .

El nombre oficial se proporciona en la Especificación del lenguaje Java :

§15.25 ¿Operador condicional? :

El operador condicional ? :usa el valor booleano de una expresión para decidir cuál de las otras dos expresiones debe evaluarse.

Tenga en cuenta que ambas ramas deben conducir a métodos con valores de retorno:

Es un error en tiempo de compilación que la segunda o la tercera expresión de operando sea una invocación de un método nulo.

De hecho, según la gramática de las declaraciones de expresión ( §14.8 ), no está permitido que aparezca una expresión condicional en ningún contexto donde pueda aparecer una invocación de un método nulo.

Entonces, si doSomething()y doSomethingElse()son métodos nulos, no puede comprimir esto:

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

dentro de esto:

someBool ? doSomething() : doSomethingElse();

Palabras simples:

booleanCondition ? executeThisPartIfBooleanConditionIsTrue : executeThisPartIfBooleanConditionIsFalse 
Michael Myers
fuente
No entiendo qué hace el inferior que está mal. Te creo a ti y a todos. A mí me parece igual que el original. ¿Es porque simplemente llaman a otra función que puede o no devolver un valor y permitir que se ejecute el siguiente código?
Johnny
8
Supongo que doSomething () y doSomethingElse () son métodos nulos. Lo que dice el último bit de la especificación es que el operador ternario debe devolver un valor, por lo que ninguno de los operandos puede ser métodos nulos.
Michael Myers
Dice un poco más que eso. Dice que el operador condicional no está permitido donde PODRÍA aparecer un método vacío. Entonces, por ejemplo, las siguientes declaraciones: VALID: String x = (false)? "X": "Y"; NO VÁLIDO: (falso)? "X": "Y";
kenj0418
44
No es erróneo llamarlo "operador ternario", así como no es erróneo (en 2016) referirse a Obama como "el Presidente", aunque es posible que haya otros presidentes en el futuro.
Dawood ibn Kareem
2
@DawoodibnKareem Creo que Michael lo incluyó deliberadamente theen la cursiva de the ternary operator, y eso es lo que quiere decir que es erróneo, no ternary operatores erróneo. El operador ternario implica que, como dice Michael, es el único, que a su vez podría llevar a suponer que no puede haber otros operadores ternarios, que es lo que Michael está diciendo es errónea, y yo estaría de acuerdo, que podría ser Una suposición errónea.
Ghoti y Chips
32

Otros han respondido esto en un grado razonable, pero a menudo con el nombre de "operador ternario".

Siendo el pedante que soy, me gustaría dejar en claro que el nombre del operador es el operador condicional o "operador condicional?:". Es un operador ternario (ya que tiene tres operandos) y por el momento es el único operador ternario en Java.

Sin embargo, la especificación es bastante clara de que su nombre es el operador condicional o "operador condicional?:" Para ser absolutamente inequívoco. Creo que es más claro llamarlo por ese nombre, ya que indica el comportamiento del operador hasta cierto punto (evaluar una condición) en lugar de cuántos operandos tiene.

Jon Skeet
fuente
3
Esta respuesta es técnicamente correcta. Sin embargo, dado que solo hay un operador ternario, a menudo se lo conoce como el operador ternario. Aunque este nombre no transmite el significado completo del operador, es un nombre que se ha pegado. Si menciona el nombre "operador ternario", los programadores saben de lo que está hablando. La especificación que menciona también se refiere a este operador como el "Condicional ternario" que parece más informativo. java.sun.com/docs/books/jls/third_edition/html/…
Gary
17
Solo creo que vale la pena llamar a algo por su nombre definido. En particular, si Java alguna vez obtiene otro operador ternario, las personas que usan el término "operador condicional" seguirán siendo correctas e inequívocas, a diferencia de las que simplemente dicen "operador ternario". Sí, la frase "operador ternario" se ha pegado: mi respuesta es parte de un esfuerzo por "despegarla", así como trato de corregir la afirmación de que "los objetos se pasan por referencia".
Jon Skeet
1
¿Puedo dirigirlo a esta página desde Oracle que habla de tres "operadores condicionales" pero solo un "operador ternario"? Si desea dejar en claro a qué operador se refiere, probablemente sea mejor usar el nombre que usa la mayoría de las personas. (Sí, sé que voy a aparecer en la fiesta justo cuando el anfitrión está lavando los últimos platos).
Dawood ibn Kareem
@DavidWallace: Usar "operador condicional?:" Es mejor, IMO - editará para aclarar eso. Pero sí creo que vale la pena persuadir a las personas para que usen el nombre real del operador en lugar de centrarse en un aspecto (cuántos operandos tiene) que no tiene nada que ver con su comportamiento. (Tampoco es raro que los tutoriales sean menos precisos que la especificación, que llama &&al condicional-y operador, y ||al condicional-u operador, pero usa solo "el operador condicional" para ?:.
Jon Skeet
No lo sé. Si alguien me dice "operador condicional", no estaré seguro de lo que significan. De donde vengo (el extremo opuesto del mundo) la gente simplemente no lo llama así. Si dicen "operador ternario" u "operador de gancho", entonces entiendo. Admiro tu ambición, queriendo cambiar la forma en que la gente habla. Si alguien puede hacerlo, eres tú. Pero no tengo mucha esperanza ni veo mucho punto.
Dawood ibn Kareem
17

De acuerdo con la especificación Sun Java , se llama Operador condicional. Ver sección 15.25. Tienes razón en cuanto a lo que hace.

El operador condicional? : utiliza el valor booleano de una expresión para decidir cuál de las otras dos expresiones debe evaluarse.

El operador condicional es sintácticamente asociativo a la derecha (agrupa de derecha a izquierda), de modo que a? B: c? D: e? F: g significa lo mismo que a? B: (c? D: (e? F :gramo)).

ConditionalExpression:
        ConditionalOrExpression
        ConditionalOrExpression ? Expression : ConditionalExpression

El operador condicional tiene tres expresiones de operando; ? aparece entre la primera y la segunda expresión, y: aparece entre la segunda y la tercera expresión.

La primera expresión debe ser de tipo booleano o booleano, o se produce un error en tiempo de compilación.

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

significa:

if (isHere) {
    count = getHereCount(index);
} else {
    count = getAwayCount(index);
}
Romain Linsolas
fuente
5

No es exactamente correcto, para ser precisos:

  1. si isHere es cierto, el resultado es de getHereCount () devuelve
  2. otheriwse el resultado de getAwayCount () es devuelto

Ese "regreso" es muy importante. Significa que los métodos deben devolver un valor y ese valor debe asignarse en alguna parte.

Además, no es exactamente equivalente sintácticamente a la versión if-else. Por ejemplo:

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

Si se codifica con if-else siempre dará como resultado más bytecode.

RichN
fuente
Creo que Java tiene la libertad de generar el mismo código de bytes. Aunque tiene razón, hay casos de esquina oscuros donde no son equivalentes.
Tom Hawtin - tackline
Sí, por supuesto. Para mí, el verdadero mérito del operador condicional es el ejemplo que he dado. Las alternativas son: // ¡jadeo! Cadena temp = str1; if (marcar) temp + = str2; sino temp + = str3; temp + = str4; temperatura de retorno; o codificar manualmente la operación de agregar StringBuilder. El primero sufre un grave problema de eficiencia, mientras que el segundo es demasiado detallado y es un esfuerzo minucioso sin mucha ganancia.
RichN
4

Ternario, condicional; tomate, tomateh. Lo que es realmente valioso es la inicialización variable. Si (como a mí) le gusta inicializar las variables donde están definidas, el operador ternario condicional (porque es ambos) le permite hacerlo en los casos en que exista una condicionalidad sobre su valor. Particularmente notable en los campos finales, pero útil también en otros lugares.

p.ej:

public class Foo {
    final double    value;

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

Sin ese operador, por cualquier nombre, tendría que hacer que el campo no sea definitivo o escribir una función simplemente para inicializarlo. En realidad, eso no está bien: todavía se puede inicializar usando if / else, al menos en Java. Pero encuentro este limpiador.

Carl Manaster
fuente
3

Este constructo se llama Operador ternario en informática y técnicas de programación.
Y Wikipedia sugiere la siguiente explicación:

En informática, un operador ternario (a veces llamado incorrectamente un operador terciario) es un operador que toma tres argumentos. Los argumentos y el resultado pueden ser de diferentes tipos. Muchos lenguajes de programación que usan sintaxis tipo C presentan un operador ternario,?:, Que define una expresión condicional.

No solo en Java, esta sintaxis está disponible en PHP, Objective-C también.

En el siguiente enlace da la siguiente explicación, lo cual es bastante bueno para entenderlo:

Un operador ternario es una operación que opera en 3 entradas. Es un acceso directo para una instrucción if-else, y también se conoce como operador condicional.

En Perl / PHP funciona como:
boolean_condition ? true_value : false_value

En C / C ++ funciona como:
logical expression ? action for true : action for false

Esto podría ser legible para algunas condiciones lógicas que no son demasiado complejas, de lo contrario es mejor usar el bloque If-Else con la combinación prevista de lógica condicional.

Podemos simplificar los bloques If-Else con este operador ternario para una línea de instrucción de código.
Por ejemplo:

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

Podría ser igual a lo siguiente:

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

Entonces, si nos referimos a su declaración:

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

En realidad, es el 100% equivalente del siguiente bloque If-Else :

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

¡Eso es!
¡Espero que esto haya sido útil para alguien!
¡Salud!

Randika Vishman
fuente
2

Correcto. Se llama el operador ternario . Algunos también lo llaman el operador condicional .

cletus
fuente
9
Para citar a Alicia en el país de las maravillas, se llama operador ternario, pero se llama Operador condicional.
Paul Tomblin
Pero el nombre se llama operador de dos puntos con signo de interrogación.
Michael Myers
1
Nombrar naming suena un poco C ++ ish. El signo de interrogación del operador de colon?: (Una ficha) se conoce como el operador de Elvis.
Tom Hawtin - tackline
2

Su operador ternario (? :)

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.
Darsy
fuente
1

Quizás le interese una propuesta para algunos operadores nuevos que sean similares al operador condicional. Los operadores de seguridad nula habilitarán un código como este:

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

Sería especialmente conveniente donde se realiza el desempaquetado automático.

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

Ha sido seleccionado para mayor consideración bajo "Proyecto Moneda" de JDK 7.

erickson
fuente
Ese operador no es uno de mis favoritos de Project Coin. Utilidad limitada, no intuitiva de leer, y simplemente fea como todo. Sin embargo, tal vez me crezca.
Michael Myers
Tampoco soy un gran admirador. Es una propuesta de Neal Gafter, y él tiende a ver las cosas de manera muy diferente al programador promedio de Java, que tiende a ver las cosas de manera diferente a su ser humano promedio. Los únicos lugares en los que me gustaría un poco de ayuda con nulos es en un bucle foreach, probando si el iterable es nulo y auto-desempaquetado.
erickson
IIRC <Neal no lo propuso. Simplemente lo usó como un simple ejemplo de cómo escribir una propuesta. Más detalles sobre el archivo de la lista de correo de monedas del proyecto.
Tom Hawtin - tackline
Acabo de leer la introducción a la propuesta, y tienes razón. Es Stephen Colebourne de Joda y "no hay Java 7" fama.
erickson
1

En realidad, puede tomar más de 3 argumentos. Por ejemplo, si queremos verificar si un número es positivo, negativo o cero, podemos hacer esto:

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

que es mejor que usar if, else if, else.

Alabado
fuente
0

Es el operador condicional, y es más que una forma concisa de escribir declaraciones if.

Dado que es una expresión que devuelve un valor, puede usarse como parte de otras expresiones.

justinhj
fuente
0

Sí, estás en lo correcto. ?: normalmente se denomina "operador condicional ternario", a menudo denominado simplemente "operador ternario". Es una versión abreviada del estándar condicional if / else.

Operador Condicional Ternario

Gary
fuente
0

Realmente me gusta este operador, pero el lector debe tenerse en cuenta.

Siempre debe equilibrar la compacidad del código con el tiempo dedicado a leerlo, y en eso tiene algunos defectos bastante graves.

En primer lugar, está el caso del Original Asker. Solo pasó una hora publicando sobre eso y leyendo las respuestas. ¿Cuánto tiempo le habría llevado al autor escribir cada una ?: como si / luego a lo largo de toda su vida. Ni una hora para estar seguro.

En segundo lugar, en lenguajes tipo C, tienes el hábito de simplemente saber que los condicionales son lo primero en la línea. Me di cuenta de esto cuando estaba usando Ruby y encontré líneas como:

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

Si fuera un usuario de Ruby desde hace mucho tiempo, probablemente no habría tenido un problema con esta línea, pero viniendo de C, cuando ve "callMethodWhatever" como lo primero en la línea, espera que se ejecute. El?: Es menos críptico, pero sigue siendo lo suficientemente inusual como para sorprender al lector.

La ventaja, sin embargo, es una sensación realmente genial en su barriga cuando puede escribir una declaración if de 3 líneas en el espacio de 1 de las líneas. No puedo negar eso :) Pero, sinceramente, no necesariamente es más legible para el 90% de las personas simplemente por su rareza.

Cuando es realmente una tarea basada en un valor booleano y valores, no tengo ningún problema con él, pero se puede abusar fácilmente.

Bill K
fuente
0

Las expresiones condicionales están en un estilo completamente diferente, sin explícito si en la declaración.

La sintaxis es: expresión-booleana? expresión1: expresión2;

El resultado de esta expresión condicional es

expresión1 si expresión-booleana es verdadera;

de lo contrario, el resultado es expresión2.

Suponga que desea asignar el mayor número de variables num1 y num2 a máx. Simplemente puede escribir una declaración usando la expresión condicional: max = (num1> num2)? num1: num2;

Nota: los símbolos? y: aparecen juntos en una expresión condicional. Forman un operador condicional y también se llaman operador ternario porque utiliza tres operandos. Es el único operador ternario en Java.

Citado de: Introducción a la 10ª edición de Java Programming por Y. Daniel Liang, página 126 - 127

Ged
fuente