El error acerca de la creación de conjunto de lista genérica en Java

maplemaple:

Primer Código :

List<Integer>[] array = (List<Integer>[]) new Object[size]; 

Se dará a la siguiente excepción:

java.lang.ClassCastException: class [Ljava.lang.Object; cannot be cast to class [Ljava.util.List; ([Ljava.lang.Object; and [Ljava.util.List; are in module java.base of loader 'bootstrap')

¿Por qué esta mal? Sólo sigo el eficaz Java Tercera Edición método Página del 132:

Segundo Código :

E[] array = (E[]) new Object[size];

Sin embargo, encontramos las siguientes obras de códigos

Tercer Código :

List<Integer>[] array = (List<Integer>[]) new List[size];

Mis preguntas:

  1. ¿Por primer código es incorrecto, pero se sugiere segundo código en Java eficaz ? ¿Hay que mal algo?

Por ejemplo: ¿por qué el siguiente código funciona bien, pero el primer código es incorrecto?

public class Test<E>{
    E[] array;
    public Test(){
        array = (E[]) new Object[10];
    }
    public E set(E x){
        array[0] = x;
        System.out.println(array[0]);
        return array[0];
    }

    public static void main(String[] args){
        Test<List<Integer>> test = new Test<>();
        List<Integer> list = new ArrayList<>();
        list.add(1);
        test.set(list);
    }
}
  1. ¿Alguien puede explicar por qué el tercer código es correcto, pero el siguiente código es incorrecto?

Cuarto Código :

List<Integer>[] array = new List<Integer>[size];

TiiJ7:

primer Código

List<Integer>[] array = (List<Integer>[]) new Object[size]; 

La razón por la falla del primer código se debe a que la fundición no cambia el tipo real de la matriz, que sólo hace que el compilador acepta el código como válido. Imagínese si usted tenía otra referencia a la tabla de objeto subyacente:

final int size = 2;
Object[] objectArr = new Object[size];
List<Integer>[] integerArr = (List<Integer>[]) objectArr; // Does not work
objectArr[0] = "foobar";
List<Integer> i = integerArr[0]; // What would happen ??

El código anterior compila bien, ya que están obligando al compilador que aceptarlo con el elenco. Pero ya se puede ver por qué sería un problema para el reparto de trabajo en tiempo de ejecución: que terminaría con una List<Integer>[]que ahora contiene una String, que no tiene sentido. Así que el lenguaje no permite esto.

segundo Código

E[] array = (E[]) new Object[size];

Genéricos en Java son un tanto extraño. Por diversas razones, tales como la compatibilidad hacia atrás, los genéricos son, básicamente, borrados por el compilador y serán (en su mayoría) no aparecen en el código compilado ( Tipo Erasure ). En su lugar, se utilizará una serie de reglas ( JLS especificaciones ) para determinar qué tipo se debe utilizar en el código en su lugar. Para un genérico unbouded básica; este tipo será Object. Por lo tanto, suponiendo que no hay corresponda en E, el segundo código se cambia por el compilador para esto:

 Object[] array = (Object[]) new Object[size];

Así que ya que ambos conjuntos tienen el mismo tipo exacto después del borrado, no hay ningún problema en tiempo de ejecución y el elenco es básicamente redundante.

Vale la pena señalar que esto sólo funciona siempre y cuando Eno está acotada. Por ejemplo, esto se producirá un error en tiempo de ejecución con un ClassCastException:

public static <E extends Number> void genericMethod() {
    final int size = 5;
    E[] e = (E[]) new Object[size];
}

Esto es así porque Ese borrará a Number, y obtendrá el mismo problema que el primer código:

Number[] e = (Number[]) new Object[size];

Es importante tener en cuenta el borrado cuando se trabaja con código. De lo contrario usted puede funcionar en situaciones en las que el código actúa diferente de lo que espera. Por ejemplo, el siguiente código compila y ejecuta sin excepciones :

public static <E> void genericMethod(E e) {
    final int size = 2;
    Object[] objectArr = new Object[size];
    objectArr[0] = "foobar";

    @SuppressWarnings("unchecked")
    E[] integerArr = (E[]) objectArr;
    integerArr[1] = e;

    System.out.println(Arrays.toString(integerArr));
    System.out.println(e.getClass().getName());
    System.out.println(integerArr.getClass().getName());
}

public static void main(String[] args) {
    genericMethod(new Integer(5)); // E is Integer in this case
}

tercer Código

List<Integer>[] array = (List<Integer>[]) new ArrayList[size];

Al igual que en el caso anterior, el tercer código se borrará la siguiente:

 List[] array = (List[]) new ArrayList[size];

Lo cual es ningún problema porque ArrayListes un subtipo de List.

cuarto Código

List<Integer>[] array = new ArrayList<Integer>[size];

La voluntad por encima se compila. La creación de matrices con un tipo que tiene un tipo genérico parámetro es explícitamente anulado por la especificación :

Es un error de tiempo de compilación si el tipo de componente de la matriz siendo inicializado no es reifiable (§4.7).

Un tipo con un parámetro genérico que no es un comodín sin límites ( ?) no adaptarse a cualquier condición para reifiability :

Un tipo es reifiable si y sólo si uno de estos procedimientos tiene:

  • Se refiere a una declaración de tipo de clase o interfaz no genérico.
  • Es un tipo parametrizado en el que todos los argumentos de tipo son comodines no acotados (§4.5.1).
  • Es un tipo crudo (§4.8).
  • Es un tipo primitivo (§ 4.2).
  • Es un tipo de matriz (§10.1) cuyo tipo de elemento es reifiable.
  • Es un tipo anidado, donde, para cada tipo T separado por un "", en sí T es reifiable.

Supongo que te gusta

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