Solved Error: cannot be cast to java.lang.Comparable

This article will look at how to solve the above-given Class Cast Exception. This ClassCast Exception occurs at runtime when we improperly typecast an object of a class to a related class of which it is not an instance.

Now, what does it mean when the exception says: cannot be cast to java.lang.Comparable. Let us first have a brief look at what is Comparable.

We use Comparable Interface mainly when we need to sort an Array of Custom Objects. In other words, it orders the objects of the user-defined class in a single sorting sequence. This interface is present in java.lang package and contains only one method named compareTo(Object), responsible for sorting these custom objects.

Now, let us look at different reasons we get the above exception in detail along with the way to resolve them.

Sorting Custom Objects of a Class

We can get this exception when we try to sort an Array of Objects without providing the implementation of sorting those objects. In such cases, we need to implement a Comparable interface. For example, consider this class:

public class Student 
{
	int id;
	String name;
	
	Student(int id,String name)
	{
		this.id=id;
		this.name=name;
	}

}

If we have an array of Student Objects and suppose we need to sort those objects on the basis we cannot sort them simply using Arrays.sort() method of array class. This will result in an Exception. So for Example:

import java.util.Arrays;

public class StudentMain {

	public static void main(String[] args) 
	{
		// Creating Objects
		Student obj=new Student(2,"Harry");
		Student obj1=new Student(3,"Sean");
		Student obj2=new Student(5,"Shane");
		Student obj3=new Student(4,"Gary");
		Student obj4=new Student(1,"Amanda");
		
		//Creating Array of Student Objects
		Student arr[] = new Student[5];
		arr[0]=obj;
		arr[1]=obj1;
		arr[2]=obj2;
		arr[3]=obj3;
		arr[4]=obj4;
		
                // Calling inbuilt Sort method of Arrays Class to sort them
		Arrays.sort(arr);
		
	}

}

Calling the sort method in such a way will result in the exception:

Exception in thread "main" java.lang.ClassCastException: class Student cannot be cast to class java.lang.Comparable
	at java.base/java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:320)
	at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:188)
	at java.base/java.util.Arrays.sort(Arrays.java:1040)
	at StudentMain.main(StudentMain.java:22)

This is because the sort method of Arrays Class provides sort implementation for only Primitive datatypes wrapped into Wrapper Class Objects. Hence, To Sort Custom Objects we need to provide the property which will sort the Array. As objects have more than one property or field.

Solution:

So, the solution will be to implement the Comparable interface and provide the sorting logic for each object by overriding its compareTo() method on basis of one field. We will have to provide two a single object as the argument and it will compare its field with the current instance. We have to implement the Interface in the same class of which the objects are made i.e. Student. So the Student Class now is:

public class Student implements Comparable<Student>
{
	int id;
	String name;
	
	Student(int id,String name)
	{
		this.id=id;
		this.name=name;
	}

	@Override
	public int compareTo(Student obj) 
	{
		// we sort objects on the basis of Student Id
		return (this.id - obj.id);
	}

}

Here, for simplicity, we sort the students according to their id. We can also sort them according to their name. After doing this we can call the sort method and sort the Student Array without getting an exception now and print the details.

Note: Using Comparable, the original class gets modified we cannot implement this in our Main Class, if we need to do it in a separate class we have to use the Comparator interface.

Using TreeSet or TreeMap or Any Ordered Collection to Store Custom Objects

This is another case where we might get this ClassCast Exception. Basically, the collection class or data structures such as Tree-Set and Tree-Map store ordered data. And, for general data types like Integer, Float, etc the classes have implemented the Comparable Interface to order them but not for Custom made objects. Suppose we have the same class Student (Not implementing Comparable) as above. Now instead of adding them in the array if we add them in Collections such as Tree Set or Tree-Map as shown below:

import java.util.Set;
import java.util.TreeSet;

public class StudentMain {

	public static void main(String[] args) 
	{
		// Creating Objects
		Student obj=new Student(2,"Harry");
		Student obj1=new Student(3,"Sean");
		Student obj2=new Student(5,"Shane");
		Student obj3=new Student(4,"Gary");
		Student obj4=new Student(1,"Amanda");
		
		//Creating Set(TreeSet) of Student Objects
		Set<Student> ts = new TreeSet<Student>();
		
		//We get exception at this line because we add Student obj without defining the order on each object.
		ts.add(obj);
		ts.add(obj1);
		ts.add(obj2);
		ts.add(obj3);
		ts.add(obj4);
		
		System.out.println("Students Details: ");
		
		for(Student s: ts)
		System.out.println(s.id+" "+s.name);
		
	}

}

In this case, we get an exception when we add the first object to the Tree-Set as the student class defines no order on the objects. This will also happen if we add any object as a Key to a Tree-Map along with a value. The Exception we get here is different.

Exception in thread "main" java.lang.ClassCastException: class Student cannot be cast to class java.lang.Comparable
        at java.base/java.util.TreeMap.compare(TreeMap.java:1563)
	at java.base/java.util.TreeMap.addEntryToEmptyMap(TreeMap.java:768)
	at java.base/java.util.TreeMap.put(TreeMap.java:777)
	at java.base/java.util.TreeMap.put(TreeMap.java:534)
	at java.base/java.util.TreeSet.add(TreeSet.java:255)
	at StudentMain.main(StudentMain.java:19)

You can see the Exception is due to add() method of Tree-Set as the class Student has no functionality to compare objects it raises an exception.

Solution:

The solution for this will also be the same as above. We need to implement the Comparable Interface within the class Student or a Comparator in a different class (Not Main Class) and define an order on those objects by overriding their compare methods respectively. So, we implement the Comparable Interface here, and let’s define an order which will sort our objects according to Student’s name unlike the id’s what we did earlier. So the Student Class now is:

public class Student implements Comparable<Student>
{
	int id;
	String name;
	
	Student(int id,String name)
	{
		this.id=id;
		this.name=name;
	}

	  @Override
	public int compareTo(Student obj) 
	{
		// we sort objects on the basis of Student Name using compareTo of String Class
		return this.name.compareTo(obj.name);
	}

}

We sort the Students with respect to their names by overriding the compareTo() of their class. After this, we can execute the StudentMain Class without any exception and print the Student Details.

Output:

Students Details: 
1 Amanda
4 Gary
2 Harry
3 Sean
5 Shane

As you can see we print the student details sorted according to their names. We can also do this using a Tree-Map.

That’s all for the article, we discussed the reasons for the exception and saw the solution. Let us know about your queries in the comment section below.

Leave a Comment

Your email address will not be published. Required fields are marked *