2010-09-27 12 views
5

Estoy realmente confundido sobre los dos temas, ¿alguien me puede explicar.autoboxing y genéricos

ArrayList<Long> queryParms = new ArrayList<Long>(); 
  1. ¿Es lo anterior uno llamado genéricos o autoboxing y lo que es unboxing?
  2. ¿Es una buena práctica?
  3. Algunos dicen que el Autoboxing es algo malo.
  4. Si uso genéricos, ¿puedo evitar el autoboxing y unboxing?

Respuesta

8
  1. Lo anterior es un ejemplo de genéricos. El auto-boxing sería la conversión automática, por el compilador, de un tipo primitivo en un tipo de envoltura, y viceversa. En su caso, por ejemplo, de una variable en una variable longLong:

    long param = 13L; 
    queryParms.add(param); 
    
  2. El uso de los genéricos? Sí. Le permite especificar lo que contendrá su lista. Deberías usarlos. ¿Usando auto-boxing? Sí, simplifica el código y no tiene que preocuparse por las conversiones entre los tipos de variables primitivas en el contenedor (y viceversa).

  3. El auto-boxeo no es malo (en mi humilde opinión). Son algunos casos de esquina en los que el auto-boxeo puede ser muy molesto, pero si sabes cómo funciona, no deberías preocuparte por ello. Aquí está the Sun (now Oracle) paper on auto-boxing, si necesita saber más al respecto.

  4. Si desea crear una lista que contenga envolturas (en su caso, Long), tendrá que ocuparse de la conversión de tipo. Puede usar la conversión de tipo explícita, o puede usar el auto-boxeo.

+4

El auto (des) boxeo involuntario puede ser un rendimiento alto, si se realiza en un bucle ejecutado muchas veces. Esta podría ser la razón por la cual algunas personas lo consideran malvado. Sin embargo, el verdadero problema aquí es la codificación descuidada (y la falta de creación de perfiles), en lugar de la característica del idioma en sí. –

+1

Si uso genéricos, ¿puedo evitar autoboxing y unboxing? – John

+0

@John Puede evitar el autoboxing y el desempaquetado innecesarios al considerar cuidadosamente si se debe usar el tipo de primitiva o de envoltura y verificar si hay alguna llamada a métodos que provoquemos el boxeo. Sin embargo, dado que necesitas usar el tipo de envoltorio con genéricos, generalmente no hay forma de evitarlo por completo. – Carlos

2

Autoboxing es cuando una primitiva se convierte automáticamente en un objeto. Por ejemplo:

Long autoboxedLong = 3; 

Nota la caja superior L, haciendo autoboxedLong un objeto en lugar de una primitiva.

Lo contrario es auto-unboxing, lo que le permite escribir:

long autounboxedLong = autoboxedLong; 

es decir, va a convertir automáticamente un objeto en un primitivo. Sin embargo, esto es peligroso, porque autoboxedLong puede ser null. Entonces este código arrojaría una NullPointerException.

Su ejemplo no trata de autoboxing, pero el autoboxing entra en juego cuando inserta objetos en su lista. Que puede hacer:

queryParams.add(1); 

y le autoboxing caja automáticamente su primitiva larga 1 en un objeto largo.

1

Sin lo anterior no se llama autoboxing.When haces

queryParms.add(22l);//here primitive type 22 is converted to wrapper class Long type.This  
        //is called autoboxing. 
1

Usted ejemplo crea un ArrayList con el tipo genérico de largo. Entonces la lista contendrá objetos de tipo largo. Outoboxing hace primitivas de los objetos y viceversa.Así que usted puede utilizar su lista como:

long x = queryParms.get(0); 

o

queryParams.add(4L); 
0

Dentro de Java 5.0, clases de contenedor se han convertido en más fácil de usar. Java 5.0 introdujo la conversión automática entre un tipo primitivo y la clase contenedora correspondiente.

De tipo primitivo a la clase corresponsal de la clase se llama autoboxing, el proceso inverso se llama unboxing. Autoboxing y unboxing también se aplican a llamadas a métodos. Por ejemplo, puede pasar un argumento de tipo int a un método que tiene un parámetro formal de tipo Integer.

  • Se produce una excepción de excepción de Nullpointer Al desempaquetar una referencia de clase de envoltura nula a su tipo primitivo. Por ejemplo, el código se compilará pero emitirá una NullpointerException en tiempo de ejecución.

    Long L = null; long l = L; ... 
    
  • conversión Boxing convierte los valores de tipo primitivo a valores de tipo de referencia correspondiente. Pero los tipos primitivos no se pueden ensanchar/Estrechar a las clases de Contenedor y viceversa. Por ejemplo,

    byte b = 43; Entero I1 = 23; // Valor entero constante Entero I2 = (int) b; // Cast para el tipo int Long L1 = 23; // error de compilación porque 23 es un valor entero Largo L2 = (Largo) 23; // no se puede convertir el valor entero a la clase Long wrapper Long L3 = 23L; Largo L4 = (largo) 23;

Esta restricción se aplica también a la invocación de métodos:

public class MyClass 
{ 
    public void method(Long i) 
    { 
     System.out.println("Here"); 

    } 
    public static void main(String[] args) 
    { 
     MyClass s = new MyClasslass(); 
     //s.method(12); 
     // error  s.method(12L); 
     // ok 
    } 

} 
•When invoking a method from multiple overloading methods, For the matching method process, the Java compiler will perferance the order of primitive types (Widening Primitive Conversion), wrapper class (Boxing Conversion), and var-args. For example, 
public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public void method(long x, long y) 
    { 
     System.out.println("method(long x, long y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

El resultado es method(long x, long y). El compilador de Java comprobará los tipos primitivos coincidentes, luego buscará los tipos de Contenedor.

public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public void method(int x, int y) 
    { 
     System.out.println("method(int x, int y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

El resultado es method(Long x, Long y). El compilador de Java da preferencia a la firma del método de clase Wrapper coincidente que no sea el método varargs primitivo.

public class MyClass 
{ 
    public void method(Double x, Double y) 
    { 
     System.out.println("method(Double x, (Double y)"); 

    } 
    public void method(int x, int y) 
    { 
     System.out.println("method(int x, int y)"); 

    } 
    public void method(long... x) 
    { 
     System.out.println("method(long... x)"); 

    } 
    public static void main(String[] args) 
    { 
     long x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

El resultado es method(long ...x). El compilador no reducirá el valor primitivo "largo" a "int"; Además, no puede ganar mucho tiempo para la clase Doble. Solo se puede usar el método var-args.

public class MyClass 
{ 
    public void method(Long x, Long y) 
    { 
     System.out.println("method(Long x, Long y)"); 

    } 
    public static void main(String[] args) 
    { 
     int x, y; 
     x = y = 0; 
     MyClass s = new MyClass(); 
     s.method(x, y); 

    } 

} 

Los argumentos no pueden winden a "long" y luego a "Long". Obtendrás un error de compilación.

  • Para ahorrar memoria, dos instancias de los siguientes objetos contenedoras siempre serán == cuando sus valores primitivos sean los mismos. Por favor, lea ¿Por qué la conversión de autoboxing a veces devuelve la misma referencia?
+0

Formatee esto. Mira la página de formato de wiki: http://stackoverflow.com/editing-help – mtk