Inesperada cadena de añadir a la lista <enteros>

John :

No entiendo cómo el mango compilador es el siguiente código como se da salida a la prueba , mientras que yo estaba esperando un error.

List<Integer> b = new ArrayList<Integer>();
List a = b;
a.add("test");
System.out.println(b.get(0));

Tenía la esperanza de que alguien me podría decir las exactas medidas que el compilador pasa por al ejecutar el código para que pueda entender la salida. Mi opinión actual es que:

  1. El compilador comprueba durante el tiempo de compilación si un método Add que soporta el tipo de argumento existe en la lista de clases que es add (Object e) como su prima-mecanografiado.
  2. Sin embargo, durante el tiempo de ejecución se intenta invocar add (Object e) del objeto real List <Integer> que no mantenga este método como el objeto real no está en carne viva-escrito y en su lugar tiene el método add (entero e) .

Si no hay ningún método add (Object e) en el objeto real List <Integer> ¿cómo se sigue de alguna manera agregar una cadena a la lista de números enteros?

Ray Toal:

Estás muy cerca. Los controles de tiempo de compilación todas dan resultado:

aes de tipo Listpor lo que la llamada

a.add("test");

filtra hacia fuera. bes de (tiempo de compilación) tipo ArrayList<Integer>tan

b.get(0)

cheques hacia fuera también. Tenga en cuenta que los cheques se hacen sólo contra los tipos en tiempo de compilación de las variables . Cuando el compilador ve a.add("test")que no , no sabe el valor de tiempo de ejecución del objeto referenciado por la variable a. En general, lo que realmente no puede (no hay un resultado en informática teórica sobre esto), aunque el análisis de tipo de flujo de control puede coger muchas cosas. Lenguajes como mecanografiado pueden hacer cosas increíbles en tiempo de compilación.

Ahora usted podría suponer que al tiempo de ejecución de este tipo de cosas podrían ser revisados. Por desgracia, en Java no pueden. Java borra tipos genéricos. Encuentra un artículo sobre Java Tipo de borrado de los detalles morbosos. El TL; DR es que una List<Integer>en tiempo de compilación se convierte en una prima Listen tiempo de ejecución. La JVM no tiene manera de los genéricos "cosificar" (aunque otros lenguajes!) Por lo que cuando se introdujeron los genéricos, se tomó la decisión de que Java acaba de borrar los tipos genéricos. Por lo tanto en tiempo de ejecución, no hay ningún problema teclee el código.

Vamos a echar un vistazo al código compilado:

   0: new           #2                  // class java/util/ArrayList
   3: dup
   4: invokespecial #3                  // Method java/util/ArrayList."<init>":()V
   7: astore_1
   8: aload_1
   9: astore_2
  10: aload_2
  11: ldc           #4                  // String test
  13: invokeinterface #5,  2            // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
  18: pop
  19: getstatic     #6                  // Field java/lang/System.out:Ljava/io/PrintStream;
  22: aload_1
  23: iconst_0
  24: invokeinterface #7,  2            // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
  29: invokevirtual #8                  // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
  32: return

Aquí se puede ver directamente que no hay ningún tipo de controles en tiempo de ejecución. Por lo tanto, la respuesta completa (pero al parecer impertinente) a su pregunta es que los tipos Java sólo los controles en tiempo de compilación en base a los tipos de las variables que se borran (conocido en tiempo de compilación), pero los parámetros de tipo genérico y el código se ejecuta sin ellos.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=181418&siteId=1
Recomendado
Clasificación