请看下面的代码:
public class MyClass<T extends MyObject> {
private Class<T> clazz;
public void setClass1(Class<T> clazz) {
this.clazz = clazz;
}
public Class<T> getClass1() {
return clazz;
}
public T getObject1() {
T o = null;
try {
o = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return o;
}
}
上面的效果很好,但需要类类型 T
在任何MyClass
之前被知道对象被创建。现在,如果我想延迟指定 T
直到 setClass1()
曾经被调用过,我必须删除 <T extends MyObject>
来自 MyClass
声明如下:
public class MyClass {
// private Class<T> clazz; // doesn't work anymore as T is unknown, so do the following instead
private Class<? extends MyObject> clazz;
public <T extends MyObject> void setClass1(Class<T> clazz) {
this.clazz = clazz; // OK
}
public void setClass2(Class<? extends MyObject> clazz) {
this.clazz = clazz; // OK
}
public <T extends MyObject> Class<T> getClass1() {
return clazz; // Error, need casting to Class<T>
}
public Class<? extends MyObject> getClass2() {
return clazz; // OK
}
public <T extends MyObject> T getObject1() {
T o = null;
try {
o = clazz.newInstance(); // Error, must cast to T
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return o;
}
public MyObject getObject2() {
MyObject o = null;
try {
o = clazz.asSubclass(MyObject.class).newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
return o; // OK, but lost the difference between ? extends MyObject and MyObject
}
}
首先,为什么 getClass1()
给出错误,而 setClass1()
可以吗?
二、为什么返回getObject1()
必须转换为 (T)
?
三、如何修复getObject1()
没有不必要的类型转换,也没有 @SuppressWarnings("unchecked")
?
第四,在我的例子中会改变使用 setClass1()
, getClass1()
, getObject1()
至 setClass2()
, getClass2()
, getObject2()
更好?
最佳答案
First, why getClass1() gives error, while setClass1() is OK?
在setClass()
你分配一个 Class<? extends MyObject>
到 Class<? extends MyObject>
类型的变量.这是允许的。
在getClass()
,你想检索一个 Class<T>
来自 Class<? extends MyObject>
类型的变量.但是编译器无法知道变量中存储的内容是否真的是 Class<T>
。或者可能是 Class<U>
.所以这是被禁止的。
Second, why the return in getObject1() must be cast to (T)?
Class<? extends MyObject>.newInstance()
返回 ? extends MyObject
类型的对象.这与 T
不同.这就是你必须转换的原因。
Third, how do you fix getObject1() without unnecessary casting nor @SuppressWarnings("unchecked")?
如前所述,上面的版本不包含不必要的转换。你要么必须制作T
类本身的通用参数,或者您需要强制转换。
关于java - 当类中没有定义泛型类型变量时处理泛型类成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40124587/