Cuándo usar la clase contenedora y el tipo primitivo

Respuestas:

69

Otros han mencionado que ciertas construcciones como Collectionsrequieren objetos y que los objetos tienen más gastos generales que sus contrapartes primitivas (memoria y boxeo).

Otra consideración es:

Puede ser útil inicializar objetos nullo enviar nullparámetros a un método / constructor para indicar el estado o la función. Esto no se puede hacer con primitivas.

Muchos programadores inicializan los números en 0 (predeterminado) o -1 para indicar esto, pero dependiendo del escenario, esto puede ser incorrecto o engañoso.

Esto también preparará el escenario para NullPointerExceptioncuando algo se esté usando incorrectamente, lo cual es mucho más amigable para el programador que algún error arbitrario en el futuro.

pstanton
fuente
15
"Puede ser útil inicializar objetos a nulo". No puede ser útil porque esto es incorrecto, si el campo es opcional debe indicarlo explícitamente.
Eddie Jamsession
8
lol @EddieJamsession gracias, nunca volveré a inicializar a null. (pfffft)
pstanton
@EddieJamsession Si la inicialización de Objects en nulo como una forma de indicar una falla al establecer el valor real ha fallado, ¿de qué otra manera propondría detectar este problema? Oh, me acabo de dar cuenta mientras escribo esto: excepciones. Una NullPointerException es demasiado genérica; Sería mejor utilizar excepciones personalizadas muy específicas para indicar qué ha fallado. Bien, lo haré de ahora en adelante ...
klaar
1
@EddieJamsession Después de leer sobre el tema, me encontré con el concepto de un objeto opcional. Correcto.
klaar
18

Generalmente, debe usar tipos primitivos a menos que necesite un objeto por alguna razón (por ejemplo, para poner en una colección). Incluso entonces, considere un enfoque diferente que no requiera un objeto si desea maximizar el rendimiento numérico. Esto es aconsejado por la documentación , y este artículo demuestra cómo el autoempaquetado puede causar una gran diferencia de rendimiento.

Matthew Flaschen
fuente
3
el impacto en el rendimiento no es tan grande como para que la legibilidad / fiabilidad del código quede en segundo plano.
pstanton
2
Primero, usar primitivas apropiadamente no hará que su código sea ilegible. En segundo lugar, el impacto en el rendimiento es significativo en algunos casos. Es absurdo decir que nunca lo es.
Matthew Flaschen
1
@pstanton: explique cómo Integeres más legible que int.
Stephen C
En muchos casos, Integer no es más legible que int y en estos casos siempre usaré int, o si sé que una determinada variable NUNCA será nula, usaré int porque int es, como ha señalado, un poco más eficiente. Sin embargo, en muchos casos es más fácil para otro programador comprender el estado de una variable cuando se usa un objeto, ya que se puede inicializar a nulo para indicar que no está listo. Por ejemplo, si tiene un registro de base de datos no guardado que tiene una identificación numérica incremental única, ¿esta identificación debería ser 0, -1 o nula antes de que se le asigne una identificación válida? En ese caso, los objetos son mejores.
pstanton
con respecto al rendimiento: en casos especiales, el impacto en el rendimiento puede ser significativo, es decir, si está creando una multitud de estos Objetos muy rápidamente o si muchos muchos de ellos se acumulan durante un período de tiempo. Sin embargo, esperaría que un programador decente pudiera identificar estos casos especiales, ya sea para evitarlos o modificarlos en consecuencia. Nunca dije que NUNCA es significativo, sin embargo, en general, no lo es.
pstanton
12

En mi opinión, si los miembros de mi clase son variables contenedoras, no depende de los valores predeterminados, que es un comportamiento amigable para los desarrolladores.

1.

class Person {
   int SSN ; // gets initialized to zero by default 
}

2.

class PersonBetter {
  Integer SSN; //gets initialized to null by default
}

En el primer caso, no puede mantener el valor del SSN sin inicializar. Puede doler si no está comprobando si el valor se estableció antes de intentar usarlo.

En el segundo caso, puede mantener SSN inicializado con nulo. Lo que puede llevar a NullPointerException, pero es mejor que insertar sin saberlo valores predeterminados (cero) como SSN en la base de datos cada vez que intente usarlo sin inicializar el campo SSN.

Cody
fuente
3
El patrón de construcción está destinado a evitar esto. En este escenario, PersonBuildercrea un que arroja una excepción si el SSN no está configurado antes de llamar a "build" para obtener la Personinstancia. Creo que este tipo de cosas es excesivo, pero es lo que promueve el lenguaje Java para los patrones adecuados.
Sandy Chapman
8

Solo usaría los tipos de envoltura si es necesario.

Al usarlos no se gana mucho, además del hecho de que lo son Objects.

Y pierde gastos generales en el uso de la memoria y el tiempo dedicado a boxear / unboxing.

jjnguy
fuente
4
Puede que no ganes mucho, pero tampoco pierdes mucho. a menos que esté ejecutando un piloto de palma de 1990.
pstanton
El hecho de que sean Objetos también les da mucho más contexto y encapsulación que como un simple primitivo. Por lo tanto, puede ganar mucho dependiendo de para qué están destinados esos primitivos y dónde se usan.
aberrant80
4

Prácticamente me encontré con una situación en la que se puede explicar el uso de la clase contenedora.

Creé una clase de servicio que tenía una longvariable de tipo

  1. Si la variable es de tipo long, cuando no se inicializa, se establecerá en 0, esto será confuso para el usuario cuando se muestre en la GUI
  2. Si la variable es de tipo Long, cuando no se inicializa, se establecerá en null, este valor nulo no se mostrará en la GUI.

Esto también se aplica Booleancuando los valores pueden ser más confusos cuando usamos primitivos boolean(ya que el valor predeterminado es falso).

Mohamed Afzal
fuente
3

Las colecciones son el caso típico de los objetos contenedores simples de Java. Sin embargo, podría considerar darle al Wrapper un significado más específico en el código (objeto de valor).

En mi humilde opinión, casi siempre hay una ventaja en el uso de objetos de valor cuando se reduce a la legibilidad y el mantenimiento del código. Envolver estructuras de datos simples dentro de objetos cuando tienen ciertas responsabilidades a menudo simplifica el código. Esto es algo muy importante en el diseño basado en dominios .

Por supuesto, existe el problema del rendimiento, pero tiendo a ignorarlo hasta que tenga la posibilidad de medir el rendimiento con los datos adecuados y realizar acciones más dirigidas hacia el área problemática. También podría ser más fácil comprender el problema de rendimiento si el código también es fácil de comprender.

Mattias Holmqvist
fuente
3

El rendimiento de aplicaciones dominadas por cálculos numéricos puede beneficiarse enormemente del uso de primitivas.

tipos primitivos, se usa el operador ==, pero para el envoltorio, la opción preferida es llamar al método equals ().

"Tipos primitivos considerados dañinos" porque mezclan "la semántica de procedimiento en un modelo orientado a objetos uniforme.

Muchos programadores inicializan los números en 0 (predeterminado) o -1 para indicar esto, pero dependiendo del escenario, esto puede ser incorrecto o engañoso.

loknath
fuente
1

Si desea utilizar Colecciones, debe utilizar las clases Wrapper.

Los tipos primitivos se utilizan para matrices. Además, para representar datos que no tienen comportamiento, por ejemplo, un contador o una condición booleana.

Desde el autoboxing, la frontera de "cuándo usar primitivo o envoltorio" se ha vuelto bastante confusa.

Pero recuerde, los Wrappers son objetos, por lo que obtiene todas las características elegantes de Java. Por ejemplo, puede utilizar la reflexión para crear objetos Integer, pero no valores int. Las clases contenedoras también tienen métodos como valueOf.

Tom
fuente
Aparte de las colecciones, ¿no debería usar clases contenedoras? ¿Qué tal usarlo para declaraciones ordinarias como Integer i = new Integer (10); ¿Es bueno hacer esto?
Gopi
autoboxing le permite hacer Integer i = 10;
Tom
1
No, Sri. Si no tienes el requisito de que yo sea un objeto, no lo conviertas en uno.
Matthew Flaschen
¿Autoboxing desempaquetará la i declarada anteriormente a int i = 10 o Integer i = 10?
Gopi
3
int pi = nuevo entero (10); trabajos. Entero oi = 10; trabajos. int ni = nulo; no funciona. el LHS se convierte a lo que requiera el RHS.
pstanton
0

Si desea crear un tipo de valor. Algo como ProductSKU o AirportCode.

Cuando un tipo primitivo (cadena en mis ejemplos) define la igualdad, querrá anular la igualdad.

Chris Missal
fuente
5
cadena no es un primitivo
pstanton
2
todavía hay buenas razones para ajustar un tipo de valor que contiene una cadena como objeto base.
Chris Missal
tu respuesta simplemente no tiene sentido. No estoy seguro de lo que estás diciendo. Sin embargo, estoy de acuerdo con tu comentario, las clases contenedoras son una buena idea si mejoran la legibilidad.
pstanton
Los tipos de valor u objetos de valor deben crearse y ser inmutables. Por ejemplo, no tendría sentido crear un objeto "CountryCode" como: new CountryCode ("USA") y luego crear otro objeto de la misma manera, donde luego son diferentes. Para empezar, son solo cadenas, pero tienen un significado detrás de ellas. Al usar cadenas, puede modificarlas (agregando más datos, etc.) pero ya no serían iguales. Consulte este artículo para obtener una mejor descripción de lo que estoy tratando de explicar :) Espero que esto tenga sentido c2.com/cgi/wiki?ValueObject
Chris Missal
0

Los valores primitivos en Java no son objeto. Para manipular estos valores como objeto, el paquete java.lang proporciona una clase contenedora para cada uno de los tipos de datos primitivos.

Todas las clases de Wrapper son finales. El objeto de todas las clases contenedoras que se pueden iniciar son inmutables, lo que significa que el valor en el objeto contenedor no se puede cambiar.

Aunque, la clase void se considera una clase contenedora, pero no envuelve ningún valor primitivo y no es iniciable. No tiene un constructor público, solo denota un objeto de clase que representa la palabra clave void.

Ahmad Sayeed
fuente