Reputation: 3709
I'd like to implement a method that takes an Object
as argument, casts it to an arbitrary type, and if that fails returns null
. Here's what I have so far:
public static void main(String[] args) {
MyClass a, b;
a = Main.<MyClass>staticCast(new String("B"));
}
public static class MyClass {
}
public static <T> T staticCast(Object arg) {
try {
if (arg == null) return null;
T result = (T) arg;
return result;
} catch (Throwable e) {
return null;
}
}
Unfortunately the class cast exception is never thrown/caught in the body of the staticCast()
function. It seems Java compiler generates the function String staticCast(Object arg)
in which you have a line String result = (String) arg;
even though I explicitly say that the template type should be MyClass
. Any help? Thanks.
Upvotes: 6
Views: 567
Reputation: 192055
Because generic type information is erased at runtime, the standard way to cast to a generic type is with a Class
object:
public static <T> T staticCast(Object arg, Class<T> clazz) {
if (arg == null) return null;
if (!clazz.isInstance(arg))
return null;
T result = clazz.cast(arg);
return result;
}
Then call it like this:
a = Main.staticCast("B", MyClass.class);
Upvotes: 10
Reputation: 61534
You cannot do what you want... at least not this way. The compiler removed all of the information so you wind up with (T) being Object in the cast - and that works.
The problem is that later on you are doing MyClass = (String)object; and that isn't allowed.
You have bypassed the compilers checking and made it fail at runtime.
So what is it exactly that you are trying to do? If you tell us why you want to do this we can probably tell you the Java way of doing it.
Given your comment you might try something like:
public class Main
{
public static void main(String[] args)
{
String a;
MyClass b;
a = staticCast(new String("B"), String.class);
b = staticCast(new String("B"), MyClass.class);
System.out.println(a);
}
public static class MyClass
{
}
public static <T> T staticCast(Object arg, final Class clazz)
{
// edit - oops forgot to deal with null...
if(arg == null)
{
return (null);
}
// the call to Class.cast, as mmeyer did, might be better... probably is better...
if(arg.getClass() != clazz)
{
// Given your answer to Ben S...
return (null);
// throw new ClassCastException("cannot cast a " + arg.getClass() + " to a " + clazz);
}
return ((T)arg);
}
}
Upvotes: 6
Reputation: 32831
I agree with Ben, however, I prefer the following notation:
MyClass.class.cast(obj);
Upvotes: 1
Reputation: 182878
Don't mistake Java generics for C++ templates. There is only going to be one staticCast method that's called with different type erasure, not one for each T.
Not using Generics at all, I would write it this way:
public static void main(String[] args) {
MyClass a, b;
a = (MyClass)Main.staticCast(new String("B"), MyClass.class);
}
public static class MyClass {
}
public static staticCast(Object arg, Class class) {
if (arg != null && class.isAssignableFrom(arg))
return arg;
return null;
}
Or stealing from another answer, using generics:
public static <T> T staticCast(Object arg, Class<T> class) {
if (arg != null && class.isAssignableFrom(arg))
{
T result = class.cast(arg);
return result;
}
return null;
}
Upvotes: 1
Reputation: 69412
You mean like Class<T>.cast(Object obj)
?
Something like:
Class.forName("YourClass").cast(obj);
Should do pretty much what you want.
Be aware that this is quite smelly though and is probably a sign of poor design.
Upvotes: 4