Casting variables in Java

JavaCasting

Java Problem Overview


I wonder if anyone could tell me how casting works? I understand when I should do it, but not really how it works. On primitive data types I understand partially but when it comes to casting objects I don't understand how it works.

How can a object with the type Object just suddenly be cast to, let's say, MyType (just an example) and then get all the methods?

Java Solutions


Solution 1 - Java

Casting in Java isn't magic, it's you telling the compiler that an Object of type A is actually of more specific type B, and thus gaining access to all the methods on B that you wouldn't have had otherwise. You're not performing any kind of magic or conversion when performing casting, you're essentially telling the compiler "trust me, I know what I'm doing and I can guarantee you that this Object at this line is actually an <Insert cast type here>." For example:

Object o = "str";
String str = (String)o;

The above is fine, not magic and all well. The object being stored in o is actually a string, and therefore we can cast to a string without any problems.

There's two ways this could go wrong. Firstly, if you're casting between two types in completely different inheritance hierarchies then the compiler will know you're being silly and stop you:

String o = "str";
Integer str = (Integer)o; //Compilation fails here

Secondly, if they're in the same hierarchy but still an invalid cast then a ClassCastException will be thrown at runtime:

Number o = new Integer(5);
Double n = (Double)o; //ClassCastException thrown here

This essentially means that you've violated the compiler's trust. You've told it you can guarantee the object is of a particular type, and it's not.

Why do you need casting? Well, to start with you only need it when going from a more general type to a more specific type. For instance, Integer inherits from Number, so if you want to store an Integer as a Number then that's ok (since all Integers are Numbers.) However, if you want to go the other way round you need a cast - not all Numbers are Integers (as well as Integer we have Double, Float, Byte, Long, etc.) And even if there's just one subclass in your project or the JDK, someone could easily create another and distribute that, so you've no guarantee even if you think it's a single, obvious choice!

Regarding use for casting, you still see the need for it in some libraries. Pre Java-5 it was used heavily in collections and various other classes, since all collections worked on adding objects and then casting the result that you got back out the collection. However, with the advent of generics much of the use for casting has gone away - it has been replaced by generics which provide a much safer alternative, without the potential for ClassCastExceptions (in fact if you use generics cleanly and it compiles with no warnings, you have a guarantee that you'll never get a ClassCastException.)

Solution 2 - Java

Actually, casting doesn't always work. If the object is not an instanceof the class you're casting it to you will get a ClassCastException at runtime.

Solution 3 - Java

Suppose you wanted to cast a String to a File (yes it does not make any sense), you cannot cast it directly because the File class is not a child and not a parent of the String class (and the compiler complains).

But you could cast your String to Object, because a String is an Object (Object is parent). Then you could cast this object to a File, because a File is an Object.

So all you operations are 'legal' from a typing point of view at compile time, but it does not mean that it will work at runtime !

File f = (File)(Object) "Stupid cast";

The compiler will allow this even if it does not make sense, but it will crash at runtime with this exception:

Exception in thread "main" java.lang.ClassCastException:
    java.lang.String cannot be cast to java.io.File

Solution 4 - Java

Casting a reference will only work if it's an instanceof that type. You can't cast random references. Also, you need to read more on Casting Objects.

e.g.

String string = "String";

Object object = string; // Perfectly fine since String is an Object

String newString = (String)object; // This only works because the `reference` object is pointing to a valid String object.

Solution 5 - Java

The right way is this:

Integer i = Integer.class.cast(obj);

The method cast() is a much safer alternative to compile-time casting.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser626912View Question on Stackoverflow
Solution 1 - JavaMichael BerryView Answer on Stackoverflow
Solution 2 - JavasandrstarView Answer on Stackoverflow
Solution 3 - JavaChristophe RoussyView Answer on Stackoverflow
Solution 4 - JavaasgsView Answer on Stackoverflow
Solution 5 - Javayegor256View Answer on Stackoverflow