将对象强制转换为泛型类型以便返回

是否有方法强制转换对象以返回方法的值? 我试过这种方法,但它在“ instanceof”部分给出了一个编译时异常:

public static <T> T convertInstanceOfObject(Object o) {
if (o instanceof T) {
return (T) o;
} else {
return null;
}
}

我也试过这个,但它提供了一个运行时异常,ClassCastException:

public static <T> T convertInstanceOfObject(Object o) {
try {
T rv = (T)o;
return rv;
} catch(java.lang.ClassCastException e) {
return null;
}
}

有没有一种简单的方法可以做到这一点:

String s = convertInstanceOfObject("string");
System.out.println(s); // should print "string"
Integer i = convertInstanceOfObject(4);
System.out.println(i); // should print "4"
String k = convertInstanceOfObject(345435.34);
System.out.println(k); // should print "null"

编辑: 我写了一份正确答案的工作副本:

public static <T> T convertInstanceOfObject(Object o, Class<T> clazz) {
try {
return clazz.cast(o);
} catch(ClassCastException e) {
return null;
}
}


public static void main(String args[]) {
String s = convertInstanceOfObject("string", String.class);
System.out.println(s);
Integer i = convertInstanceOfObject(4, Integer.class);
System.out.println(i);
String k = convertInstanceOfObject(345435.34, String.class);
System.out.println(k);
}
268778 次浏览

由于编译期间的泛型类型擦除,因此必须使用 Class实例。

public static <T> T convertInstanceOfObject(Object o, Class<T> clazz) {
try {
return clazz.cast(o);
} catch(ClassCastException e) {
return null;
}
}

那种方法的声明如下:

public T cast(Object o)

这也可以用于数组类型:

final Class<int[]> intArrayType = int[].class;
final Object someObject = new int[]{1,2,3};
final int[] instance = convertInstanceOfObject(someObject, intArrayType);

请注意,当 someObject传递给 convertToInstanceOfObject时,它的编译时类型为 Object

我偶然发现了这个问题,它引起了我的兴趣。接受的答案是完全正确的,但是我认为我在 JVM 字节码级别提供了我的发现,以解释为什么 OP 会遇到 ClassCastException

我的代码和 OP 的代码差不多:

public static <T> T convertInstanceOfObject(Object o) {
try {
return (T) o;
} catch (ClassCastException e) {
return null;
}
}


public static void main(String[] args) {
String k = convertInstanceOfObject(345435.34);
System.out.println(k);
}

相应的字节码是:

public static <T> T convertInstanceOfObject(java.lang.Object);
Code:
0: aload_0
1: areturn
2: astore_1
3: aconst_null
4: areturn
Exception table:
from    to  target type
0     1     2   Class java/lang/ClassCastException


public static void main(java.lang.String[]);
Code:
0: ldc2_w        #3                  // double 345435.34d
3: invokestatic  #5                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
6: invokestatic  #6                  // Method convertInstanceOfObject:(Ljava/lang/Object;)Ljava/lang/Object;
9: checkcast     #7                  // class java/lang/String
12: astore_1
13: getstatic     #8                  // Field java/lang/System.out:Ljava/io/PrintStream;
16: aload_1
17: invokevirtual #9                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
20: return

请注意,checkcast字节码指令发生在主方法中,而不是 convertInstanceOfObject,而且 convertInstanceOfObject方法没有任何可以抛出 ClassCastException的指令。因为 main 方法不能捕获 ClassCastException,所以当您执行 main 方法时,您将得到一个 ClassCastException,而不是期望打印 null

现在我将代码修改为可接受的答案:

public static <T> T convertInstanceOfObject(Object o, Class<T> clazz) {
try {
return clazz.cast(o);
} catch (ClassCastException e) {
return null;
}
}
public static void main(String[] args) {
String k = convertInstanceOfObject(345435.34, String.class);
System.out.println(k);
}

相应的字节码是:

public static <T> T convertInstanceOfObject(java.lang.Object, java.lang.Class<T>);
Code:
0: aload_1
1: aload_0
2: invokevirtual #2                  // Method java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
5: areturn
6: astore_2
7: aconst_null
8: areturn
Exception table:
from    to  target type
0     5     6   Class java/lang/ClassCastException


public static void main(java.lang.String[]);
Code:
0: ldc2_w        #4                  // double 345435.34d
3: invokestatic  #6                  // Method java/lang/Double.valueOf:(D)Ljava/lang/Double;
6: ldc           #7                  // class java/lang/String
8: invokestatic  #8                  // Method convertInstanceOfObject:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
11: checkcast     #7                  // class java/lang/String
14: astore_1
15: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
18: aload_1
19: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: return

请注意,在 convertInstanceOfObject方法中有一个 invokevirtual指令,它调用 Class.cast()方法,抛出 ClassCastExceptionClassCastException将被 catch(ClassCastException e)块捕获并返回 null; 因此,“ null”将毫无例外地打印到控制台。

如果您不想依赖于抛出异常(您可能不应该这样做) ,您可以尝试这样做:

public static <T> T cast(Object o, Class<T> clazz) {
return clazz.isInstance(o) ? clazz.cast(o) : null;
}