Last active
October 24, 2021 08:36
-
-
Save renatoathaydes/a18fcd509115df66efecb1b9cfcc6dc9 to your computer and use it in GitHub Desktop.
Using static variables in local scope in Java.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.regex.Pattern; | |
public class Test { | |
public static void main(String[] args) { | |
check("a"); | |
check("b"); | |
} | |
static Pattern compile(String pattern) { | |
System.out.println("compile(" + pattern + ")"); | |
return Pattern.compile(pattern); | |
} | |
static void check(String string) { | |
// Compiling the pattern only once: Good | |
// Keeping the pattern local to the method: Good | |
// Capturing scope: Egh... | |
var patterns = new Object() { | |
static final Pattern P_CHECK = compile("a"); | |
}; | |
System.out.println("check(" + string + "): " | |
+ patterns.P_CHECK.matcher(string).find()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.regex.Pattern; | |
public class Test { | |
public static void main(String[] args) { | |
check("a"); | |
check("b"); | |
} | |
static Pattern compile(String pattern) { | |
System.out.println("compile(" + pattern + ")"); | |
return Pattern.compile(pattern); | |
} | |
static void check(String string) { | |
// Compiling the pattern only once: Good | |
// Keeping the pattern local to the method: Good | |
// Does not capture the scope: Good | |
class Patterns { | |
static final Pattern P_CHECK = compile("a"); | |
} | |
System.out.println("check(" + string + "): " | |
+ Patterns.P_CHECK.matcher(string).find()); | |
} | |
} |
Bytcode of the first version:
▶ javap -c Test\$1
Compiled from "Test.java"
class Test$1 {
static final java.util.regex.Pattern P_CHECK;
Test$1();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
static {};
Code:
0: ldc #7 // String a
2: invokestatic #9 // Method Test.compile:(Ljava/lang/String;)Ljava/util/regex/Pattern;
5: putstatic #15 // Field P_CHECK:Ljava/util/regex/Pattern;
8: return
}
▶ javap -c Test
Compiled from "Test.java"
public class Test {
public Test();
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 #7 // String a
2: invokestatic #9 // Method check:(Ljava/lang/String;)V
5: ldc #15 // String b
7: invokestatic #9 // Method check:(Ljava/lang/String;)V
10: return
static java.util.regex.Pattern compile(java.lang.String);
Code:
0: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
3: aload_0
4: invokedynamic #23, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
9: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
12: aload_0
13: invokestatic #32 // Method java/util/regex/Pattern.compile:(Ljava/lang/String;)Ljava/util/regex/Pattern;
16: areturn
static void check(java.lang.String);
Code:
0: new #38 // class Test$1
3: dup
4: invokespecial #40 // Method Test$1."<init>":()V
7: astore_1
8: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_0
12: aload_1
13: pop
14: getstatic #41 // Field Test$1.P_CHECK:Ljava/util/regex/Pattern;
17: aload_0
18: invokevirtual #45 // Method java/util/regex/Pattern.matcher:(Ljava/lang/CharSequence;)Ljava/util/regex/Matcher;
21: invokevirtual #49 // Method java/util/regex/Matcher.find:()Z
24: invokedynamic #55, 0 // InvokeDynamic #1:makeConcatWithConstants:(Ljava/lang/String;Z)Ljava/lang/String;
29: invokevirtual #27 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
32: return
}
The generated class Test$1
is identical to the Test$Patterns
class, but the check
implementation is unnecessarily creating a new instance of Test$1
, resulting in 8 extra, unnecessary bytecode instructions.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Bytecode of the second version: