Es Java Lista de múltiples tipos posibles

Patryk Krawczyk:

ayer me topé con un comportamiento extraño Java / primavera / IntelliJ que yo no era capaz de explicar.

Esta es una aplicación de la primavera de arranque hecho con jdk1.8.0_152.

Me encontré con este sencillo SQL para llenar mi DB:

CREATE TABLE TEST_ORGANIZATION
(
    ID NUMBER(19) NOT NULL,
    NAME VARCHAR(255) NOT NULL
);

INSERT INTO TEST_ORGANIZATION (ID, NAME) VALUES ('1', 'test1');
INSERT INTO TEST_ORGANIZATION (ID, NAME) VALUES ('2', 'test2');

Aquí está mi clase de entidad:

@Data
@NoArgsConstructor
@Entity
public class TestOrganization {

    @Id
    private Long id;

    @NotNull
    private String name;
}

Y mi APP Repositorio:

public interface TestOrganizationRepository extends JpaRepository<TestOrganization, Long> {

    @Query("SELECT new map(id as key, name as value) FROM TestOrganization")
    List<Map<String, String>> findAllAndMapById();
}

Y aquí es donde las cosas se confunde. He escrito una prueba de unidad de control para detectar los valores, pero resulta que no funciona en segundo afirman:

@Test
public void shouldGetDocumentByName() {
    List<String> values = testOrganizationRepository.findAllAndMapById()
            .stream()
            .flatMap( m -> m.values().stream() )
            .collect( Collectors.toList() );

    assertThat( values ).isNotEmpty();
    assertThat( values ).allMatch( n -> n instanceof String );
}

Cuando se depura con IntelliJ, que muestra los valores de esta manera:

introducir descripción de la imagen aquí

¿Cómo es esto posible? ¿Por qué soy capaz de tener valores a largo plazo de una lista de cuerda?

También:

 values.add(1L) // fails to compile
 values.get(0).getClass().name // returns java.lang.String
 values.get(1).getClass().name // returns java.lang.Long
Sergii Bishyr:

Esto es posible porque el tipo de borrado en Java. En pocas palabras, esto significa que en el tiempo de ejecución de Java no sabe acerca de su tipo genérico, por lo que cualquier Listobjeto opera con Objecttipo. Los medicamentos genéricos se hacen para tener la seguridad de tipo de compilación. Pero se puede leer sobre el tipo de borrado en más detalles, por ejemplo aquí .

El mismo comportamiento se puede emular en solitario:

public static void main(String[] args) {
    List<String> list = new ArrayList<>();
    addToList(list);
    System.out.println(list);
}

private static void addToList(List list) {
    list.add(1L);
    list.add(42);
    list.add("String");
    list.add(new Runnable() {
        @Override
        public void run() {}
    });
}

Este código funciona bien siempre y cuando no se trate de operar con las entradas de la lista como una Cuerdas. Pero cuando se agrega algo como:

for (String s : list) {
    System.out.println(s);
}

Obtendrá java.lang.ClassCastException.

Así que en tiempo de compilación, se trabaja con List<String>, pero en el tiempo de ejecución, Java sólo conoce List.

Supongo que te gusta

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