2010-04-08 16 views
5

(Para los fines de esta pregunta, supongamos que uno intencionalmente no usa el auto (un) boxing, ya sea porque uno está escribiendo código pre-Java 1.5, o porque uno siente que el autoenvío hace que sea muy fácil crear NullPointerException s .)¿Por qué querría uno usar los constructores públicos en Boolean y clases inmutables similares?

Tome Boolean, por ejemplo. La documentación para el constructor Boolean(boolean) dice:

Nota: Rara vez es apropiado utilizar este constructor. A menos que se requiera una nueva instancia , la fábrica estática valueOf(boolean) generalmente es una mejor opción. Es probable que rinda significativamente mejor espacio y tiempo rendimiento.

Mi pregunta es, ¿por qué cada vez desee obtener una nueva instancia en el primer lugar? Parece que las cosas serían más simples si los constructores como ese fueran privados. Por ejemplo, si lo fueran, podría escribir esto sin peligro (incluso si eran myBooleannull):

if (myBoolean == Boolean.TRUE) 

que sería seguro porque toda verdadera Booleans habría referencias a Boolean.TRUE y todas falsas Booleans habría referencias a Boolean.FALSE. Pero debido a que los constructores son públicos, alguien puede haber usado ellos, lo que significa que usted tiene que escribir esto en su lugar:

if (Boolean.TRUE.equals(myBoolean)) 

Pero donde realmente se pone malo es cuando se desea comprobar dos Booleans por la igualdad. Algo como esto:

if (myBooleanA == myBooleanB) 

... se convierte en esto:

if (
    myBooleanA == myBooleanB || 
    (myBooleanA != null && myBooleanA.equals(myBooleanB)) 
) 

ACTUALIZACIÓN: Con el lanzamiento de Java 7, java.util.Objects hace que este más simple posible construir:

if (Objects.equals(myBooleanA, myBooleanB)) 

No puedo pensar en ninguna razón para tener instancias separadas de estos objetos, que es más convincente que no tener que hacer las tonterías anteriores. ¿Lo que usted dice?

+0

Tiene el último bloque de código erróneo. O bien 'a == nulo? b == nulo: a.equals (b) 'o' a == b || (a! = null && a.equals (b)) '. O 'Objects.eq (a, b)'. –

+0

Tiene razón. Lo cambié a 'a == b || (a! = null && a.equals (b)) '. –

Respuesta

5

Los valores almacenados en caché nunca son basura, por lo tanto, utilice los constructores siempre que desee utilizarlos como referencias débiles/débiles, de modo que se puedan recolectar de todos modos siempre que sea necesario. Lo mismo se aplica en , Integer#valueOf() y consortes con valores dentro de los rangos de caché.

Haciendo una búsqueda de referencia en Eclipse mí se entera de que en cada java.lang.Thread utiliza new Boolean() como caché basada suave de referencia, que incluso se comentó de manera explícita (en isCCLOverridden() método): se necesitaban

/* 
* Note: only new Boolean instances (i.e., not Boolean.TRUE or 
* Boolean.FALSE) must be used as cache values, otherwise cache 
* entry will pin associated class. 
*/ 
-1

Estos tipos de objetos debido a que la La clase de recopilación solo aceptaba objetos, por lo tanto, no podía usar los tipos nativos.

Esto introdujo la falla de diseño de la que está hablando y, por lo tanto, se introdujo el autoboxing.

EDITAR

Y los constructores son públicos porque siempre fueron públicas. Antes del mundo del autoboxing en un código muy pobre, querías que new Integer(0) != new Integer(0) fuera verdad. Era un defecto más que nada del diseño original, sin embargo, como ahora es parte de la interfaz pública, no quieren romper el código anterior.

Apuesto a que podrían desaprobarlo ahora y la mayoría de las personas estarían de acuerdo con él ya que el autoboxing simplemente funciona.

1

Los constructores son públicos debido a la compatibilidad hacia atrás ... solo recibió añadido en Java 1.4 .valueOf() ...

También usando un booleano como variable de tres estados en su ejemplo (nulo/TRUE/FALSE) es probablemente una mala idea, es mejor usar una enumeración (UNKNOWN, True, FALSE), o si null no es un valor válido, verifíquelo y desempaque manualmente para probar la igualdad.

+0

En cuanto al uso de booleanos como tri-estados: estoy de acuerdo, las enumeraciones son preferibles, pero esto es más una cosa de programación defensiva; es decir, manejando el caso en el que alguien te entrega un nulo cuando solo esperabas VERDADERO o FALSO. (Esta es la razón exacta por la que siento que el autoenvasado es peligroso; hace que sea demasiado fácil ignorar el caso nulo cuando se tratan Objetos como primitivos). –

Cuestiones relacionadas