Reputation: 1314
Let's assume I have an Employee base class and Manager subclass which extends Employee.Now let's say I create an object x of type Employee and object y of type Manager and call x.compareTo(y)
no exception is triggered and x and y is compared as Employees namely y is cast to an Employee but when I call y.compareTo(x)
I get a classCastException.I need to know why this happens and how to prevent x.compareTo(y) to execute as x and y are from different classes.My idea is to use getclass() method in Reflection class like this:
if (getClass() != other.getClass())
throw new ClassCastException();
I also want to know is there any other way to implement this.
Upvotes: 3
Views: 2122
Reputation: 281
You could perhaps use isAssignableFrom which will return true or false and then use it for doing further comparison or equals etc. Not sure why you would need this in compareTo; however.
Anyways assuming name , salary for an employee and set of reportees for manager and then for example further just comparing salaries as part of compareTo.
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
}
}
Upvotes: 0
Reputation: 2081
here Manager
is a Employee
.
but Employee
is not Manager
.
Quote from Effective Java, Item 12:
Let’s go over the provisions of the compareTo contract. The first provision says that if you reverse the direction of a comparison between two object refer- ences, the expected thing happens: if the first object is less than the second, then the second must be greater than the first; if the first object is equal to the second, then the second must be equal to the first; and if the first object is greater than the second, then the second must be less than the first. The second provision says that if one object is greater than a second, and the second is greater than a third, then the first must be greater than the third. The final provision says that all objects that compare as equal must yield the same results when compared to any other object.
One consequence of these three provisions is that the equality test imposed by acompareTo method must obey the same restrictions imposed by the equals con- tract: reflexivity, symmetry, and transitivity. Therefore the same caveat applies: there is no way to extend an instantiable class with a new value component while preserving the compareTo contract, unless you are willing to forgo the benefits of object-oriented abstraction (Item 8). The same workaround applies, too. If you want to add a value component to a class that implements Comparable, don’t extend it; write an unrelated class containing an instance of the first class. Then provide a “view” method that returns this instance. This frees you to implement whatever compareTo method you like on the second class, while allowing its cli- ent to view an instance of the second class as an instance of the first class when needed.
Upvotes: 2
Reputation: 639
If your are using compareTo method then i am excepting you have implemented Comparable interface in your class and provide a implementation of the method compareTo. let me know how you are comparing object on what logic ,based on that only you get the solution.
I have little bit confuse on this
if (getClass() != other.getClass())
throw new ClassCastException();
if it is the code in your compareTo method then rather then doing this create one more interface say "XYZ" and implement that Interface to both the class
check the logic
public int compareTo(T obj){
if(this instanceof XYZ && obj instanceof XYZ)){
return 0;
}else{
throw new ClassCastException();
}
}
Upvotes: 0
Reputation: 2692
All Manager
are Employee
but not all Employee
are Managers
. Since all the attributes of Employee
are available in Manager
,Manager
can be casted to Employee
. But attributes of Manager
is unavailable to Employee
, so cast is not possible.
My suggestion is to override compareTo()
method in your classes and cast the object Employee
.
Upvotes: 0
Reputation: 53525
You should implement compareTo()
in the class Employee
and start it with:
Employee o = (Employee)other;
Then continue with comparing this
to o
- this will ensure you're comparing two Employee
s (which is the lowest common denominator).
Upvotes: 3
Reputation: 2895
Because your Manager is an Employee
but Employee is not a Manager
See below
http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
instance of
can be usefull in such cases
Upvotes: 2