Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Java Java Data Structures Organizing Data Interfaces

Matthew Francis
Matthew Francis
6,967 Points

Clarification on compareTo

public class Treet{
public int compareTo(Object obj){
    Treet other = (Treet) obj;
    if(equals(other)){
      return 0;
    }
    int dateCmp = mCreationDate.compareTo(other.mCreationDate);
    if(dateCmp == 0){
      return mDescription.compareTo(other.mDescription); 
    }
    return dateCmp;
  }
}

Question 1:(For those who watched the video, if not skip to question 2) Is upcasting the obj neccecary? I can't seem to find a reson why, Treet does not seem to have any subclasses. I'm assuming this is just "back up" if in the future we want to have subclasses for Treet?

Question 2:From my understanding, the compareTo method holds a parameter (Object obj) and it compares this.object with "other". But in this video, it seems that we never invoked it (thus we never mentioned what the "obj" is in the parameter"). So how does the method know what to compare this.object with?

Matthew Francis
Matthew Francis
6,967 Points

Makes sense! Just for curisoity though, could you also do:

compareTo(Treet obj){ Treet other = obj; ..... }

Sorry! I haven't fixed my code yet so I cant test it out

Benjamin Barslev Nielsen
Benjamin Barslev Nielsen
18,958 Points

Not in your current implementation, but only a small change is needed. The interface Comparable is generic:

Interface Comparable<T>

and here is the method signature for compareTo as defined in the API:

int compareTo(T o)

First note that

public class Treet implements Comparable {

is equal to:

public class Treet implements Comparable<Object> {

Therefore in the current implementation you need the method signature:

public int compareTo(Object obj){

So to be able to use the signature:

public int compareTo(Treet obj){

you need to implement Comparable<Treet>:

public class Treet implements Comparable<Treet> {

2 Answers

Benjamin Barslev Nielsen
Benjamin Barslev Nielsen
18,958 Points

Answer for question 1: Is upcasting the obj necessary?

The code does not upcast obj, but instead downcasts obj, since Treet is a subtype of Object. Remember that Object is a superclass of all objects. Without the downcast you couldn't write the code other.mCreationDate. mCreationDate exists in a Treet, but not an Object and therefore the downcast is needed.

Answer for question 2:

The compareTo method is used when sorting the array:

Arrays.sort(treets);

Looking at the API for sort we see that the sort method uses the compareTo method in order to sort the array, and therefore which objects to compare are specified in the implementation of Arrays.sort.

Hope this helps

Matthew Francis
Matthew Francis
6,967 Points

Thanks for clear things up! However regarding question 1:

I'm assuming that the array is automatically inserted into the compareTo()'s parameter because of the implementation of Array.sort();. So it's basically:

public int compareTo(Treet treet){} 
and
public int compareTo(Treet secondTreet){}

So if both objects share the same class, they do not need downcasting do they?

Benjamin Barslev Nielsen
Benjamin Barslev Nielsen
18,958 Points

To understand why we need the downcast, we can ignore Arrays.sort(), and only look at the implementation of compareTo.

Looking at the method signature:

public int compareTo(Object obj){

we see that obj is of type Object. We would like to access the fields mCreationDate and mDescription, but these aren't accessible on Object. Therefore accessing obj.mCreationDate will result in a compile error. mCreationDate however is accessible on a Treet object and therefore, we need to tell the Compiler that obj is in fact a Treet, which is what we do with the cast:

Treet other = (Treet) obj;

Hope this clarifies why the downcast is needed.

Kathy Lanier
Kathy Lanier
4,426 Points

Got it! So, you use compareTo() to tell Arrays.sort() HOW to sort (mCreationDate).

Matthew Francis
Matthew Francis
6,967 Points

Hey Benjamin, I just read on an article that you cannot downcast a superclass to a subclass,

eg;

class Animal{..}

class Cat extends Animal{...}

Animal test = (Cat) new Animal();

But seeing as this code below works, Im guessing downcasting can work if you downcast the Object superclass into any subclass?

public int compareTo(Object obj){
    Treet other = (Treet) obj;
Benjamin Barslev Nielsen
Benjamin Barslev Nielsen
18,958 Points

The class Object doesn't behave differently than any other class regarding casts.

I will explain why the first cast is wrong and why the second is correct, but to understand this, we first need to look at some theory about types in Java. In Java we have static types (the ones the compiler uses) and runtime types (the actual types). The actual type can be more accurate than the static type, i.e., the static type is either equal to the actual type or an superclass of it. In some cases we might have more information about the actual type than the compiler does, and therefore we can use casts to inform the compiler of the more accurate type. This means that the type we cast to, needs to match the actual type or be a superclass of the actual type. Now let's see some examples of this:

Animal animal = (Cat) new Animal();

Animal animalCat = new Cat();
Cat cat = (Cat) animalCat;

In the first code line the actual type is Animal, and since Animal is not a Cat, we cannot make that cast. In the second line we create animalCat which has the actual type Cat and the static type Animal. The cast in the third line is therefore correct, since the actual type of animalCat is Cat, and therefore we can cast it to be of static type Cat.

The same thing happens in compareTo. Object is the static type, but the actual type is Treet and therefore the cast to Treet is correct. If we called compareTo with an actual type different from Treet, then the cast would be wrong.

Hope this clarifies things.

Matthew Francis
Matthew Francis
6,967 Points

Ahh, so If I understand this correctly:

Treet[] treets = {treet, secondTreet};
Array.sort(treets);


public int compareTo(Object obj){/* the treets are being compared to each other and since the data type of the argument is Object here, the treets are upcasted to object, which is later downcasted to treet again with Treet other = (Treet obj);. Correct?
    Treet other = (Treet) obj;
....
}