[英]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.