简体   繁体   English

将对象转换为通用类型以返回

[英]Cast Object to Generic Type for returning

Is there a way to cast an object to return value of a method?有没有办法将对象强制转换为方法的返回值? I tried this way but it gave a compile time exception in "instanceof" part:我试过这种方式,但它在“instanceof”部分给出了一个编译时异常:

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

I also tried this one but it gave a runtime exception, ClassCastException:我也试过这个,但它给出了一个运行时异常,ClassCastException:

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

Is there a possible way of doing this easily:有没有办法轻松做到这一点:

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"

EDIT: I wrote a working copy of the correct answer:编辑:我写了一份正确答案的工作副本:

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);
}

You have to use a Class instance because of the generic type erasure during compilation.由于编译期间的泛型类型擦除,您必须使用Class实例。

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

The declaration of that method is:方法的声明是:

public T cast(Object o)

This can also be used for array types.这也可用于数组类型。 It would look like this:它看起来像这样:

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

Note that when someObject is passed to convertToInstanceOfObject it has the compile time type Object .请注意,当someObject传递给convertToInstanceOfObject它具有编译时类型Object

I stumble upon this question and it grabbed my interest.我偶然发现了这个问题,它引起了我的兴趣。 The accepted answer is completely correct, but I thought I do provide my findings at JVM byte code level to explain why the OP encounter the ClassCastException .接受的答案是完全正确的,但我认为我确实在 JVM 字节码级别提供了我的发现来解释为什么 OP 遇到ClassCastException

I have the code which is pretty much the same as OP's code:我的代码与 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);
}

and the corresponding byte code is:对应的字节码为:

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

Notice that checkcast byte code instruction happens in the main method not the convertInstanceOfObject and convertInstanceOfObject method does not have any instruction that can throw ClassCastException .请注意, checkcast字节码指令发生在 main 方法而不是convertInstanceOfObject并且convertInstanceOfObject方法没有任何可以抛出ClassCastException指令。 Because the main method does not catch the ClassCastException hence when you execute the main method you will get a ClassCastException and not the expectation of printing null .因为 main 方法没有捕获ClassCastException因此当你执行 main 方法时你会得到一个ClassCastException而不是打印null的期望。

Now I modify the code to the accepted answer:现在我将代码修改为接受的答案:

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);
    }

The corresponding byte code is:对应的字节码为:

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

Notice that there is an invokevirtual instruction in the convertInstanceOfObject method that calls Class.cast() method which throws ClassCastException which will be catch by the catch(ClassCastException e) bock and return null ;注意,有一个invokevirtual在指令convertInstanceOfObject调用方法Class.cast()方法,其抛出ClassCastException ,这将是由抓catch(ClassCastException e)博克和返回null ; hence, "null" is printed to console without any exception.因此,“null”毫无例外地打印到控制台。

If you do not want to depend on throwing exception (which you probably should not) you can try this:如果你不想依赖抛出异常(你可能不应该这样做),你可以试试这个:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM