这两种铸造方式有什么区别吗?
Is there any difference in those two way of casting?
在下面的代码中
Object o;
//getting o
Integer i = (Integer) o; //1
Integer j = Integer.class.cast(mapValue); //2
//1
和//2
有区别吗?
我的意思是,在 JVM 中,所有这些情况都将使用相同的字节码指令执行,对吗?
它的作用相同。但是如果你看一下实现:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
很明显,该方法进行了一些额外的检查。在类似于您的示例的 class 上使用 javap -c
可以看到字节码中的内容:
这是简单的直接转换:
0: aload_0
1: getfield #2; //Field o:Ljava/lang/Object;
4: checkcast #3; //class java/lang/Integer
7: astore_1
这是使用Class.cast()
方法:
11: aload_0
12: getfield #2; //Field o:Ljava/lang/Object;
15: invokevirtual #4; //Method java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
18: checkcast #3; //class java/lang/Integer
21: astore_2
可以看出,invokevirtual
操作有开销,这与这种方法可能不知道结尾 class 的事实一致(正如@screenmutt 在他的回答中所写).
干杯,
正如安德斯指出的那样,效果是一样的。
但是,只有知道结尾才能使用第一个class。在此示例中,您可以在不知道结尾的情况下进行转换 class.
Class toCast = getClassToCast();
toCast.cast(objectToCast);
在下面的代码中
Object o;
//getting o
Integer i = (Integer) o; //1
Integer j = Integer.class.cast(mapValue); //2
//1
和//2
有区别吗?
我的意思是,在 JVM 中,所有这些情况都将使用相同的字节码指令执行,对吗?
它的作用相同。但是如果你看一下实现:
public T cast(Object obj) {
if (obj != null && !isInstance(obj))
throw new ClassCastException(cannotCastMsg(obj));
return (T) obj;
}
很明显,该方法进行了一些额外的检查。在类似于您的示例的 class 上使用 javap -c
可以看到字节码中的内容:
这是简单的直接转换:
0: aload_0
1: getfield #2; //Field o:Ljava/lang/Object;
4: checkcast #3; //class java/lang/Integer
7: astore_1
这是使用Class.cast()
方法:
11: aload_0
12: getfield #2; //Field o:Ljava/lang/Object;
15: invokevirtual #4; //Method java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
18: checkcast #3; //class java/lang/Integer
21: astore_2
可以看出,invokevirtual
操作有开销,这与这种方法可能不知道结尾 class 的事实一致(正如@screenmutt 在他的回答中所写).
干杯,
正如安德斯指出的那样,效果是一样的。
但是,只有知道结尾才能使用第一个class。在此示例中,您可以在不知道结尾的情况下进行转换 class.
Class toCast = getClassToCast();
toCast.cast(objectToCast);