Veo que Java tiene Boolean (clase) vs boolean (primitivo). Del mismo modo, hay un entero (clase) vs int (primitivo). ¿Cuál es la mejor práctica sobre cuándo usar la versión primitiva frente a la clase? ¿Debería usar siempre la versión de clase, a menos que tenga una razón específica (¿rendimiento?) ¿Cuál es la forma más común y aceptada de usar cada uno?
54
Respuestas:
En el ítem 5, de Java efectivo, Joshua Bloch dice
Un buen uso para las clases es usarlas como tipos genéricos (incluidas las clases de Colección, como listas y mapas) o cuando desea transformarlas a otro tipo sin conversión implícita (por ejemplo, la
Integer
clase tiene métodosdoubleValue()
obyteValue()
.Editar: La razón de Joshua Bloch es:
fuente
La práctica estándar es ir con los primitivos, a menos que se trate de genéricos (¡asegúrese de conocer el autoboxing y unboxing !).
Hay varias buenas razones para seguir la convención:
1. Evitas errores simples:
Hay algunos casos sutiles, no intuitivos, que a menudo atrapan a los principiantes. Incluso los codificadores experimentados se equivocan y cometen estos errores a veces (¡espero que esto sea seguido de juramentos cuando depuran el código y encuentran el error!).
El error más común es usar en
a == b
lugar dea.equals(b)
. La gente está acostumbrada a lasa == b
primitivas, por lo que se hace fácilmente cuando se usan los contenedores de objetos.2. Legibilidad:
Considere los siguientes dos ejemplos. La mayoría de la gente diría que el segundo es más legible.
3. Rendimiento:
El hecho es que es más lento usar los contenedores de objetos para primitivas que solo usar las primitivas. Está agregando el costo de la creación de instancias de objetos, llamadas a métodos, etc. a cosas que usa en todo el lugar .
La cita de Knuth "... digamos alrededor del 97% del tiempo: la optimización prematura es la raíz de todo mal", en realidad no se aplica aquí. Estaba hablando de optimizaciones que hacen que el código (o sistema) sea más complicado: si está de acuerdo con el punto 2, ¡esta es una optimización que hace que el código sea menos complicado!
4. Es la convención:
Si realiza diferentes elecciones estilísticas para el 99% de los otros programadores de Java, hay 2 desventajas:
Normalmente, enumeraría algunos contrapuntos, pero honestamente no puedo pensar en ninguna buena razón para no ir con la convención aquí.
fuente
==
. Los objetos deben compararse conequals()
.equals()
... les das una solución para que comparar objetos con==
los resultados esperados.equals()
el segundo fragmento de código y cambié mi voto.Normalmente voy con los primitivos. Sin embargo, una peculiaridad de usar clases como
Integer
yBoolean
es la posibilidad de asignarnull
a esas variables. Por supuesto, esto significa que tiene que hacernull
verificaciones todo el tiempo, pero aún mejor obtener una NullPointerException que tener errores lógicos debido al uso de algunaint
oboolean
variable que no se ha inicializado correctamente.Por supuesto, desde Java 8 puede (y probablemente debería) ir un paso más allá y, en lugar de, por ejemplo
Integer
, podría usarOptional<Integer>
variables que podrían o no tener un valor.Además, presenta la posibilidad de utilizar
null
para asignar a esas variables un valor " desconocido " o " comodín ". Esto puede ser útil en algunas situaciones, por ejemplo, en Ternary Logic . O puede que desee comprobar si un determinado objeto coincide con alguna plantilla; en este caso, puede usarnull
para aquellas variables en la plantilla que pueden tener cualquier valor en el objeto.fuente
null
por defecto. Por el contrario: sería mejor no "inicializar" la variable. Establecer cualquier valor predeterminado, inclusonull
, cierra el compilador ... pero también evita que detecte la falta de asignación útil en todas las rutas de código. Por lo tanto, un error que el compilador podría haber detectado, pasa al tiempo de ejecución.0.0
, o-1
, oInteger.MAX_VALUE
, oFalse
, pero al final no sabe si ese es el valor predeterminado o un valor real que se asignó a esa variable. En casos donde esto es importante, tener unnull
valor allí podría ser más claro.null
vienen con una gran cantidad de problemas, incluida la paranoia nula). Dentro de una función, una variable que en realidad no se ha inicializado en el punto de uso generalmente indica casos no cubiertos. (El análisis de asignación definida es simplista, por lo que son posibles los falsos positivos. Pero a menudo puede resolverlos simplificando la lógica, por lo tanto.)En palabras simples:
Utiliza los contenedores cuando necesitas agregar cosas a las colecciones.
Las colecciones no pueden contener primitivas.
fuente
Java presenta autoboxing como señaló m3th0dman. Piense en el nivel más bajo posible y verá que el autoboxing (dentro o fuera) de un valor primitivo implicará ciclos de reloj gastados en algunas tareas que no necesita si está trabajando con tipos de datos nativos alrededor de su aplicación.
Como regla general, debe intentar utilizar tipos de datos nativos siempre que sea posible.
fuente