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
How to Properly Configure Implicit/Explicit Waits and Pageloadtimeout Through Selenium
Getting an Attribute Value in Xml Element
How to Read Xml Response from a Url in Java
Java.Lang.Outofmemoryerror: Java Heap Space in Maven
Strange Java Null Behavior in Method Overloading
How to Use Parameters, Request and Session Objects Present in Actioncontext
Javafx Launch Another Application
Simpledateformat Parse Loses Timezone
Wrap the String After a Number of Characters Word-Wise in Java
How to Output Two Columns to the Console in Java
How to Print Escape Characters in Java
How Can My Java Program Store Files Inside of Its .Jar File
How to Do a Soap Web Service Call from Java Class
Mapping a Specific Servlet to Be the Default Servlet in Tomcat
Parsing JSON with Gson, Object Sometimes Contains List Sometimes Contains Object
Must Spring Component Classes Be Thread-Safe
Are Non-Capturing Groups Redundant
Java.Lang.Nosuchmethoderror: Javax.Servlet.Servletcontext.Getcontextpath()Ljava/Lang/String;