Diferencia entre Lista, Lista , Lista , Lista y Lista

¿Cuáles son las diferencias entre List , List , List , List y List ?

Ahora no hago esta pregunta a ciegas, así que por favor no cierren este hilo. Déjame primero introducir el código base:

 private static List names = new ArrayList(); static { names.add("Tom"); names.add("Peter"); names.add("Michael"); names.add("Johnson"); names.add("Vlissides"); } public static void test(List set){ System.out.println(set); } public static void main(String args[]){ test(names); } 

Yo entiendo eso:

1. List : es un tipo sin procesar, por lo tanto, no es typesafe . Solo generará un error de tiempo de ejecución cuando la conversión sea incorrecta. Queremos un error de tiempo de comstackción cuando el lanzamiento es malo. No recomendado para usar.

2. List : Es un comodín ilimitado. Pero no estoy seguro de para qué sirve esto? Entonces si cambio el método de test a

 public static void test(List set){ System.out.println(set); } 

todavía funciona bien Si puede explicar el uso de esto, lo agradecería enormemente.

EDITAR : Si hago esto:

 public static void test(List set){ set.add(new Long(2)); //--> Error set.add("2"); //--> Error System.out.println(set); } 

pero si cambio la test a esto:

 public static void test(List set){ set.add(new Long(2)); //--> Error set.add("2"); //--> Work System.out.println(set); } 

3. List :

 public static void test(List set){ //T cannot be resolved System.out.println(set); } 

Supongo que no entiendo esta syntax. Vi algo así y funciona:

 public  T[] toArray(T[] a){ return a; } 

Por favor, explícame esto por favor? A veces, veo , o , o , . ¿Son todos iguales o representan algo diferente?

4. List

 public static void test(List set){ System.out.println(set); } 

Luego recibí el error. The method test(List) is not application for the argument List para el siguiente código. Estoy confundido. Pensé que String era un subconjunto de Object ?

 public static void main(String args[]){ test(names); } 

EDITAR: Si pruebo esto

 test((List)names); 

luego obtuve Cannot cast from List to List

1) Correcto

2) Puede pensar en esa como una lista de “solo lectura”, donde no le importa el tipo de elementos. Podría, por ejemplo, ser utilizado por un método que devuelve la longitud de la lista.

3) T, E y U son lo mismo, pero las personas tienden a usar, por ejemplo, T para tipo, E para Elemento, V para valor y K para clave. El método que comstack dice que tomó una matriz de cierto tipo y devuelve una matriz del mismo tipo.

4) No puedes mezclar naranjas y manzanas. Usted podría agregar un Objeto a su lista de Cadenas si pudiera pasar una lista de cadenas a un método que espera listas de objetos. (Y no todos los objetos son cadenas)

Para la última parte: Aunque String es un subconjunto de Object, pero List no se hereda de List .

La notación List Significa “una lista de algo (pero no digo qué)”. Como el código en test funciona para cualquier tipo de objeto en la lista, esto funciona como un parámetro de método formal.

El uso de un parámetro de tipo (como en el punto 3) requiere que se declare el parámetro de tipo. La syntax de Java para eso es poner al frente de la función. Esto es exactamente análogo a declarar nombres de parámetros formales a un método antes de usar los nombres en el cuerpo del método.

En cuanto a la List no acepta una List , tiene sentido porque una String no es un Object ; es una subclase de Object . La solución es declarar public static void test(List set) ... Pero luego el extends Object es redundante, porque cada clase extiende directa o indirectamente el Object .

La razón por la que no puede convertir List en List es que le permitirá violar las restricciones de List .

Piensa en el siguiente escenario: si tengo una List , se supone que solo debe contener objetos de tipo String . (Que es una clase final )

Si puedo convertirlo en una List , entonces eso me permite agregar Object a esa lista, violando así el contrato original de List .

Por lo tanto, en general, si la clase C hereda de la clase P , no se puede decir que GenericType también hereda de GenericType

.

NB Ya he comentado esto en una respuesta anterior, pero quería ampliarlo.

Aconsejaría leer rompecabezas de Java. Explica bastante bien la herencia, los generics, las abstracciones y los comodines en las declaraciones. http://www.javapuzzlers.com/

En su tercer punto, “T” no puede ser resuelto porque no está declarado, generalmente cuando declara una clase genérica puede usar “T” como el nombre del parámetro de tipo encuadernado , muchos ejemplos en línea que incluyen los tutoriales de Oracle usan “T” como el nombre del parámetro tipo, digamos por ejemplo, declaras una clase como:

 public class FooHandler { public void operateOnFoo(T foo) { /*some foo handling code here*/} } 

usted está diciendo que FooHandler's método FooHandler's operateOnFoo espera una variable de tipo “T” que se declara en la statement de clase en sí, con esto en mente, puede agregar más tarde otro método como

 public void operateOnFoos(List foos) 

en todos los casos, ya sea T, E o U, todos los identificadores del parámetro tipo, incluso puede tener más de un parámetro de tipo que utiliza la syntax

 public class MyClass {} 

en su cuarta ponint aunque efectivamente Sting es un sub tipo de Object, en las clases de generics no existe tal relación, List no es un subtipo de List son dos tipos diferentes desde el punto de vista del comstackdor, esto se explica mejor en esta entrada de blog

El problema 2 está bien, porque “System.out.println (set);” significa “System.out.println (set.toString ());” set es una instancia de List, por lo que el comstackdor llamará a List.toString ();

 public static void test(List set){ set.add(new Long(2)); //--> Error set.add("2"); //--> Error System.out.println(set); } Element ? will not promise Long and String, so complier will not accept Long and String Object public static void test(List set){ set.add(new Long(2)); //--> Error set.add("2"); //--> Work System.out.println(set); } Element String promise it a String, so complier will accept String Object 

Problema 3: estos símbolos son los mismos, pero puedes darles la especificación de differet. Por ejemplo:

 public  void p(T t, E e) {} 

Problema 4: La recostackción no permite la covarianza del parámetro de tipo. Pero la matriz permite la covarianza.

Hablemos de ellos en el contexto de la historia de Java;

  1. List :

La lista significa que puede incluir cualquier Objeto. La lista estaba en la versión anterior a Java 5.0; Java 5.0 presentó la Lista, por compatibilidad con versiones anteriores.

 List list=new ArrayList(); list.add(anyObject); 
  1. List :

? significa Objeto desconocido, no cualquier Objeto; el comodín ? la introducción es para resolver el problema creado por Generic Type; ver comodines ; pero esto también causa otro problema:

 Collection c = new ArrayList(); c.add(new Object()); // Compile time error 
  1. List< T> List< E>

Significa statement genérica en la premisa de ningún tipo T o E en su proyecto Lib.

  1. List< Object> significa parametrización genérica.

Tienes razón: String es un subconjunto de Object. Dado que String es más “preciso” que Object, debe convertirlo para usarlo como argumento para System.out.println ().

Teoría

String[] se puede convertir a Object[]

pero

List no se puede convertir a List .

Práctica

Para las listas es más sutil que eso, porque en tiempo de comstackción, el tipo de un parámetro List pasado a un método no está marcado. La definición de método también podría decir List : Desde el punto de vista del comstackdor es equivalente. Esta es la razón por la cual el ejemplo # 2 del PO da errores de tiempo de ejecución no comstack errores.

Si maneja un parámetro List pasado a un método cuidadosamente para no forzar una verificación de tipo en ningún elemento de la lista, entonces puede hacer que su método se defina usando List pero de hecho acepte una List parámetro del código de llamada.

A. Entonces, este código no dará errores de comstackción o tiempo de ejecución y realmente (¿y quizás sorprendentemente?) Funcionará:

 public static void test(List set) { List params = new List<>(); // This is a List params.addAll(set); // A String can be added to List params.add(new Long(2)); // A Long can be added to List System.out.println(params); } public static void main(String[] args) { List argsList = Arrays.asList(args); test(argsList); // The object passed is a List } 

B. Este código dará un error de tiempo de ejecución:

 public static void test(List set) { List params = set; // Surprise! Runtime error set.add(new Long(2)); // Also a runtime error System.out.println(set); } public static void main(String[] args) { List argsList = Arrays.asList(args); test(argsList); } 

C. Este código dará un error de tiempo de ejecución ( java.lang.ArrayStoreException: java.util.Collections$UnmodifiableRandomAccessList Object[] ):

 public static void test(Object[] set) { Object[] params = set; // This is OK even at runtime params[0] = new Long(2); // Surprise! Runtime error System.out.println(params); } public static void main(String[] args) { test(args); } 

En B, el set parámetros no es una List tipeada en tiempo de comstackción: el comstackdor la ve como List . Hay un error de tiempo de ejecución porque en el tiempo de ejecución, set convierte en el objeto real pasado de main() , y eso es una List . Una List no se puede convertir a List .

En C, el set parámetros requiere un Object[] . No hay ningún error de comstackción y ningún error de tiempo de ejecución cuando se llama con un objeto String[] como parámetro. Eso es porque String[] lanza a Object[] . Pero el objeto real recibido por test() sigue siendo String[] , no cambió. Entonces el objeto params también se convierte en String[] . ¡Y el elemento 0 de una String[] no se puede asignar a un Long !

(Espero tener todo aquí, si mi razonamiento es incorrecto, estoy seguro de que la comunidad me lo dirá).