Java 方法返回classCastException

Java 方法返回classCastException,java,compareto,Java,Compareto,假设我有一个扩展Employee的Employee基类和Manager子类。现在假设我创建了Employee类型的对象x和Manager类型的对象y,并调用x.compareTo(y)没有触发异常,x和y作为雇员进行比较,即y被强制转换为雇员,但当我调用y.compareTo(x)时我得到一个classCastException。我需要知道为什么会发生这种情况,以及如何防止x.compareTo(y)执行,因为x和y来自不同的类。我的想法是在反射类中使用getclass()方法,如下所示: if

假设我有一个扩展Employee的Employee基类和Manager子类。现在假设我创建了Employee类型的对象x和Manager类型的对象y,并调用
x.compareTo(y)
没有触发异常,x和y作为雇员进行比较,即y被强制转换为雇员,但当我调用
y.compareTo(x)时
我得到一个classCastException。我需要知道为什么会发生这种情况,以及如何防止x.compareTo(y)执行,因为x和y来自不同的类。我的想法是在反射类中使用getclass()方法,如下所示:

if (getClass() != other.getClass()) 
throw new ClassCastException();

我还想知道有没有其他方法来实现这一点。

这里的
经理是一名员工

但是
员工
不是
经理

引用有效Java第12项:

让我们看一下合同的条款。第一条规定说,如果你颠倒两个对象参照之间的比较方向,预期的事情就会发生:如果第一个对象小于第二个对象,那么第二个对象必须大于第一个对象;如果第一个对象等于第二个对象,则第二个对象必须等于第一个对象;如果第一个物体大于第二个物体,那么第二个物体必须小于第一个物体。第二条规定,如果一个物体大于第二个物体,第二个物体大于第三个物体,那么第一个物体必须大于第三个物体。最后一条规定是,当与任何其他对象进行比较时,所有作为相等对象进行比较的对象必须产生相同的结果


这三条规定的一个结果是,比较法施加的平等测试必须遵守平等合同施加的相同限制:自反性、对称性和及物性。因此,同样的警告也适用:除非您愿意放弃面向对象抽象的好处(第8项),否则在保留compareTo契约的同时,无法使用新的值组件扩展可实例化类。同样的解决方法也适用。如果要向实现Comparable的类添加值组件,请不要扩展它;编写一个不相关的类,其中包含第一个类的实例。然后提供一个返回此实例的“view”方法。这使您可以在第二个类上实现您喜欢的任何compareTo方法,同时允许其客户端在需要时将第二个类的实例视为第一个类的实例。

因为您的
经理是员工
,但
员工不是经理
请参见下文


的实例在这种情况下可用

所有
经理
都是
员工
,但并非所有
员工
都是
经理
。由于
Employee
的所有属性在
Manager
中可用,
Manager
可以强制转换为
Employee
。但是
Manager
的属性对
Employee
不可用,因此无法进行强制转换


我的建议是在类中重写
compareTo()
方法,并强制转换对象
Employee
,您应该在类
Employee
中实现
compareTo()
,并从以下内容开始:

Employee o = (Employee)other;

然后继续将
o
进行比较-这将确保您比较的是两名
员工
s(最低公分母).

您可以使用isAssignableFrom,它将返回true或false,然后使用它进行进一步的比较或相等等。不确定您为什么需要这个来进行比较;不过

无论如何,假设员工的姓名、工资和经理的一组报告对象,然后进一步比较工资作为比较的一部分

public class Test{   
    public static void main(String[] args) {
        class Employee implements Comparable<Employee> {
            public Employee(String string, int salary) {
                this.name = string;
                this.salary = salary;
            }

            public Employee() {
                name = "";
                salary = 0;
            }

            String name;
            Integer salary;

            public int compareTo(Employee o) {
                return o!=null && getClass().isAssignableFrom(Employee.class)
                        ? salary.compareTo(o.salary) : Integer.MIN_VALUE;
            }

        }

        class Manager extends Employee {
            public Manager(String name, String[] subordinates) {
                super(name, 1000000);
                reportees = subordinates;
            }

            String[] reportees;
        }

        Employee e = new Employee("me", 1000);
        Employee e1 = new Employee("mycolleague", 2000);
        Manager m = new Manager("myboss", "me mycolleague".split(" "));
        System.out.println(e1.compareTo(e));
        System.out.println(e.compareTo(m));
        System.out.println(m.compareTo(e)); // this gives INT.MIN as you cannot compare manager to employee
    }

}
公共类测试{
公共静态void main(字符串[]args){
类Employee实现了可比较的{
公共雇员(字符串,整数工资){
this.name=字符串;
这个。薪水=薪水;
}
公职人员(){
name=“”;
工资=0;
}
字符串名;
整数工资;
公共内部比较(员工o){
return o!=null&&getClass().isAssignableFrom(Employee.class)
?薪资。比较(o.salary):整数最小值;
}
}
类管理器扩展雇员{
公共经理(字符串名称,字符串[]下属){
超级(名称,1000000);
被报道者=下属;
}
字符串[]报告对象;
}
员工e=新员工(“我”,1000);
雇员e1=新雇员(“mycolleague”,2000年);
经理m=新经理(“我的老板”、“我的同事”)。拆分(“”);
系统输出打印ln(e1.与(e)比较);
系统输出println(e.compareTo(m));
System.out.println(m.compareTo(e));//这会给出INT.MIN,因为您无法比较经理和员工
}
}

您想在两名员工之间比较什么?薪水?:)@卢声远生源路不,这只是一个例子,我的代码太大了,不能在这里发布。是的,我知道,但我也想阻止执行的x.compareTo(y),我的想法是使用getclass(),我想知道还有其他方法吗?@user1613360请参见alfasin的答案。这并不能回答这个问题。若要评论或要求作者澄清,请在他们的帖子下方留下评论。@Payeli我要求他思考“是一种”关系。请查看
public class Test{   
    public static void main(String[] args) {
        class Employee implements Comparable<Employee> {
            public Employee(String string, int salary) {
                this.name = string;
                this.salary = salary;
            }

            public Employee() {
                name = "";
                salary = 0;
            }

            String name;
            Integer salary;

            public int compareTo(Employee o) {
                return o!=null && getClass().isAssignableFrom(Employee.class)
                        ? salary.compareTo(o.salary) : Integer.MIN_VALUE;
            }

        }

        class Manager extends Employee {
            public Manager(String name, String[] subordinates) {
                super(name, 1000000);
                reportees = subordinates;
            }

            String[] reportees;
        }

        Employee e = new Employee("me", 1000);
        Employee e1 = new Employee("mycolleague", 2000);
        Manager m = new Manager("myboss", "me mycolleague".split(" "));
        System.out.println(e1.compareTo(e));
        System.out.println(e.compareTo(m));
        System.out.println(m.compareTo(e)); // this gives INT.MIN as you cannot compare manager to employee
    }

}