请考虑以下代码:
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
:
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;
你可以这样工作。