162

有没有办法将对象转换为方法的返回值?我尝试过这种方式,但它在“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);
}
4

3 回答 3

241

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

于 2013-01-25T15:19:52.510 回答
24

我偶然发现了这个问题,它引起了我的兴趣。接受的答案是完全正确的,但我认为我确实在 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字节码指令发生在 main 方法中,而不是convertInstanceOfObjectandconvertInstanceOfObject方法没有任何可以 throw 的指令ClassCastException。因为 main 方法没有捕获,ClassCastException因此当您执行 main 方法时,您将得到 aClassCastException而不是 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 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

请注意,方法中有一条invokevirtual指令convertInstanceOfObject调用Class.cast()throws的方法,该方法ClassCastException将被catch(ClassCastException e)bock 捕获并返回null;因此,“null”会毫无例外地打印到控制台。

于 2017-06-02T07:26:44.420 回答
21

如果你不想依赖抛出异常(你可能不应该),你可以试试这个:

public static <T> T cast(Object o, Class<T> clazz) {
    return clazz.isInstance(o) ? clazz.cast(o) : null;
}
于 2018-06-28T09:01:47.467 回答