2009-02-05 13 views
24

Tengo un método como este:Java: Arsenal de tipos de datos primitivos no AUTOBOX

public static <T> boolean isMemberOf(T item, T[] set) 
{ 
    for (T t : set) { 
     if (t.equals(item)) { 
      return true; 
     } 
    } 
    return false; 
} 

ahora trato de llamar a este método utilizando un char para T:

char ch = 'a'; 
char[] chars = new char[] { 'a', 'b', 'c' }; 
boolean member = isMemberOf(ch, chars); 

Esto no tiene' t trabajo. Yo esperaría que el char y char[] para llegar a autoboxed Character y Character[], pero que no parece que suceda.

¿Algún conocimiento?

Respuesta

33

No hay autoboxing para las matrices, sólo para primitivas. Creo que este es tu problema

+4

Sí, ese es el problema. Eso me parece tan malo ... o al menos, contra-intuitivo. –

+5

Y una limitación de Java, en mi humilde opinión. –

+0

Personalmente, no me gusta el autoboxing, ya que es una operación comparativamente costosa que me gustaría evitar a menos que sea realmente necesario. – Eddie

12

¿Por qué char[] ser encajonado a Character[]? Las matrices son siempre tipos de referencia, por lo que no se requiere boxeo.

Por otra parte, sería terriblemente caro - que implicaría la creación de una nueva matriz y luego el boxeo cada caracter en turno. ¡Ay!

+7

Desde una perspectiva técnica, estoy totalmente de acuerdo con usted. Desde una perspectiva centrada en el usuario, parece que esto debería "funcionar". (Supongo que esto no sería un problema en absoluto si no fuera por el uso de tipos primitivos en primer lugar) –

1

Esto parece ser por diseño, tanto para evitar una operación de autoboxing tan costosa como porque los genéricos tienen que ser compatibles con versiones anteriores con el bytecode de Java existente.

Véase this article y this bug, por ejemplo.

1

Las matrices son un tipo de implementación de bajo nivel de cosas. char[] será un área contigua de memoria con caracteres de dos bytes. Character[] será un área contigua de memoria con referencias de cuatro u ocho bytes. No puede obtener un Character[] para envolver un char []. Sin embargo, un List<Character> podría envolver un char[].

matrices de referencias no son generalmente una buena idea a menos que usted está escribiendo código de bajo nivel. Si lo desea, puede escribir u obtener un equivalente de java.util.Arrays.asList.

0

Una forma más sencilla de hacer esto es

char ch = 'a'; 
String chars = "abc"; 
boolean member = chars.indexOf(ch) >= 0; 
+0

Cierto, pero esperaba crear un método que pudiera usar con cualquier tipo. –

2

correcta, no hay autoboxing para las matrices (que da lugar a la rareza en casos como int[] ints; ...; Arrays.asList(ints) - asList devuelve una lista que contiene un único objeto, la matriz)

Aquí hay una utilidad simple para encajonar una matriz.

public static Integer[] boxedArray(int[] array) { 
    Integer[] result = new Integer[array.length]; 
    for (int i = 0; i < array.length; i++) 
     result[i] = array[i]; 
    return result; 
} 

Necesitará una versión diferente para cada tipo primitivo, por supuesto.

3

Puede usar la reflexión para obtener un método que funcione para todos los tipos de matrices, pero perdería seguridad de tipo, por lo que probablemente no sea lo que desea.

import java.lang.reflect.Array 
public static boolean isMemberOfArray(Object item, Object array) 
{ 
    int n = Array.getLength(array) 
    for (int i = 0; i < n; i++) { 
     if (Array.get(array, i).equals(item)) { 
      return true; 
     } 
    } 
    return false; 
} 
1

Como han mencionado otros, no hay autoboxing para arreglos de primitivos. Si desea utilizar su método con matrices primitivas, deberá proporcionar una sobrecarga para cada tipo primitivo. Esta parece ser la forma estándar de hacer las cosas en las bibliotecas de clase. Ver las sobrecargas en java.util.Arrays, por ejemplo.

1

En primer lugar, intentaría evitar matrices tanto como sea posible, use listas en su lugar.

No hay autoboxing para arrays, pero hay autoboxing para varargs. Así que si usted declara su método (en la misma entidad):

public static <T> boolean isMemberOf(T item, T ... set) 

entonces usted puede escribir

isMemberOf('a', 'a', 'b', 'c'); 

Personalmente, yo prefiero usar la guayaba de Google, donde puede escribir cosas como

char ch = 'a'; 
char[] chars = new char[] { 'a', 'b', 'c' }; 
boolean member = isMemberOf(ch, Chars.asList(chars).toArray(new Character[0])); 

Su código probablemente sea solo un ejemplo, pero si realmente desea probar la membresía, puede hacerlo así:

Chars.contains(chars, ch); 

or 

ImmutableSet.of('a', 'b', 'c').contains('a') 
1

Introduzca Java 8 y vamos primArray ser un identificador de tipo PrimType[], entonces usted puede haga lo siguiente:
BoxedType[] boxedArray = IntStream.range(0, primArray.length).mapToObj(i -> primArray[i]).toArray(BoxedType[] :: new);

Cuestiones relacionadas