programing tip

리턴하기 위해 오브젝트를 일반 유형으로 캐스트

itbloger 2020. 7. 11. 10:56
반응형

리턴하기 위해 오브젝트를 일반 유형으로 캐스트


메소드의 값을 리턴하기 위해 오브젝트를 캐스트하는 방법이 있습니까? 이 방법을 시도했지만 "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);
}

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있습니다.


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.

I have the code which is pretty much the same as OP's code:

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. 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.

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; hence, "null" is printed to console without any exception.


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

참고URL : https://stackoverflow.com/questions/14524751/cast-object-to-generic-type-for-returning

반응형