Consider the following piece of code:
final String str = "1-2-3";
for (int idx = 0; idx < str.split("\\D").length; idx++) {
// do something
}
How many times will this portion of code: str.split("\\\\D")
be executed? Three times? Or will the compiler see that as str
is declared as final
, only one call to str.split("\\\\D")
will be enough?
This might be interesting to you. For this code:
class Foo {
public static void main(String args[]) {
final String str = "1-2-3";
for (int idx = 0; idx < str.split("\\D").length; idx++) {
}
}
}
the bytecode is:
Compiled from "Foo.java"
class Foo {
Foo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: ldc #2 // String 1-2-3
5: ldc #3 // String \D
7: invokevirtual #4 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
10: arraylength
11: if_icmpge 20
14: iinc 2, 1
17: goto 2
20: return
}
It is clear that split
is executed
three
FOUR times, regardless of the finality of str
, and of invariance of split
.
JLS 14.14.1.2 states ( Expression
here being the middle bit of the for
statement):
Next, a for iteration step is performed, as follows. If the Expression is present, it is evaluated.
That means it does it on each iteration step, there is no leeway there in the specification for optimisation.
You can see something similar with the following code:
class Test {
public static int getSeven () {
System.out.println ("called getSeven()");
return 7;
}
public static void main (String[] args){
for (int i = 1; i <= getSeven(); i++) {
System.out.println ("i = " + i);
}
}
}
When you run that, you get:
called getSeven()
i = 1
called getSeven()
i = 2
called getSeven()
i = 3
called getSeven()
i = 4
called getSeven()
i = 5
called getSeven()
i = 6
called getSeven()
i = 7
called getSeven()
showing that the function is called each time through the loop (including the exit condition).
That means your particular case won't call it once or three times, it will actually call it four times, with idx
set respectively to 0
, 1
, 2
and the final check at 3
.
EDIT
The split method will be executed 3 times to determine the length, BUT this has nothing to do with the fact that the string is final or not. It would be execute the same even if the strign was not final.
See this example :
/* package whatever; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
String g = "bla bla";
for (int i = 0; i < index(g); i++)
{
System.out.println("Round");
}
}
public static int index(String input)
{
System.out.println("index Called");
return input.length();
}
}
The output will show for each round: index Called
How does for loop
works
int idx = 0
str.split("\\\\D").length;
idx++
str.split("\\\\D").length;
idx < str.split("\\\\D").length()
fails So every time your idx < str.split("\\\\D").length()
will get executed. I would say it will get execute three times for condition match and one last for condition fail.
There's a 100% sure way to see if a compiler optimizes something - look at the compilation result. I've included the byte code in the response and I think it's pretty obvious - the split method will be executed multiple times in the first case regardless of the final keyword (the invoke virtual line is the split method call, you can understand what is looped by the goto statement).
Different compilers MAY behave in a different way, though. Feel free to retest this on your desired environment (you can view bytecode with 'javap -c classname'
public class gti {
public static void main ( String[] args ) {
final String str = "1-2-3";
for (int idx = 0; idx < str.split("\\D").length; idx++) {
// do something
}
}
}
results in:
public class gti {
public gti();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_2
2: iload_2
3: ldc #2 // String 1-2-3
5: ldc #3 // String \D
7: invokevirtual #4 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
10: arraylength
11: if_icmpge 20
14: iinc 2, 1
17: goto 2
20: return
}
while
public class gti {
public static void main ( String[] args ) {
final String str = "1-2-3";
int length = str.split("\\D").length;
for (int idx = 0; idx < length; idx++) {
// do something
}
}
}
results in:
public class gti {
public gti();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String 1-2-3
2: ldc #3 // String \D
4: invokevirtual #4 // Method java/lang/String.split:(Ljava/lang/String;)[Ljava/lang/String;
7: arraylength
8: istore_2
9: iconst_0
10: istore_3
11: iload_3
12: iload_2
13: if_icmpge 22
16: iinc 3, 1
19: goto 11
22: return
}
str.split("\\D") will not split your str string it returns new instance of String[] array. Answer is 3 times str.split("\\D") will be executed.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.