É Java lista de vários tipos possíveis

Patryk Krawczyk:

ontem me deparei com algum comportamento estranho Java / Primavera / IntelliJ que eu não era capaz de explicar.

Esta é uma aplicação de Primavera Bota feito com jdk1.8.0_152.

Corri esse SQL simples para preencher o meu 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');

Aqui está minha classe Entity:

@Data
@NoArgsConstructor
@Entity
public class TestOrganization {

    @Id
    private Long id;

    @NotNull
    private String name;
}

E meu Repository JPA:

public interface TestOrganizationRepository extends JpaRepository<TestOrganization, Long> {

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

E é aí que as coisas ficam confusas. Eu escrevi um teste de unidade simples para verificar se os valores, mas acaba por falhar na segunda assert:

@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 );
}

Quando a depuração com IntelliJ, mostra valores como este:

digite descrição da imagem aqui

Como isso é possível? Por que eu sou capaz de ter valores longas dentro de uma lista de corda?

Além disso:

 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:

Isso é possível por causa do tipo de apagamento em Java. Em suma, isso significa que no tempo de execução Java não sabe sobre o seu tipo genérico, portanto, qualquer Listobjeto opera com Objecttipo. Os genéricos são feitas para ter a segurança do tipo de compilação. Mas você pode ler sobre o tipo de apagamento em mais detalhes, por exemplo aqui .

O mesmo comportamento que você pode emular por si mesmo:

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 fina funciona, desde que você não tente operar com as entradas da lista como Strings. Mas quando você adiciona algo como:

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

Você vai ter java.lang.ClassCastException.

Assim, em tempo de compilação, você trabalha com List<String>, mas no tempo de execução, Java só conhece List.

Acho que você gosta

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