可能な複数の種類のJavaのリストです

Patryk Krawczyk:

昨日私が説明することができなかったことをいくつかの奇妙なのJava /春/ IntelliJの行動につまずきました。

これはjdk1.8.0_152で作られた春のブートアプリケーションです。

私は自分のDBを埋めるために、この単純なSQLを実行しました:

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');

ここに私のエンティティクラスがあります:

@Data
@NoArgsConstructor
@Entity
public class TestOrganization {

    @Id
    private Long id;

    @NotNull
    private String name;
}

そして、私の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();
}

物事が混乱取得する場所と、これはあります。私は値をチェックするための簡単なユニットテストを書いたが、それが判明した第二アサートに失敗します。

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

IntelliJのでデバッグする場合、それが示した値、このように:

ここでは、画像の説明を入力します。

これはどのように可能ですか?なぜ私は文字列のリストの中に長い値を持つことができるのですか?

また:

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

これは、Javaの型消去可能です。要するに、この手段は、実行時にJavaがあなたのジェネリック型を知っていないということなので、任意のListオブジェクトがで動作Objectタイプ。ジェネリック医薬品は、コンパイル型の安全性を持つように作られています。しかし、あなたは、たとえば、より詳細で型消去について読むことができますここで

自分でエミュレートすることができます同じ動作:

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() {}
    });
}

このコードは、文字列としてリストエントリで動作するようにしようとしない限りとして罰金を動作します。しかし、あなたのような何かを追加する場合:

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

あなたは取得しますjava.lang.ClassCastException

だから、コンパイル時に、あなたが働くList<String>が、実行時に、Javaは唯一知っていますList

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=187561&siteId=1