[英]Java generics: Why can't the compiler tell that this Class<T> object has the same type as the class of an object of this class' type parameter?
[英]How to tell compiler that two objects are of same - but unknown - class (with generics)?
請考慮以下代碼:
public class MyClass {
public static void main(String[] args) {
Object o1 = getObject(Math.random());
Object o2 = getObject(Math.random());
if (o1.getClass().equals(o2.getClass()) { // two Cars or two Apples
Comparable c1 = (Comparable) o1;
Comparable c2 = (Comparable) o2;
int x = c1.compareTo(c2); // unsafe
System.out.println(x);
)
}
public Object getObject(double d) { // given method that may not be changed
if (d < 0.5) return (new Car()); // Car implements Comparable<Car>
else return (new Apple()); // Apple implements Comparable<Apple>
}
}
代碼可以工作(給定Cat
和Apple
類),但是編譯器會警告操作不安全,因為我使用了不帶泛型的compareTo
。 但是,我不知道如何解決此問題,因為我不知道如何指定c1
和c2
的類型相同-但未知-類型(在if
子句中)。 有什么辦法(除了使用@SuppressWarnings
以外)來解決此問題?
我知道這里有一個類似的問題: 如何告訴Java兩個通配符類型相同? 但是那里給出的答案似乎是針對問詢者的具體情況。 例如,它使用在我的上下文中不存在的鍵值映射。
由於條件if (o1.getClass().equals(o2.getClass()))
保證兩個對象屬於同一類,因此可以忽略警告。 您可以抑制它。
但是,由於此時它們的類型是Object
,將它們Comparable
為Comparable
不安全的。 您可以通過一些較小的調整使其更安全,以使它們成為Comparable
類:
public static void main(String[] args) {
Comparable<?> o1 = getComparable(Math.random());
Comparable<?> o2 = getComparable(Math.random());
if (o1.getClass().equals(o2.getClass())) {
// safe cast
Comparable c1 = (Comparable) o1;
Comparable c2 = (Comparable) o2;
// safe comparison
int x = c1.compareTo(c2);
System.out.println(x);
}
}
public Comparable<? extends Comparable<?>> getComparable(double d) {
if (d < 0.5) return (new Car());
return (new Apple());
}
這里的問題是,不能將Comparable<Car>
和Comparable<Apple>
相互比較,因為Comparable<T>
僅比較T
s就具有“舒適”功能。 現在,我們為此付出了代價。
對於.equals
並非如此。
我們正在嘗試什么
// WILL NOT WORK
if (o1.getClass().equals(o2.getClass()) { // two Cars or two Apples
int x = comparison(o1.getClass(), o1, o2);
System.out.println(x);
)
static <T extends Comparable<T>> int comparison(Class<T> type, T o1, T o2) {
return type.cast(o1).compareTo(type.cast(o2));
}
這是Java的一個功能,它具有極少表現力的類型系統。
更新您的方法以處理可Comparable
對象而不是Object
對象。
public class MyClass {
public static void main(String[] args) {
Comparable o1 = getObject(Math.random());
Comparable o2 = getObject(Math.random());
if (o1.getClass().equals(o2.getClass()) { // two Cars or two Apples
int x = o1.compareTo(o2);
System.out.println(x);
)
}
public Comparable getObject(double d) { // given method that may not be changed
if (d < 0.5) return (new Car()); // Car implements Comparable<Car>
else return (new Apple()); // Apple implements Comparable<Apple>
}
}
另一個替代實現:
public static void main(String[] args) {
Object o1 = getObject(Math.random());
Object o2 = getObject(Math.random());
if ( o1.getClass().equals(o2.getClass() ) && o1 instanceof Comparable ) {
int x = getObject(o1).compareTo(o2);
System.out.println(x);
}
}
public static Object getObject(double d) { // given method that may not be changed
if (d < 0.5) return ( new Car() ); // Car implements Comparable<Car>
else return ( new Apple() ); // Apple implements Comparable<Apple>
}
public static <T> Comparable<T> getObject(Object o) {
return (Comparable<T>)o;
}
您可以使用instanceof運算符。 您可以將其編寫為:
if(c1 instanceof Integer && c2 instanceof Integer)
int x = c.compareTo(c2);
or if(c1 instanceof String)
String s = c1;
您可以通過這種方式工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.