概述
一个简单的字符串比较,以下四种写法有什么区别呢?
写法一:
public class TestClass {
public void test() {
"str1".equals("str2");
}
public static void main(String[] args) {
new TestClass().test();
}
}
写法二:
public class TestClass {
public void test() {
String str = "str1";
str.equals("str2");
}
public static void main(String[] args) {
new TestClass().test();
}
}
写法三:
public class Constans {
public static final String str1 = "str1";
}
public class TestClass {
public void test() {
String str = Constans.str1;
str.equals("str2");
}
public static void main(String[] args) {
new TestClass().test();
}
}
写法四:
public class TestClass {
public void test() {
String str = "str1";
String st2 = "str2";
str.equals(st2);
}
public static void main(String[] args) {
new TestClass().test();
}
}
以上四种写法基本上一样,但如果我们非要抠一下区别呢,我们通过 javap -c -l TestClass.class 来看一下它们的区别。
写法一:
Compiled from "TestClass.java"
public class com.example.demo.compile.TestClass {
public com.example.demo.compile.TestClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/demo/compile/TestClass;
public void test();
Code:
0: ldc #2 // String str1
2: ldc #3 // String str2
4: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
7: pop
8: return
LineNumberTable:
line 11: 0
line 12: 8
LocalVariableTable:
Start Length Slot Name Signature
0 9 0 this Lcom/example/demo/compile/TestClass;
public static void main(java.lang.String[]);
Code:
0: new #5 // class com/example/demo/compile/TestClass
3: dup
4: invokespecial #6 // Method "":()V
7: invokevirtual #7 // Method test:()V
10: return
LineNumberTable:
line 15: 0
line 16: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
}
重点关注 test() 下的 Code 那一段。
写法二:
Compiled from "TestClass.java"
public class com.example.demo.compile.TestClass {
public com.example.demo.compile.TestClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/demo/compile/TestClass;
public void test();
Code:
0: ldc #2 // String str1 将常量“str1”压入栈
2: astore_1 // 将栈中的“str1”pop出,赋值给str
3: aload_1 // 将str的引用值压入栈
4: ldc #3 // String str2
6: invokevirtual #4 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
9: pop
10: return
LineNumberTable:
line 11: 0
line 12: 3
line 13: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lcom/example/demo/compile/TestClass;
3 8 1 str Ljava/lang/String;
public static void main(java.lang.String[]);
Code:
0: new #5 // class com/example/demo/compile/TestClass
3: dup
4: invokespecial #6 // Method "":()V
7: invokevirtual #7 // Method test:()V
10: return
LineNumberTable:
line 16: 0
line 17: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
}
可以看到,在 test 方法里, 写法二 比 写法一 多了对 str 局部变量的操作。
关于方法里的几个命令的作用,见下图:
写法三:
Compiled from "TestClass.java"
public class com.example.demo.compile.TestClass {
public com.example.demo.compile.TestClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/demo/compile/TestClass;
public void test();
Code:
0: ldc #3 // String str1
2: astore_1
3: aload_1
4: ldc #4 // String str2
6: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
9: pop
10: return
LineNumberTable:
line 11: 0
line 12: 3
line 13: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 this Lcom/example/demo/compile/TestClass;
3 8 1 str Ljava/lang/String;
public static void main(java.lang.String[]);
Code:
0: new #6 // class com/example/demo/compile/TestClass
3: dup
4: invokespecial #7 // Method "":()V
7: invokevirtual #8 // Method test:()V
10: return
LineNumberTable:
line 16: 0
line 17: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
}
写法二 和 写法三 完全一样,这是为什么呢?
我们用反编译工具打开 写法三 的 class 文件。
从 class 文件反编译后了内容上看, 写法三 的 String str = Constans.str1 在编译后会被转成 String str = "str1" ,转之后跟 写法二 一样了。
java在编译的时候,会做一些性能上的优化,比如:为了减少运行时的栈调用,将 var = 常量字段 直接编译成 var = 常量字段的值 。
写法四:
Compiled from "TestClass.java"
public class com.example.demo.compile.TestClass {
public com.example.demo.compile.TestClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
LineNumberTable:
line 8: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Lcom/example/demo/compile/TestClass;
public void test();
Code:
0: ldc #3 // String str1
2: astore_1
3: ldc #4 // String str2
5: astore_2
6: aload_1
7: aload_2
8: invokevirtual #5 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
11: pop
12: return
LineNumberTable:
line 11: 0
line 12: 3
line 13: 6
line 14: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 this Lcom/example/demo/compile/TestClass;
3 10 1 str Ljava/lang/String;
6 7 2 st2 Ljava/lang/String;
public static void main(java.lang.String[]);
Code:
0: new #6 // class com/example/demo/compile/TestClass
3: dup
4: invokespecial #7 // Method "":()V
7: invokevirtual #8 // Method test:()V
10: return
LineNumberTable:
line 17: 0
line 18: 10
LocalVariableTable:
Start Length Slot Name Signature
0 11 0 args [Ljava/lang/String;
}
写法四 是在 写法二 基础上,又多了对 str2 局部变量的操作。
最后
以上就是健忘毛豆为你收集整理的java字符串的赋值,java字符串赋值比较在写法上的区别的全部内容,希望文章能够帮你解决java字符串的赋值,java字符串赋值比较在写法上的区别所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复