Diferencia en el tipo de borrado de la lista [Int] y la Lista [entero]

Mario Galic:

¿Por qué List[scala.Int]tipo de borrado al List[Object]mismo tiempo Integeren List[java.lang.Integer]que parece ser preservado? Por ejemplo, javappara

object Foo {
  def fooInt: List[scala.Int] = ???
  def fooInteger: List[java.lang.Integer] = ???
}

salidas

public scala.collection.immutable.List<java.lang.Object> fooInt();
public scala.collection.immutable.List<java.lang.Integer> fooInteger();

donde vemos Integerque se conserva en el segundo caso. La documentación del estado

Reemplazar todos los parámetros de tipo de tipos genéricos con sus límites o Objectsi los parámetros de tipo son ilimitados.

Es esto quizás debido a la cláusula de "límites"? Si es así, en la que se especifica esta cota?

Eugene:

Estoy no un desarrollador Scala, tomar esto con un grano de sal. El borrado es el mismo:

public static scala.collection.immutable.List<java.lang.Object> fooInt();
descriptor: ()Lscala/collection/immutable/List;

public static scala.collection.immutable.List<java.lang.Integer> fooInt();
descriptor: ()Lscala/collection/immutable/List;

mirar el descriptorparámetro; esto es lo que se hace referencia en los sitios de llamadas a nivel de código de bytes.

Cuando sólo tiene que hacer javap, se "tramposos" un poco mirando el Signatureparámetro (leer más) para que se le muestra esta pequeña mentira inofensiva.

Ahora pensar en ello. Vamos a tomar este método y lo colocan en la clase A:

static List<Integer> test() {
    return null; // or whatever that is not the point
} 

compilamos ella, comparten el .classarchivo a otra persona. Que alguien más lo usa en esta forma: (sin llegar a tener el código fuente para A).

public void testMe() {
    Integer x = A.test().get(0);
}

Si nos fijamos en el byte de código, verá:

    5: invokeinterface #3,  2 // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
    10: checkcast     #4      // class java/lang/Integer

Hay una pregunta inmediata que tiene que surgir: ¿cómo saber acerca de Integer(a través de que checkcast) si se borran los genéricos? La respuesta es la opción Signatureque se genera cuando Ase compila, o en sus casos:

 ()Lscala/collection/immutable/List<Ljava/lang/Object;>; //fooInt
 ()Lscala/collection/immutable/List<Ljava/lang/Integer;>; // fooInteger

Esta Signatureinformación es la que se utiliza por el compilador para hacer cumplir la seguridad de tipos en callsites , a través de los controles de tiempo de ejecución; Si este campo no estaría presente - que habría sido imposible.

Ahora a por qué el Signaturede la scalacgenera Object(por lo tanto la seguridad de tipos cero para las personas que llaman) es algo que las direcciones duplicadas. He tratado de leer el tema y no es una lectura fácil que voy a ir con "Confío en ti".


Un poco más explicaciones: Signatureaparecido en java-5cuando los genéricos, donde añaden. Hasta entonces, todas las llamadas sitios donde hace referencia mediante descriptor, cambiantes que a Signaturecambio significaría que el código existente se rompería; por lo tanto nunca hecho. De este modo Signaturese convirtió en opcional y se utiliza de una manera diferente - para checkcast. Al menos esto es lo que estoy fuertemente inclinado a asumir :)

Supongo que te gusta

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