0

我有 2 个子类(学生、教师)和一个超类(职业)。
我从学生创建了对象 A,从老师创建了对象 B。

Student A = new Student();
Teacher B = new Teacher();

我已经创建了一个将对象作为参数并返回布尔值的静态方法;

compare(A, B);

public static boolean compare(Student s, Teacher t)

在方法中,我只是把这段代码用来比较两个对象是否属于同一个类;

if (s.getClass() == t.getClass())

现在我收到错误消息:

incomparable types: Class<CAP#1> and Class<CAP#2>

其中 CAP#1,CAP#2 是新的类型变量:

CAP#1 extends Student from capture of ? extends Student
CAP#2 extends Teacher from capture of ? extends Teacher

这里有什么问题?

注意:如果我使用比较 s.equals(t),它根本没有任何错误。为什么我不能正确使用 object.getClass() 方法?

4

2 回答 2

1

我想你想要这样的东西:

    public static boolean compare(Object o1, Object o2)

然后也许instanceof用来比较喜欢if(o1 instanceof Teacher && o2 instanceof Student)

抛出异常是因为getClass()返回 aClass<? extends Object>并且就像错误消息告诉你的那样,这些类是无法比较的,因为 Student 和 Teacher 将返回不同的类(我认为你的错误是假设返回了类似字符串的东西)。

于 2012-12-02T13:07:21.440 回答
1

如果class Student extends Occupationclass Teacher extends Occupation,则不存在既是 aStudent又是 a 的类Teacher。因此,试图比较它们是没有意义的。s.getClass() == t.getClass()总是会返回 false。

编译器可以检测到,因为对于任何类型 T,T.getClass()返回Class<? extends T>. Class<? extends Student>并且Class<? extends Teacher>永远不会相互平等,因此无法比较。

如果您确实想比较它们,您需要让编译器相信这些类型确实具有可比性。您可以将方法签名(如@Seismoid 所建议)更改为compare( Object o1, Object o2)或通过显式向上转换为Class<?>或什至Class(我在这里感觉到原始类型警告)或Object

return ((Class<?>) s.getClass()) == ((Class<?>) t.getClass());

根据为什么s.equals(t)有效,这是因为T.equalsis public boolean equals(Object), not的签名public boolean equals(T),所以编译器无法检查比较总是返回 false。实际上,它甚至可能不会返回 false,因为您可以创建一个等于来自不同类的对象的对象。

你不能 override ==,所以编译器知道比较是无关紧要的,因为不能是同一个类的对象不能彼此相同(除非两者都是null - 你应该以不同的方式检查)。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.21.3说:

如果无法通过强制转换(第 5.5 节)将任一操作数的类型转换为另一个操作数的类型,则会出现编译时错误。两个操作数的运行时值必然不相等。

于 2012-12-02T13:09:39.317 回答