簡體   English   中英

Java泛型類型問題

[英]Java generic type issue

考慮以下簡化示例:

package com.test;

class B<S> {
    B(Class<S> clazz) {}
}

class A<T> {
    class SubB extends B<SubB> {
        SubB() {
            super(SubB.class);
        }
    }
}

盡管 IntelliJ 沒有顯示任何錯誤(就像存在編譯錯誤時通常那樣),但啟動程序時的實際編譯以位於super(SubB.class);錯誤結束super(SubB.class);

錯誤:(8, 23) java:不兼容的類型: java.lang.Class<com.test.A.SubB>無法轉換為java.lang.Class<com.test.A<T>.SubB>

我很好奇,為什么會這樣? 我怎么能解決呢?

編譯是使用 AdoptOpenJDK 11 完成的。

這種行為的原因有點復雜。 考慮java.util.List.class ,它的類型為Class<java.util.List> ,而不是Class<java.util.List<?>> 這是類文字的限制。

在您的示例中, SubB.class的類型為Class<com.test.A.SubB> ,同樣具有 SubB 的原始類型。 但是構造函數需要某種類型的Class<com.test.A<T>.SubB>

這就是為什么我們需要將文字轉換為所需的類型:

super((Class<SubB>) (Class<?>) SubB.class);

這將產生警告,但快速檢查將表明沒有什么可擔心的。

我覺得這很有趣。

這里的問題是,當你聲明這個時:

class A<T> {

    class SubB extends B<SubB> {
        SubB() {
            super...
        }
    }
}

B<SubB>實際上是B<A<T>.SubB> (我什至不知道這是可能的)。 這很容易為javap證明 thx(只需反編譯該類並親自查看)。 一旦你把它寫成“長”形式:

class A<T> {
    class SubB extends B<A<T>.SubB> {
        SubB() {
            super(....);
        }
    }
}

它開始變得更有意義。

理想情況下,要使其正常工作,您必須能夠編寫:

super(A<T>.SubB.class);

但是 java 不允許這樣做, .class只能在原始類型上調用。

最好的方法是在這里明確:

class A<T> {
    class SubB extends B<A.SubB> {
        SubB() {
            super(SubB.class);
        }
    }
}

在說:我正在使用A的原始類型: B<A.SubB>

在泛型中,繼承並不像我們通常所知道的那樣,即讓我們舉個例子類ArrayList<String>不是List的子類。 List<String>List

同樣在泛型中,您通常不會輕易得到編譯錯誤,因為在編譯期間泛型類型被轉換為它們的原始類型。

因此,我們需要按照@JohannesKuhn 所述進行轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM