我怎樣才能得到這個類的型別?對于背景關系,我使用的是 modelMapper,我需要型別別 T 來從 S 轉換為 T。
@Component
public class A<T, S> {
private Class<T> tType;
private Class<S> sType;
@SuppressWarnings("unchecked")
public A() {
this.tType = (Class<T>) // some method to take the type
this.sType = (Class<S>) // some method to take the type
}
public T toModel(S regras) {
return modelMapper.map(regras, tType);
}
語境:
public class B{
@Autowired
private A<SomeClassX, SomeClassY> var;
// Some code
我已經嘗試了 N 種方式,我將“// some method to take type”放在其中,但沒有任何效果。例如:
@SuppressWarnings("unchecked")
public A() {
this.tType = (Class<T>) getGenericClassType(0);
this.sType = (Class<S>) getGenericClassType(1);
}
private Type getGenericClassType(int index) {
Type type = getClass().getGenericSuperclass();
while(!(type instanceof ParameterizedType)) {
if (type == null) {
return null;
}
if (type instanceof ParameterizedType) {
type = ((Class<?>) ((ParameterizedType) type).getRawType()).getGenericSuperclass();
} else {
type = ((Class<?>) type).getGenericSuperclass();
}
}
return ((ParameterizedType) type).getActualTypeArguments()[index];
}
或者
@SuppressWarnings("unchecked")
public A() {
this.tType = (Class<T>) GenericTypeResolver.resolveTypeArguments(getClass(), GenericConverter.class)[0];
this.sType = (Class<S>) GenericTypeResolver.resolveTypeArguments(getClass(), GenericConverter.class)[1];
}
uj5u.com熱心網友回復:
你不能。泛型是編譯器想象的虛構:編譯器使用它們來生成錯誤和注入強制轉換,然后將其全部洗掉。它不在類檔案中,因此在運行時不可用,因此,“我的 T 實際上是什么”的概念是不可能的。
有解決方法:
java.lang.Class
您當然可以將 jlClass 實體傳遞給建構式。您的代碼段使用非常不幸的名稱“A”和“B”,因為單大寫字母通常用于型別變數,因此我將命名為 MyCompA 和 MyCombB。
就像是:
public class MyCompA<S, T> {
private final Class<S> sourceType;
private final Class<T> targetType;
public MyCompA(Class<S> sourceType, Class<T> targetType) {
this.sourceType = sourceType;
this.targetType = targetType;
}
public T toModel(S regras) {
return modelMapper.map(regras, targetType);
}
}
雖然,聽起來你實際上不需要sourceType任何東西,所以你不妨把它關掉。
這種策略的問題有兩個:
j.l.Class實體可以表示泛型無法表示的某些事物。具體來說,原語:int,原語,有一個j.l.Class代表它的實體;您可以使用運算式獲得它int.class。int不是有效的泛型(無論如何,可能在未來的 java 版本中還沒有):Class<int>不起作用,List<int>.- 一個
j.l.Class實體只能代表基本型別- 即已擦除的。List<String>不能表示為j.l.Class實體。這意味著 S 和 T 型別本身不能有泛型,這通常會破壞交易 - 你可能希望能夠將某些東西映射到List<String>.
超級型別令牌
一種出路是 STT。他們看起來很時髦。制作它們:
TypeToken<List<String>> = new TypeToken<>() {};
注意那里奇怪的尾隨{}。這會創建一個匿名類,并且類確實攜帶在編譯后仍然存在的泛型資訊,因此可以通過反射訪問進行查詢。運行時系統對它不做任何事情 - 就 JVM 而言,它是注釋(JVM 不知道泛型是什么,也不將它們用于任何事情。它存在于類檔案中javac只是為了...... ..但我們可以通過反思來閱讀它,所以就是這樣)。
public abstract class TypeToken<T> {
public Type getType() {
Type t = getClass().getGenericSuperclass();
if (!(t instanceof ParameterizedType pt)) throw new IllegalStateException("Incorrect use of TypeToken: " t);
Type[] typeArgs = pt.getActualTypeArguments();
if (typeArgs.length == 1) return typeArgs;
throw new IllegalStateException("Incorrect use of TypeToken: " t);
}
我已經向您展示了如何制作這些實體。如果你愿意,你可以在建構式中包含一個呼叫getType()(并且你可能想要快取回傳值;它不能改變并且反射可能有點貴),因為這樣你會在你無效時得到例外型別標記(例如:new TypeToken() {}-這是原始用法,當然在這里不起作用,重點是捕獲 中的內容<>)。
API麻煩!
modelMapper.map顯然,您的方法需要 type 的值Class<>。如前所述,那些不能表示泛型,所以這個映射器只能映射到基本的、無型別引數的型別。在這種情況下,STT 完全是矯枉過正,您只需要傳入類實體的簡單解決方案。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/483538.html
下一篇:帶有泛型的Kotlin中綴函式
