2008-10-09 21 views
15

¿Qué estructura de datos especifica la siguiente declaración?Java Generics Sintaxis para matrices

List<ArrayList>[] myArray; 

creo que debería declarar una matriz en donde cada elemento es un List (por ejemplo, un LinkedList o un ArrayList) y requieren que cada List contienen ArrayList objetos.

Mi razonamiento:

List<String> someList;    // A List of String objects 
List<ArrayList> someList;   // A List of ArrayList objects 
List<ArrayList>[] someListArray; // An array of List of ArrayList objects 

Después de ejecutar algunas pruebas, que determinó que acepta una matriz donde cada elemento es un objeto LinkedList y no especifica lo que contienen los objetos ListaEnlazada.

Así List<ArrayList> especifica lo que el List debe contener, pero List<ArrayList>[] especifica cómo se debe implementar la List.

¿Echo de menos algo?

Aquí están mis pruebas.

import java.util.ArrayList; 
import java.util.List; 
import java.util.LinkedList; 


public class Generics1 { 

    public static void main(String[] args) { 

     List<ArrayList>[] someListArray; 

     someListArray = getArrayWhereEachElementIsAnArrayListObject(); 
     // Why does this satisfy the declaration? 
     //someListArray[0] => ArrayList object holding Strings 

     someListArray= getArrayWhereEachElementIsAListOfArrayListObjects(); 
     //someListArray[0] => ArrayList object holding ArrayList objects 

    } 

    public static List[] getArrayWhereEachElementIsAnArrayListObject() { 
     List[] arrayOfLists = new ArrayList[2]; 
     arrayOfLists[0] = getStringList(); 
     arrayOfLists[1] = getIntegerList(); 
     return arrayOfLists; 
    } 

    public static List[] getArrayWhereEachElementIsAListOfArrayListObjects() { 

     List list1 = new ArrayList(); 
     list1.add(getArrayList()); 

     List list2 = new ArrayList(); 
     list2.add(getArrayList()); 

     List[] arrayOfListsOfArrayLists = new ArrayList[2]; 
     arrayOfListsOfArrayLists[0] = list1; 
     arrayOfListsOfArrayLists[1] = list2; 
     return arrayOfListsOfArrayLists; 
    } 

    public static List getStringList() { 
     List stringList= new ArrayList(); 
     stringList.add("one"); 
     stringList.add("two"); 
     return stringList; 
    } 


    public static List getIntegerList() { 
     List intList= new ArrayList(); 
     intList.add(new Integer(1)); 
     intList.add(new Integer(2)); 
     return intList; 
    } 

    public static ArrayList getArrayList() { 
     ArrayList arrayList = new ArrayList() ; 
     return arrayList; 
    } 
} 
+0

Cada elemento probablemente fue asignado como myArray [0] = new ArrayList (); –

+0

Parece que todos los argumentos de tipo genérico fueron eliminados de su muestra de código. Esto habría sucedido porque lo incluyó en etiquetas PRE, y el sitio interpretó los argumentos de tipo como etiquetas HTML malformadas o prohibidas (según Q31657). Deberías poder editarlo. –

Respuesta

8

Sr. Josh Bloch dice:

"Prefiero listas a la matriz porque matrices son covariantes y los genéricos son invariante'

Usted tal vez podría hacer:

List<List<ArrayList>> someListArray; 

Esto puede dar un poco de pe Rformance Hit (ni siquiera es notable apostar), pero obtendrá un mejor tipo de seguridad en tiempo de compilación.

pero creo que la pregunta debería ser más acerca de "por qué" necesita esto?

+0

No "necesito" esto. Me encontré con la declaración durante el mantenimiento del código y estaba tratando de entender lo que significaba la declaración. – user19685

+0

Bien, eso es genial, solo estaba verificando ... – Mark

5
List<ArrayList>[] someListArray; 

le da una:

array of (List of ArrayList) 

embargo, debido a las limitaciones en los genéricos de Java (bug 6229728) sólo se puede crear realmente:

array of List 

y lo echó:

List<ArrayList>[] someListArray = (List<ArrayList>[]) new List[5]; 
0

Usted es co rrect al decir:

Después de ejecutar algunas pruebas, determiné que la declaración significa una matriz donde cada elemento es un objeto ArrayList.

ejecución de este código

List<ArrayList>[] myArray = new ArrayList[2]; 

myArray[0] = new ArrayList<String>(); 
myArray[0].add("test 1"); 

myArray[1] = new ArrayList<String>(); 
myArray[1].add("test 2"); 

print myArray; 

Produce este resultado:

{["test 1"], ["test 2"]} 

Me parece no hay ninguna razón para no hacer esto en su lugar:

List<ArrayList> myArray = new ArrayList<ArrayList>(); 
0

lista es una lista capaz de contener objetos ArrayList La lista [] es una matriz de dichas listas

Entonces, lo que usted dijo es que una matriz de (Lista de objeto ArrayList) es CORRECTA.

¿Puede compartir cuáles fueron sus pruebas? Mis propias pruebas son diferentes

import java.util.*; 

public class TestList { 
    public static void main(String ... args) { 
     class MySpecialLinkedList extends LinkedList<ArrayList<Integer>> { 
      MySpecialLinkedList() { 

      } 

      public void foo() { 

      } 


      public Object clone() 
      { 
       return super.clone(); 
      } 
     } 

     List<ArrayList<Integer>> [] someListArray = new MySpecialLinkedList[10]; 
     for (int i = 0; i < 10; ++i) { 
      someListArray[i] = new LinkedList<ArrayList<Integer>>(); 
      for (int j = 0; j < 20; ++j) { 
       someListArray[i].add(new ArrayList<Integer>()); 
       for (int k = 0; k < 30; ++k) { 
        someListArray[i].get(j).add(j); 
       } 
      } 
     } 
    } 
} 
0

Después de ejecutar algunas pruebas adicionales, creo que tengo mi respuesta.

Lista <ArrayList> [] sí especifica una matriz donde cada elemento es una lista de objetos ArrayList.

Al compilar el código como se muestra a continuación, se reveló por qué mi primera prueba me permitió usar una matriz donde cada elemento es una lista de cualquier cosa. El uso de los tipos de devolución de Lista [] y Lista en los métodos que pueblan las matrices no proporcionó al compilador suficiente información para prohibir las asignaciones. Pero el compilador emitió advertencias sobre la ambigüedad.

Desde el punto de vista del compilador, un método que devuelve una Lista [] podría devolver una lista (que cumple la declaración) o no. De forma similar, un método que devuelve una Lista puede devolver o no una ArrayList.

Aquí fue la salida del compilador:

javac Generics2.java -Xlint: Desactivada

 
Generics2.java:12: warning: [unchecked] unchecked conversion 
found : java.util.List[] 
required: java.util.List<java.util.ArrayList>[] 
     someListArray = getArrayWhereEachElementIsALinkedListObject(); 
                   ^
Generics2.java:16: warning: [unchecked] unchecked conversion 
found : java.util.List[] 
required: java.util.List<java.util.ArrayList>[] 
     someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects(); 

Éstos son mis pruebas.

 
import java.util.ArrayList; 
import java.util.List; 
import java.util.LinkedList; 


public class Generics2 { 

    public static void main(String[] args) { 

     List<ArrayList>[] someListArray; 

     someListArray = getArrayWhereEachElementIsALinkedListObject(); 
     // Why does this satisfy the declaration? 
     //someListArray[0] => LinkedList object holding Strings 

     someListArray= getArrayWhereEachElementIsAListOfLinkedListObjects(); 
     //someListArray[0] => LinkedList object holding LinkedList objects 

    } 

    public static List[] getArrayWhereEachElementIsALinkedListObject() { 
     List[] arrayOfLists = new LinkedList[2]; 
     arrayOfLists[0] = getStringLinkedListAsList(); 
     arrayOfLists[1] = getIntegerLinkedListAsList(); 
     return arrayOfLists; 
    } 

    public static List[] getArrayWhereEachElementIsAListOfLinkedListObjects() { 

     List list1 = new LinkedList(); 
     list1.add(new LinkedList()); 

     List list2 = new LinkedList(); 
     list2.add(new LinkedList()); 

     List[] arrayOfListsOfLinkedLists = new LinkedList[2]; 
     arrayOfListsOfLinkedLists[0] = list1; 
     arrayOfListsOfLinkedLists[1] = list2; 
     return arrayOfListsOfLinkedLists; 
    } 

    public static List getStringLinkedListAsList() { 
     List stringList= new LinkedList(); 
     stringList.add("one"); 
     stringList.add("two"); 
     return stringList; 
    } 


    public static List getIntegerLinkedListAsList() { 
     List intList= new LinkedList(); 
     intList.add(new Integer(1)); 
     intList.add(new Integer(2)); 
     return intList; 
    } 

} 
+0

debería poder editar su publicación original para incluir el código anterior, que sería mejor que publicarlo como respuesta – Jean

17

La respuesta es que las matrices solo pueden contener tipos reificados. Y las clases genéricas no se reifican. Es decir, el "tipo de tiempo de ejecución" de la lista <ArrayList> es simplemente List. Los genéricos se borran en el tiempo de ejecución (google "wall of erasure" para obtener más información).

Así que esto:

List<ArrayList>[] myArray 

realmente significa:

List[] myArray 

No hay forma de tipo seguro para declarar lo que estamos tratando de declarar. En general, te recomiendo que uses una lista en lugar de una matriz en este caso. Algunas personas han llegado a sugerir que las matrices deberían tratarse como tipos obsoletos ahora que tenemos genéricos. No puedo decir que esté dispuesto a llegar tan lejos, pero debería considerar si una colección es una alternativa mejor cada vez que se siente atraído por una matriz.

El libro Java Generics and Collections de Naftalin and Wadler es una referencia excelente para las preguntas que pueda tener sobre los genéricos. O, por supuesto, el Generics FAQ es su referencia canónica en línea.