7
I wonder if there’s a difference between:
String a = (String) arg;
and the cast class:
String a = String.class.cast(arg);
I once heard that using the cast static class is more performatic, this is true?
7
I wonder if there’s a difference between:
String a = (String) arg;
and the cast class:
String a = String.class.cast(arg);
I once heard that using the cast static class is more performatic, this is true?
6
Both run the same task, but the so-called "static" version generates more bytecode (more overhead at compile time).
In practice both run the cast using bytecode instruction:
CHECKCAST java/lang/String
The difference that the code generated by the "static" version gets the type declaratively, in the case of String.class, by making a call from Class.cast(Object)
reference code:
public class CastTest2 {
public static void main(String... args) {
Object arg = "Test";
String explicitCast = (String) arg;
String explicitDynCast = String.class.cast(arg);
}
bytecode generated for direct cast:
L1
LINENUMBER 10 L1
ALOAD 1
CHECKCAST java/lang/String
ASTORE 2
bytecode generated for cast "statico":
L2
LINENUMBER 12 L2
LDC Ljava/lang/String;.class
ALOAD 1
INVOKEVIRTUAL java/lang/Class.cast (Ljava/lang/Object;)Ljava/lang/Object;
CHECKCAST java/lang/String
ASTORE 3
So:
LDC Ljava/lang/String;.class
The above statement returns a Class instance
which in turn, calls the cast method, returning an Object:
INVOKEVIRTUAL java/lang/Class.cast (Ljava/lang/Object;)Ljava/lang/Object;
and implicitly does Cast for Type, Class T.
CHECKCAST java/lang/String
ps: The fact that I call "static" and how can be seen in the bytecode that the call to Class.cast(Object) is made using the INVOKEVIRTUAL and not INVOKESTATIC statement.
3
As said by Felipe in the comments, for comparison of performance just you do a benchmarking simple of the two approaches.
In this example was used the Metrics, version 3.1.0
. If use Maven, just add this dependency:
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
<version>3.1.0</version>
</dependency>
Other considerations:
Were made 10000 Casts of objects to String
, both using the cast Operator, how much using cast(Object obj)
.
Below are the snippets used for cast:
static void usingCastMethod() {
final Object obj = "string";
for (int i = 0; i < 10000; i++) {
final String str = String.class.cast(obj);
}
}
Result: 629.19 milliseconds
cast(Object obj)
static void usingCastOperator() {
final Object obj = "string";
for (int i = 0; i < 10000; i++) {
final String str = (String) obj;
}
}
Result: 3065.02 milliseconds
Obs.: the result is only for comparison, just to see that there is a difference in performance.
By the result we can realize that there is significant difference, ie we can conclude that this is not treated differently by the compiler.
Now, let’s see how the bytecode generated in both approaches:
static void usingCastMethod();
Code:
0: ldc #104 // String string
2: astore_0
3: iconst_0
4: istore_1
5: goto 21
8: ldc #106 // class java/lang/String
10: aload_0
11: invokevirtual #113 // Method java/lang/Class.cast:(Ljava/lang/Object;)Ljava/lang/Object;
14: checkcast #106 // class java/lang/String
17: astore_2
18: iinc 1, 1
21: iload_1
22: sipush 10000
25: if_icmplt 8
28: return
cast(Object obj)
static void usingCastOperator();
Code:
0: ldc #104 // String string
2: astore_0
3: iconst_0
4: istore_1
5: goto 16
8: aload_0
9: checkcast #106 // class java/lang/String
12: astore_2
13: iinc 1, 1
16: iload_1
17: sipush 10000
20: if_icmplt 8
23: return
By bytecode we can see that actually using cast Operator is more expensive, if you check every instruction in specification you will see in detail why.
In short it is due to the fact that java knows the type only at runtime, so it has to turn around to ensure as much as possible that it does not give a ClassCastException
. Already in the other approach, even generating more bytecode, you’ve already made explicit the kind that waits, if not him (isInstance(Object obj)
) one ClassCastException
will be launched, without the JVM seeking more information to try the cast
Knowing that in terms of performance there is a difference, there are advantages and disadvantages? I can now remember only when we use generics:
String
), that is, instead of this:@SuppressWarnings("unchecked")
public <T> T cast(final Object o) {
return (T) o;
}
Prefer to use this:
public <T> T cast(final Class<T> clazz, final Object o) {
return clazz.cast(o);
}
Browser other questions tagged java cast
You are not signed in. Login or sign up in order to post.
I think you can make bechmarking and find out.
– Filipe Miranda