2012-05-02 22 views
15

Estoy tratando de especificar que una clase genérica tiene que ser una matriz, o mejor aún una matriz primitiva. Hasta el momento esto es lo que tengo trabajo:Java tipos genéricos y de matriz, no es lo que está pensando (por ejemplo, matrices de tipos genéricos)

interface Foo<T> { 
    void process(T data); 
} 

public class Moo implements Foo<int[]> { 
    void process(int[] data) { 
    // do stuff here 
    } 
} 

Este es todo el código Java perfectamente válido y funciona porque las matrices primitivas objeto extendido. Tenga en cuenta que esta pregunta es completamente diferente de todas las demás preguntas genéricas de matriz de Java que sigo encontrando. En esa situación, la gente quiere crear una matriz de un tipo genérico.

El problema es que el tipo T puede ser cualquier objeto que extienda Object. Lo que quiero es hacer algo como:

<T extends ONLY ARRAYS> 

o

<T extends ONLY PRIMITIVE ARRAYS>. 

¿Es posible?

EDITAR: El objetivo final sería agregar una verificación de tiempo de compilación en el tipo de matriz que se está transfiriendo. En este momento se puede pasar cualquier objeto antiguo y se compilará muy bien. El error solo se encontrará en el tiempo de ejecución cuando se lanza una excepción de lanzamiento de clase. De hecho, este es el objetivo de Generics en Java, para agregar una comprobación de tipo de tiempo de compilación más fuerte.

+2

¿Por qué necesitaría para hacer esto? – Jeffrey

+0

Estoy de acuerdo en que "debería" ser posible. Mi instinto me dice que no hay otro supertipo de las matrices de primitiva de Object. (Hay un isArray() en la Clase Class) – esej

+0

Una única interfaz para procesar imágenes con datos de diferentes tipos primitivos. La alternativa es tener una interfaz diferente para cada tipo, que es una peor kludge. Ejemplo, Foo_S32, Foo_U8, Foo_F32, ... etc. –

Respuesta

10

No puede hacer esto. Ninguna clase puede extender una matriz, por lo que nunca habrá un tipo que satisfaga el parámetro genérico T extends Object[]. (. Aparte de Object[] sí, pero entonces no estaría utilizando los genéricos)

Lo que podría hacer es algo como esto:

public interface Foo<T extends Number> { 
    public void process(T[] data); 
} 

Pero entonces usted podría tener problemas de rendimiento con el boxeo.

+4

No del todo bien, las matrices de un tipo específico como String [] se pueden asignar a Object []. Pero esto no ayuda con las matrices primitivas. –

+1

@StevenSchlansker El ejemplo que dí fue discutible de todos modos, las matrices no se pueden usar como un parámetro de tipo vinculado. – Jeffrey

+0

Tiene razón en que el enfoque alternativo mataría el rendimiento. Después de hacer un poco más de búsqueda no puedo encontrar ningún tipo de excepción de idioma especial que permita el tipo de restricción que quiero. Seleccionando esto como la solución ya que fuiste el primero en dar la respuesta correcta. –

1

No se puede hacer. No existe ninguna interfaz de "interesante" ni ningún supertipo pero Objeto para las matrices de primitivas:

public class SOTEST {  
    public static void main(String[] args) throws Exception { 
     int[] arr = new int[] {}; 
     Class c = arr.getClass(); 
     for(Class clazz:c.getInterfaces()) { 
      System.out.println(clazz.getName()); 
     } 

     System.out.println(c.getSuperclass().toString()); 
    } 
} 
8

En Java, los parámetros de tipo pueden only verse limitada por la relación subtipo, y las únicas supertipos comunes de todas las matrices areObject, Clonable y Serializable. Lo más cerca que se puede conseguir es constreñir a Object[], que es el supertipo de todas las matrices con los tipos de componentes no primitivos, o posiblemente a Number[], que es el supertipo de Integer[], Long[], ...

Incluso si Java hizo admite tal restricción, ¿cómo haría algo útil con esa matriz? No se pudieron leer elementos individuales ya que no se puede declarar una variable para contener los resultados, ni escribir elementos individuales ya que no se puede escribir una expresión que se pueda asignar a un elemento de matriz.

Dicho esto, me ato la variable tipo al tipo de componente, no el tipo de matriz:

interface Foo<T extends Whatever> { 
    void process(T[] data); 
} 

porque se puede hacer referencia a T[] saber T, pero sabiendo un T extends Object[] no le permite directamente a consulte el tipo de componente.

Edición: Jeffrey señala correctamente que el tipo de matriz no puede ser utilizado dentro de los límites de tipo, es decir <T extends Whatever[]> no compila, por lo que definitivamente tiene que seguir mi consejo de declarar <T extends Whatever>T[] y utilizar para referirse al tipo de matriz.

+0

El punto de querer agregar la restricción no es que se pueda escribir una clase generalizada manipulando la matriz, sino para hacer que la API sea más fácil de trabajar. En este momento no hay verificación de tiempo de compilación y los errores solo se detectarán en el tiempo de ejecución. –

-2

Las matrices de X no tienen una jerarquía de tipos. Entero [] no es una subclase de Número [].

para conseguir lo que desea, utilice el tipo de componente de matriz como su parámetro de tipo T, y declaran los parámetros y tipos de devolución como matrices de T.

+0

-1 para información incorrecta: 'Entero []' * es * un subtipo de 'Número []'. Por ejemplo, 'Number [] numbers = new Integer [] {1, 2, 3};' compila muy bien ... – meriton

+0

Bueno, eso es una locura, y es un agujero en el sistema de tipo java. \t Entero [] ints = new Entero [] {1, 2, 3}; \t Número [] numbers = ints; \t números [1] = nuevo Float (4); \t para (int x: ints) { \t \t System.out.println (x); \t} compila y arroja una ArrayStoreException en tiempo de ejecución. – PaulMurrayCbr

+1

Sí, la covarianza de matrices viola la sustituibilidad de liskov (a menos que tratemos a ArrayStoreExceptions como parte del contrato de matrices, como lo hace JLS). Sin embargo, la comprobación del tiempo de ejecución garantiza que Java permanezca segura durante el tiempo de ejecución. En cuanto a que sea "loco", ciertamente tiene derecho a su opinión, pero creo que centrarse únicamente en el vacío en el sistema de tipos es una visión bastante restringida. Las matrices son covariantes y se controlan en tiempo de ejecución. Los genéricos deben ser covariantes en cada sitio de uso y no se verifican en el tiempo de ejecución (lo que realmente permite la corrupción del montón). ¿Cuál es el mejor diseño? – meriton