objeto == nulo o nulo == objeto?

96

Escuché de alguien que null == objectes mejor que object == null chequear

p.ej :

void m1(Object obj ) {
   if(null == obj)  // Is this better than object == null ? Why ?
       return ;
   // Else blah blah
}

¿Hay alguna razón o esto es otro mito? Gracias por la ayuda.

Jijoy
fuente
Imitación de 271561 y 1957836 (excepto que este dice 'en Java')
Gishu
20
Java es diferente de C #
Jijoy
5
Si no era una ventaja significativa del rendimiento, a continuación, para que el compilador optimizarlo ...
Andreas Dolk
Para nullreferencias, el curso de acción predeterminado debería ser lanzar una NPE. Algunas bibliotecas agradables (como la biblioteca de Java JDK7) tienen un método parecido a public static <T> T notNull(T obj) { if (obj == null) { throw new NullPointerException(); } else { return obj; } }. También hay @NonNull( @Nonnull¿ o ?), Pero eso se "borra".
Tom Hawtin - tackline
2
null == objectse conoce como una condición de Yoda .
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

140

Este es probablemente un hábito aprendido de C, para evitar este tipo de error tipográfico (simple en =lugar de doble ==):

if (object = null) {

La convención de poner la constante en el lado izquierdo de ==no es realmente útil en Java, ya que Java requiere que la expresión en una ifevaluación sea un booleanvalor, por lo que, a menos que la constante sea a boolean, obtendría un error de compilación de cualquier manera que ponga el argumentos. (y si es un booleano, no deberías usarlo de ==todos modos ...)

Laurence Gonsalves
fuente
4
que no es un hábito muy útil para java, ya que el error tipográfico daría como resultado un error de compilación en java
radai
11
Excepto en un caso de esquina específico. stackoverflow.com/questions/2369226/null-check-in-java/…
Chandra Sekar
3
@Chandru para un booleano, puede usar x.booleanValue()o !x.booleanValue(). x == trueo x == falseen una condición la expresión es un mal olor, en mi humilde opinión.
Laurence Gonsalves
2
Está comprobando nulo aquí. Y hay casos en los que realmente tiene que verificar un booleano para nulo, ya que nulo no es verdadero ni falso.
Chandra Sekar
1
Acostumbrarse al uso null == objectsolo para asegurarnos de no sobrescribir el objeto accidentalmente con un error tipográfico no debería ser un caso de uso en absoluto. Lo que significa que nos estamos entrenando a nosotros mismos para que ahora que utilizo "nulo" primero, está bien, incluso si cometo un error. Eso no significa que el código funcione como se esperaba. Incluso si null = objectse proporciona en lugar de null == object, ¡el programa no funcionará como se esperaba! ¡Entonces no tiene sentido seguir esta convención!
VanagaS
32

Como han dicho otros, es un hábito aprendido de C para evitar errores tipográficos, aunque incluso en C, esperaría compiladores decentes con niveles de advertencia lo suficientemente altos como para dar una advertencia. Como dice Chandru, comparar con nulo en Java de esta manera solo causaría problemas si estuviera usando una variable de tipo Boolean(que no está en el código de muestra). Yo diría que es una situación bastante rara, y no una para la que vale la pena cambiar la forma en que escribe el código en cualquier otro lugar. (No me molestaría en invertir los operandos incluso en este caso; si estoy pensando con la suficiente claridad como para considerar invertirlos, estoy seguro de que puedo contar los signos iguales).

Lo que no se ha mencionado es que muchas personas (incluido yo mismo) encuentran que el if (variable == constant)formulario es más legible, es una forma más natural de expresarse. Esta es una razón para no copiar ciegamente una convención de C. Siempre debe cuestionar las prácticas (como lo está haciendo aquí :) antes de asumir que lo que puede ser útil en un entorno es útil en otro.

Jon Skeet
fuente
3
Estoy de acuerdo con cada palabra que dijo, especialmente la parte de "copiar a ciegas una convención". Estoy leyendo un código en este momento y el estilo del objeto null = me molesta tanto que lo busqué y vine aquí. ¿Qué estaba pensando el codificador?
Adrian M
28

Esto no tiene mucho valor en Java (1.5+) excepto cuando el tipo de objeto es Boolean. En cuyo caso, esto aún puede ser útil.

if (object = null)no causará fallas de compilación en Java 1.5+ si el objeto es, Booleanpero lanzaría un NullPointerExceptionen tiempo de ejecución.

Chandra Sekar
fuente
Probablemente quería decir que hará que el fracaso compilación :)
vava
7
No, no provocará un error de compilación cuando el objeto sea booleano.
Chandra Sekar
¿No es lo mismo para todos los tipos de objetos además de los booleanos?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
2
Para los tipos no booleanos, el código no se compilará porque el tipo de la expresión "objeto = nulo" no será booleano. Debido al auto-boxing, se compilará para booleano.
Chandra Sekar
Pero, ¿por qué este comportamiento para Boolean? ¿Alguna justificación?
Rohit Banga
9

En Java no hay una buena razón.

Un par de otras respuestas han afirmado que se debe a que accidentalmente puede asignarlo en lugar de igualdad. Pero en Java, debe tener un booleano en un if, así que esto:

if (o = null)

no se compilará.

La única vez que esto podría importar en Java es si la variable es booleana:

int m1(boolean x)
{
    if (x = true)  // oops, assignment instead of equality
R Samuel Klatchko
fuente
4
Pero, ¿por qué escribirías alguna vez == trueo igualmente == true == true?
Tom Hawtin - tackline
7
No hay una buena razón para escribir == true. Pero he visto tanto código incorrecto en mi carrera que ya no pregunto por qué alguien escribiría algo y simplemente acepto que algunas personas escribieron código innecesario / cuestionable.
R Samuel Klatchko
1
De hecho, hay un montón de código deficiente dando vueltas, aún así, cuando se lo considera x == truemalo porque podría estar escrito erróneamente como x = true, no tendría mucho sentido cambiarlo a en true == xlugar de solo x.
Holger
9

Esto también se relaciona estrechamente con:

if ("foo".equals(bar)) {

lo cual es conveniente si no desea tratar con NPE:

if (bar!=null && bar.equals("foo")) {
Cherouvim
fuente
puede ser conveniente pero peligroso blue-walrus.com/2010/11/…
Oliver Watkins
@OliverWatkins: Encuentro este artículo débil. Suponga que la variable es de tipo int. Si no se inicializa, el valor sería 0 y la promesa del artículo no se mantendría. El hecho de que las cadenas sean objetos y las enteras sean primitivas es irrelevante del hecho de que un programador puede olvidar iniciar una variable. En esta pregunta, simplemente resolvemos la cuestión de la comparación de cadenas nulas.
Cherouvim
@cherouvim, el hecho de que intsea ​​un tipo primitivo es relevante, ya que es imposible invocar equalsen un int, por lo tanto, no tiene sentido discutir si usar x.equals(constant)o constant.equals(x)para intvalores. Y para los Integervalores, el valor predeterminado es en nulllugar de 0.
Holger
5

Este truco se supone que evita v = nullerrores tipográficos.

Pero Java solo permite expresiones booleanas como if()condiciones, por lo que ese truco no tiene mucho sentido, el compilador encontrará esos errores tipográficos de todos modos.

Sin embargo, sigue siendo un truco valioso para el código C / C ++.

vava
fuente
3

Por la misma razón lo haces en C; La asignación es una expresión, por lo que coloca el literal a la izquierda para que no pueda sobrescribirlo si accidentalmente usa en =lugar de ==.

Ignacio Vázquez-Abrams
fuente
Sin embargo, solo es un problema en Java para los tipos booleanos, ¿verdad? Cualquier otro tipo de asignación no tendrá un tipo booleano y debería provocar un error del compilador.
Scott Smith
1
no, el compilador de Java detectará ese tipo de error tipográfico en cualquier orden que prefiera
vava
@Jijoy: no creo que esto tenga nada que ver con el rendimiento. Esto suena como un viejo truco en C para evitar el temido error de asignación dentro de una expresión condicional. La idea era que si estás tratando de verificar si xes igual 5, cuando escribes por error if (x = 5), se compilará silenciosamente (y siempre evaluará true, independientemente del valor de x). Sin embargo, si adquiere el hábito de especificar siempre el literal primero: 'if (5 = x)', el compilador puede verificar su trabajo y ahorrarle tiempo de cabeza en el depurador. Los compiladores modernos hacen innecesario este hábito.
Scott Smith
6
-1: Si accidentalmente usa = no se compilará en Java; por lo que la razón de C no se aplica.
Jon Skeet
Técnicamente, si objfuera del tipo java.lang.Boolean(B grande), entonces podría marcar la diferencia (creo que, en realidad, no se intentó ni nada).
Tom Hawtin - tackline
3

Eso es para personas que prefieren tener la constante en el lado izquierdo. En la mayoría de los casos, tener la constante en el lado izquierdo evitará que se lance NullPointerException (o tener otro nullcheck). Por ejemplo, el método String equals también realiza una comprobación nula. Tener la constante a la izquierda le impedirá escribir el cheque adicional. Lo cual, de otra manera también se realiza posteriormente. Tener el valor nulo a la izquierda es simplemente ser consistente.

me gusta:

 String b = null;
 "constant".equals(b);  // result to false
 b.equals("constant");  // NullPointerException
 b != null && b.equals("constant");  // result to false
SPee
fuente
este ocultamiento de NPE crea errores aún más difíciles de encontrar más abajo
Oliver Watkins
2

Es la condición de Yoda escribiendo de manera diferente.

En java

String myString = null;
if (myString.equals("foobar")) { /* ... */ } //Will give u null pointer

condición de yoda

String myString = null;
if ("foobar".equals(myString)) { /* ... */ } // will be false 
Tanmay Naik
fuente
1

Compare con el siguiente código:

    String pingResult = "asd";
    long s = System.nanoTime ( );
    if ( null != pingResult )
    {
        System.out.println ( "null != pingResult" );
    }
    long e = System.nanoTime ( );
    System.out.println ( e - s );

    long s1 = System.nanoTime ( );
    if ( pingResult != null )
    {
        System.out.println ( "pingResult != null" );
    }
    long e1 = System.nanoTime ( );
    System.out.println ( e1 - s1 );

Salida (después de varias ejecuciones):

null != pingResult
325737
pingResult != null
47027

Por tanto, pingResult != nulles el ganador.

Avinash
fuente
7
¡Ejecute su prueba en un ciclo adicional! O simplemente cambie las declaraciones IF. En pocas palabras: ¡no hay diferencia! El primer bucle siempre es más lento.
Marcel Jaeschke
En esta prueba, pingResult siempre es no nulo. ¿Qué sucede con la sincronización de pingResult si es nulo? Apuesto a que es independiente de la plataforma, pero en mi pila de Oracle Java 1.6 / Linux, los resultados son prácticamente iguales (en un bucle), excepto si pingResult es nulo, ambas comprobaciones son un poco más rápidas.
Ogre Psalm33
1
si pones "pingResult! = null block antes de null! = pingResult block, dará como resultado algo como" pingResult! = null 325737 "
Sola Yang
Como dice @Sola Yang, si pones pingResult! = Null antes, verás que lleva más tiempo que null! = PingResult. Si pingResult! = Null fue más rápido que null! = PingResult, el IDE (como IntelliG, Eclipse, ...) hará una advertencia para obligar a los desarrolladores a usar este rol;)
adil.hilmi
1

Debido a su propiedad conmutativa , la única diferencia entre object == nully null == object(la versión de Yoda ) es de naturaleza cognitiva : cómo el lector lee y digiere el código. Sin embargo, no sé la respuesta definitiva, pero sé que personalmente prefiero comparar el objeto que estoy inspeccionando con otra cosa, en lugar de comparar otra cosa con el objeto que estoy inspeccionando , si eso tiene algún sentido. Comience con el tema, luego el valor con el que compararlo.

En algunos otros idiomas, este estilo de comparación es más útil.

Sin embargo, para protegerse contra un signo "=" perdido en general, creo que escribir null == objectes un acto equivocado de programación defensiva . La mejor forma de evitar este código en particular es garantizando el comportamiento con una prueba junit. Recuerde, el posible error de perder un "=" no depende de los argumentos de entrada del método; usted no depende del uso correcto de esta API por parte de otras personas, por lo que una prueba junit es perfecta para protegerse contra eso. De todos modos, querrá escribir pruebas junit para verificar el comportamiento; un "=" faltante naturalmente cae dentro del alcance.

Benny Bottema
fuente