Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Java Java Data Structures - Retired Getting There Type Casting

Ben Attenborough
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Ben Attenborough
Front End Web Development Techdegree Graduate 32,769 Points

Confused by type casting

I've been following the Java Data Structures to this point, but I'm really confused by type casting. I'm trying to understand what it is and why we need to use it. I know it is connected to inheritance whereby a child class inherits the features of the parent class, but I'm really befuddled by what type casting is for.

The transcript right at the start of the video is particularly confusing to me:

"Another thing that you should know about inheritance is that it allows you to use an instance anywhere, one of its superclasses is required."

Can't we just pass the treet object in without calling it's parent class?

"Now for example, if there was a method that took an object as a parameter, we could pass it our Treet class and because Treet is an object, everything would work out just fine, implicitly."

Um, okay...

"It's also possible to go the other way and have a parent class redefine its type or explicitly cast itself as a child."

Now this really confuses me. How can a parent class treat itself as a child class? And why not just use the child class seeing as the child inheirts everything from its parent anyway?

Sorry, this has just has really twisted my mind!

4 Answers

Dan Johnson
Dan Johnson
40,533 Points

The major advantage of using parent classes or interfaces when you can over the child classes is it allows for methods to operate on objects without needing to know the details for every single one of the child classes when they're not relevant. For example let's say we need to print out all the elements in a collection. If we go with the child classes we'll end up with something like this:

public class Application {
    public static void main(String[] args) {
        Set<Integer> uniqueNumbers = new HashSet<>();
        List<Character> letters = new ArrayList<>();

        uniqueNumbers.add(1);
        uniqueNumbers.add(2);
        uniqueNumbers.add(3);

        letters.add('a');
        letters.add('b');
        letters.add('c');

        printCollection(uniqueNumbers);
        printCollection(letters);
    }

    // Generics aren't actually required for this method but I used
    // for clarity's sake.
    public static <Type> void printCollection(Set<Type> set) {
        System.out.printf("Here are the %d element(s):%n", set.size());
        for(Type element: set)
            System.out.println(element);
    }

    public static <Type> void printCollection(List<Type> list) {
        System.out.printf("Here are the %d element(s):%n", list.size());
        for(Type element: list)
            System.out.println(element);
    }

}

You'll notice that these functions do the exact same thing, they state the element count then iterate through a collection. No specific methods are required for each type, these are all features of a collection. Even if the iterator that they use behaves differently internally or the size is calculated differently between the List and the Set, it doesn't matter, you just want it to perform the same action:

public class Application {
    public static void main(String[] args) {
        Set<Integer> uniqueNumbers = new HashSet<>();
        List<Character> letters = new ArrayList<>();

        uniqueNumbers.add(1);
        uniqueNumbers.add(2);
        uniqueNumbers.add(3);

        letters.add('a');
        letters.add('b');
        letters.add('c');

        printCollection(uniqueNumbers);
        printCollection(letters);
    }

    public static <Type> void printCollection(Collection<Type> collection) {
        System.out.printf("Here are the %d element(s):%n", collection.size());
        for(Type element : collection)
            System.out.println(element);
    }
}

As for casting from a parent class down to a child class, this only works if the object in memory actually is the child class in question.

This is fine:

Object myObject = new String("Actually a string");
String myString = (String)myObject;
System.out.println(myString.toLowerCase());

This will throw a ClassCastException at runtime (specifically at the line of the myString declaration):

Object myObject = new Object();
String myString = (String)myObject;
System.out.println(myString.toLowerCase());

This is used for when you do need the specific methods of the child classes but are working with the parent classes. It's best not to use too heavily as it can work against the reasons mentioned above.

Craig Dennis
STAFF
Craig Dennis
Treehouse Teacher

I think this might help. As you probably know, String has a method named length that allows you to see how many characters it contains. As we saw a String is an Object, so it is possible that we could pass a String to a method that is accepting an Object.

String example = "This is an example";

public int justSomeExampleToShowTypeCastingOff(Object obj) {
   if (obj instanceof String) {
        String str = (String) obj;
        return str.length();
   }
   // Otherwise, I don't know how to figure out the length
   return 0;
}

// Call the method even though it takes an Object, I will pass in a String
justSomeExampleToShowTypeCastingOff(example);

Now, what if we wanted to call length on that Object. Well, Object doesn't have that method, so we can't call obj.length(), we need to cast it to something that does. So let's check and see if it is a String, and then we can access that method.

That make sense? Hope that didn't make things more murky ;)

I understand that you can do what you've just done, but could method overloading be used in this instance?

public String getTitle (String str) { //logic to return length }

public String getTitle ( //default logic }

If we can, then why is casting better? If we can't, I assume it's because java can't distinguish between two objects when overloading?

Kevin Faust
Kevin Faust
15,353 Points

Hey mridul,

thanks alot for that link as it was extremely helpful. i went from being absolutely completely lost to actually knowing whats sorta going on. do you know if there are more of those notes? do you know where i can find them? i checked that cs.utexas.edu site but i have no idea.

or do you know any places where i can find similar notes to those that are easy to understand for beginners. because too much of the stuff online is way beyond my capabilities and get me even more confused than i am

Wan Nor Adzahari Wan Tajuddin
Wan Nor Adzahari Wan Tajuddin
2,438 Points

That link is very helpful! Whoever wrote that is a genius! I am eternally grateful. Sometimes I wish that Treehouse thought us like the article did. The article explained everything in detail and giving us examples like Animals > Mammals > Cats/Dogs thing.

Hey kevin,

I definitely understand your problem as I also encounter it when i am new to some topic. But what i do is just google the problem and go through some links, and find the one for me.

Check this website too, it may help :- http://beginnersbook.com/2013/05/java-interface/

If you have doubts in some particular topics in java i can help you out with them too. :)

Kevin Faust
Kevin Faust
15,353 Points

Hey Mridul thanks for your reply !! ill definetely check that site out. it looks like a promising website :)