Java Class.Cast() VS. Cast Operator

Java Class.cast() vs. cast operator

I've only ever used Class.cast(Object) to avoid warnings in "generics land". I often see methods doing things like this:

@SuppressWarnings("unchecked")
<T> T doSomething() {
Object o;
// snip
return (T) o;
}

It's often best to replace it by:

<T> T doSomething(Class<T> cls) {
Object o;
// snip
return cls.cast(o);
}

That's the only use case for Class.cast(Object) I've ever come across.

Regarding compiler warnings: I suspect that Class.cast(Object) isn't special to the compiler. It could be optimized when used statically (i.e. Foo.class.cast(o) rather than cls.cast(o)) but I've never seen anybody using it - which makes the effort of building this optimization into the compiler somewhat worthless.

The efficiency of Java Class.cast() compared to normal cast?

I recommend using Class.cast() over @SuppressWarnings where possible.

Don't care about performance here. If you have performance issues, profile your application, and I would be very surprised if this turned out to be a hot spot.

Casting a generic class. (cast) vs Class.cast()

I think that both methods do the same.

No, they don't. Because at execution time, the first code doesn't know the type of T due to type erasure. That means the cast basically does nothing within the method. The calling code might implicitly cast to whatever T it is specifying, but if the caller is another generic method (with the T used here as another type parameter), even that wouldn't want.

Here's a simple example of that:

public class Test {
public static void main(String[] args) {
Object o = new Object();
// No exception
Test.<String>fakeCast(o);
// Exception at the point of assignment:
// the code is effectively String x = (String) ...;
String x = Test.<String>fakeCast(o);
}

private static <T> T fakeCast(Object o) {
return (T) o;
}
}

The second code knows the type of T in the form of Class<T>, so it can perform a real cast at execution time, at exactly the point you're performing it.

Cast via reflection and use of Class.cast()

An example where is does work:

class Favorites {
private Map<Class<?>, Object> map = new HashMap<Class<?>, Object>();

public <T> T get(Class<T> clazz) {
return clazz.cast(map.get(clazz));
}

public <T> void put(Class<T> clazz, T favorite) {
map.put(clazz, favorite);
}
}

which allows you to write:

Favorites favs = new Favorites();
favs.put(String.class, "Hello");
String favoriteString = favs.get(String.class);

The reason your code doesn't work is that Class.forName() returns a Class<?>, i.e. a class object representing an unknown type. While the compiler could possibly infer the type in your example, it can not in general. Consider:

Class.forName(new BufferedReader(System.in).readLine())

what's the type of this expression? Clearly the compiler can not know what the class name will be at runtime, so it doesn't know whether

String s = Class.forName(new BufferedReader(System.in).readLine()).cast(o);

is safe. Therefore it requests an explicit cast.

How to write custom casting method in Java

You can't overload the cast operator. Java doesn't support it and probably never will.

To convert a single value to an instance of the desired class, we use static factory methods.

public static Person fromAge(int age) {
return new Person(age);
}

They often return a partially constructed object. In the snippet above, a newly constructed person has only age set: other fields will have their default values.

To do the opposite, we use getters.

public int getAge() {
return age;
}

However, since toString is already there, it makes sense to add other data types as well.

toInt makes no sense when it's applied to me (as an instance of the Person class). It could be my height, my weight, my age, a number of times I went to a bathroom today, etc. I can't represent myself by one int number, neither can a large majority of classes.

On the other hand, toString can do this job pretty well: I can give you (read return) a summary of my hobbies, my biometric information, even my picture. Or I can leave it to the default implementation, which still would satisfactorily represent an object.

Groovy - as vs (cast)

The main difference is casting uses the concept of inheritance to do the conversion where the as operator is a custom converter that might or might not use the concepts of inheritance.

Which one is faster?
It depends on the converter method implementation.

Casting

Well, all casting really means is taking an Object of one particular
type and “turning it into” another Object type. This process is called
casting a variable.

E.g:

Object object = new Car();
Car car = (Car)object;

As we can see on the example we are casting an object of class Object into a Car because we know that the object is instance of Car deep down.

But we cant do the following unless Car is subclass of Bicycle which in fact does not make any sense (you will get ClassCastException in this case):

Object object = new Car();
Bicycle bicycle = (Bicycle)object;

as Operator

In Groovy we can override the method asType() to convert an object
into another type. We can use the method asType() in our code to
invoke the conversion, but we can even make it shorter and use as.

In groovy to use the as operator the left hand operand must implement this method:

Object asType(Class clazz) {
        //code here
    }

As you can see the method accepts an instance of Class and implements a custom converter so basically you can convert Object to Car or Car to Bicycle if you want it all depends on your implementation.



Related Topics



Leave a reply



Submit