java字符串的赋值,java字符串赋值比较在写法上的区别

一个简单的字符串比较,以下四种写法有什么区别呢?

写法一:

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 局部变量的操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值