ventajas sistemas qué operativos metodos metodo listas ligada ficheros fichero espacio enlazadas encadenada disco desventajas debe contigua contener bloques asignación asignacion archivos java generics generic-method

java - sistemas - metodos de asignación de ficheros



Asignación de lista de enteros a una lista de cadenas (5)

Estaba aprendiendo genéricos en Java y me acerqué a una pieza de código muy interesante. Sé que en Java es ilegal agregar una lista de un tipo a otro.

List<Integer> integerList = new ArrayList<Integer>(); List<String> stringList=integerList;

Entonces en la segunda línea obtengo un error de tiempo de compilación.
Pero si creo un método genérico dentro de una clase como esta,

class GenericClass <E>{ void genericFunction(List<String> stringList) { stringList.add("foo"); } // some other code }

Y en la clase principal, llame al método con la lista Integer. No obtengo ningún error.

public class Main { public static void main(String args[]) { GenericClass genericClass=new GenericClass(); List<Integer> integerList= new ArrayList<Integer>(); integerList.add(100); genericClass.genericFunction(integerList); System.out.println(integerList.get(0)); System.out.println(integerList.get(1)); } }

Salida
100
foo

¿Por qué no recibo ningún error?


Esto sucede, porque (bastante sorprendente para mí) has desactivado la comprobación de tipos genéricos para toda la clase GenericClass .

Debes ser consciente de que estás, en primer lugar, construyendo una clase genérica sin argumento tipo aquí:

GenericClass genericClass = new GenericClass();

Y aparentemente, debido a esto, su siguiente código:

class GenericClass<E> { void genericFunction(List<String> stringList) { stringList.add("foo"); } // some other code }

ha sido refinado para:

class GenericClass { void genericFunction(List stringList) { stringList.add("foo"); } // some other code }

Tenga en cuenta que List también se convirtió en un tipo crudo, lo que me resulta bastante sorprendente.

Puede encontrar la respuesta completa aquí, haciendo referencia al JLS: https://.com/a/662257/2057294 como lo explicó Jon Skeet.

Creo que es justo que esto suceda (aunque no es lo que esperaría), porque si decide usar tipos sin formato, se supone que está utilizando Java 4 o una versión más baja y no tiene acceso alguno a los genéricos de ninguna manera, por lo que tampoco puede proporcionarles métodos que no incluyan el tipo genérico de la clase que se borró.


Has mezclado Genérico con el tipo sin procesar . Se compilará bien, pero en tiempo de ejecución podría fallar porque la información genérica se pierde en el tiempo de ejecución.

Generic debería usarse para rastrear dichos errores en tiempo de compilación.

Se explica mejor en ¿Qué es un tipo sin procesar y por qué no deberíamos usarlo? en detalle.

Advertencia: Seguridad tipo: El método genericFunction(List) pertenece al tipo GenericClass . Las referencias al tipo genérico GenericClass<E> deben parametrizar.

Si tiene dos métodos con el mismo nombre con un tipo de Lista genérico diferente, se genera un error de tiempo de compilación. El compilador no puede resolver el tipo genérico en el caso de los argumentos del método que pueden ser probados por el código de muestra siguiente.

Código de muestra: (error del compilador, no es un método válido sobrecargado)

void genericFunction(List<String> stringList){...} void genericFunction(List<Integer> stringList){...}

Haga algunos cambios y vuelva a intentarlo:

class GenericClass <E>{ void genericFunction(List<E> stringList) { ... } // some other code } ... GenericClass<String> genericClass=new GenericClass<String>(); // Genreric object List<Integer> integerList= new ArrayList<Integer>(); integerList.add(100); genericClass.genericFunction(integerList); // compile time error

Crea métodos de tal manera

class GenericClass<E> { private List<E> list = new ArrayList<E>(); public void addAll(List<E> newList) { list.addAll(newList); } public void add(E e) { list.add(e); } public E get(int index) { return list.get(index); } // some other code }


No obtiene ningún error de tiempo de compilación porque usa GenericClass<E> de forma cruda:

GenericClass genericClass = new GenericClass(); ,

Prácticamente le está diciendo al compilador que desactive las comprobaciones de tipo genérico porque no le importa.

Entonces el :

void genericFunction(List<String> stringList)

se convierte

void genericFunction(List stringList) para el compilador.

Puede intentar lo siguiente: GenericClass<?> genericClass , y notará inmediatamente que el compilador conoce el mal uso de los genéricos y le mostrará el error:

The method genericFunction(List<String>) in the type GenericClass<capture#1-of ?> is not applicable for the arguments (List<Integer>)

Además, si intenta obtener la clase del objeto de 2ª posición en tiempo de ejecución:

System.out.println(integerList.get(1).getClass());

, obtendrá un error: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer .


Para agregar a las otras respuestas.

De hecho, está mezclando un tipo en bruto (no parametrizado) con tipos parametrizados que causa una pérdida de tipo y un argumento aparentemente correcto que pasa a genericFunction cuando las comprobaciones de seguridad del tipo no deberían permitirse.

La pregunta sigue siendo por qué el tipo List<String> se pierde en un objeto GenericClass no GenericClass . La razón por la que el compilador "desactiva" la verificación de tipo en su caso es el mecanismo de borrado de tipo , que dice (en términos simples) que su objeto sin procesar pertenece a una clase con los siguientes contenidos:

class GenericClass { void genericFunction(List stringList) { stringList.add("foo"); } // some other code }

Que como ve no hace ninguna verificación de tipo alguno sobre el contenido de la lista que se está pasando (borra los parámetros de tipo en todas partes ). Aún más, la borradura de tipo también borra su tipo parametrizado de la variable integerList , lo que lo hace completamente adecuado como argumento para su método genericFunction .

Por lo tanto, como señalaron otros, siempre es mejor ayudar a Java a mantener intactos sus mecanismos seguros de verificación de tipos:

GenericClass<?> genericClass=new GenericClass<Integer>(); List<Integer> integerList= new ArrayList<Integer>(); integerList.add(100); // no-no here genericClass.genericFunction(integerList); System.out.println(integerList.get(0)); System.out.println(integerList.get(1));

Pero, si lo haces, el compilador hace su trabajo y te aplica bazooka.

Lea más sobre el borrado de tipos aquí . Es una buena característica que permite la comprobación de tipos genéricos al tiempo que mantiene la compatibilidad con las versiones anteriores a los genéricos de Java.


class GenericClass <E>{ void genericFunction(List<String> stringList) { stringList.add("foo"); } // some other code }

cuando escribe justo después del nombre de la clase. Especifica los parámetros de tipo. Es una funcionalidad genérica. Esto introduce la variable de tipo, E, que puede usarse en cualquier lugar dentro de la clase. Una variable de tipo puede ser cualquier tipo no primitivo que especifique: cualquier tipo de clase, cualquier tipo de interfaz, cualquier tipo de matriz o incluso otra variable de tipo.