欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java有意思的知识点

程序员文章站 2024-03-12 22:20:56
...
今天在论坛上看到的几个题,有几个貌似还挺有意思的。
 
public static void test() {
String x = "hello";
String y = "world";
String z = new String("helloworld");
String a = "helloworld";
System.out.println("x == hello:" + (x == "hello"));
System.out.println("a == helloworld:" + (a == "hello" + "world"));
System.out.println("a == x+y:" + (a == (x + y)));
}

x == hello:true
a == helloworld:true
a == x+y:false
请看翻译过的源码:
public static void test();
0 ldc <String "hello"> [15]
2 astore_0 [x]
3 ldc <String "world"> [17]
5 astore_1 [y]
6 ldc <String "helloworld"> [19]
8 astore_2 [a]
9 getstatic java.lang.System.out : java.io.PrintStream [21]
12 new java.lang.StringBuilder [27]
15 dup
16 ldc <String "x == hello:"> [29]
18 invokespecial java.lang.StringBuilder(java.lang.String) [31]
21 aload_0 [x]
22 ldc <String "hello"> [15]
24 if_acmpne 31
27 iconst_1
28 goto 32
31 iconst_0
32 invokevirtual java.lang.StringBuilder.append(boolean) : java.lang.StringBuilder [34]
35 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [38]
38 invokevirtual java.io.PrintStream.println(java.lang.String) : void [42]
41 getstatic java.lang.System.out : java.io.PrintStream [21]
44 new java.lang.StringBuilder [27]
47 dup
48 ldc <String "a == helloworld:"> [47]
50 invokespecial java.lang.StringBuilder(java.lang.String) [31]
53 aload_2 [a]
54 ldc <String "helloworld"> [19]
56 if_acmpne 63
59 iconst_1
60 goto 64
63 iconst_0
64 invokevirtual java.lang.StringBuilder.append(boolean) : java.lang.StringBuilder [34]
67 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [38]
70 invokevirtual java.io.PrintStream.println(java.lang.String) : void [42]
73 getstatic java.lang.System.out : java.io.PrintStream [21]
76 new java.lang.StringBuilder [27]
79 dup
80 ldc <String "a == x+y:"> [49]
82 invokespecial java.lang.StringBuilder(java.lang.String) [31]
85 aload_2 [a]
86 new java.lang.StringBuilder [27]
89 dup
90 aload_0 [x]
91 invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [51]
94 invokespecial java.lang.StringBuilder(java.lang.String) [31]
97 aload_1 [y]
98 invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [57]
101 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [38]
104 if_acmpne 111
107 iconst_1
108 goto 112
111 iconst_0
112 invokevirtual java.lang.StringBuilder.append(boolean) : java.lang.StringBuilder [34]
115 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [38]
118 invokevirtual java.io.PrintStream.println(java.lang.String) : void [42]
121 return

对于String常量,包括“hello”+“world”这种方式的的值(第54行),都被设置为常量。然而对于x+y这种方式,其实首先是创建了一个StringBuilder,然后把两个变量都加到StringBuilder内,再转换成String。此时,就形成了一个新的String对象了。equals方法也就不适用了。

三、Override覆盖

public class Parent {

public static String say() {
return "parent static say";
}

public String say2() {
return "parent say";
}
}

public class Child extends Parent {
public static String say() {
return "child static say";
}

public String say2() {
return "child say";
}
}

public class OverrideTest {

public static void main(String[] args) {
Parent p = new Child();
System.out.println(p.say());
System.out.println(p.say2());

}

}

parent static say
child say

所谓静态方法,并不仅仅指该方法在所有实例中只有一份,同时也指该方法是“静态”加载的,即在编译期就已决定其行为。此处p的静态类型为Parent,所以它所调用的方法也在编译期和Parent的say()方法绑定:
  // Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 2, Locals: 2
public static void main(java.lang.String[] args);
0 new com.ibm.oneteam.Child [16]
3 dup
4 invokespecial com.ibm.oneteam.Child() [18]
7 astore_1 [p]
8 getstatic java.lang.System.out : java.io.PrintStream [19]
11 invokestatic com.ibm.oneteam.Parent.say() : java.lang.String [25]
14 invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]
17 getstatic java.lang.System.out : java.io.PrintStream [19]
20 aload_1 [p]
21 invokevirtual com.ibm.oneteam.Parent.say2() : java.lang.String [37]
24 invokevirtual java.io.PrintStream.println(java.lang.String) : void [31]
27 return


六、提前引用
public class ForwardReference {  

static int first = test();
static int second = 2;

static int test() {
return second;
}

public static void main(String[] args) {
System.out.println("first = " + first);
}

}

first = 0

这段代码有点诡异,但明白万变不离其宗,只要牢记静态方法&变量是“[b]静态[/b]”加载的,即编译时就决定的即可。当然,对于静态变量的这种[b]先定义后赋值[/b]的行为,还是需要小心:

public class com.ibm.oneteam.Main {

// Field descriptor #6 I
static int first;

// Field descriptor #6 I
static int second;

// Method descriptor #9 ()V
// Stack: 1, Locals: 0
static {};
0 invokestatic com.ibm.oneteam.Main.test() : int [11]
3 putstatic com.ibm.oneteam.Main.first : int [15]
6 iconst_2
7 putstatic com.ibm.oneteam.Main.second : int [17]
10 return
Line numbers:
[pc: 0, line: 5]
[pc: 6, line: 6]
[pc: 10, line: 3]

// Method descriptor #9 ()V
// Stack: 1, Locals: 1
public Main();
0 aload_0 [this]
1 invokespecial java.lang.Object() [22]
4 return
Line numbers:
[pc: 0, line: 3]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: com.ibm.oneteam.Main

// Method descriptor #14 ()I
// Stack: 1, Locals: 0
static int test();
0 getstatic com.ibm.oneteam.Main.second : int [17]
3 ireturn
Line numbers:
[pc: 0, line: 9]

看这段代码也许更加直观点:
public class Main {

static int first = test();
static int second = 2;

static int test() {
return second;
}

static int third = 3;

public static void main(String[] args) {
System.out.println("first = " + first);
}
}

编译后的代码:
// Compiled from Main.java (version 1.6 : 50.0, super bit)
public class com.ibm.oneteam.Main {

// Field descriptor #6 I
static int first;

// Field descriptor #6 I
static int second;

// Field descriptor #6 I
static int third;

// Method descriptor #10 ()V
// Stack: 1, Locals: 0
static {};
0 invokestatic com.ibm.oneteam.Main.test() : int [12]
3 putstatic com.ibm.oneteam.Main.first : int [16]
6 iconst_2
7 putstatic com.ibm.oneteam.Main.second : int [18]
10 iconst_3
11 putstatic com.ibm.oneteam.Main.third : int [20]
14 return
Line numbers:
[pc: 0, line: 5]
[pc: 6, line: 6]
[pc: 10, line: 12]
[pc: 14, line: 3]

// Method descriptor #10 ()V
// Stack: 1, Locals: 1
public Main();
0 aload_0 [this]
1 invokespecial java.lang.Object() [25]
4 return
Line numbers:
[pc: 0, line: 3]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: com.ibm.oneteam.Main

// Method descriptor #15 ()I
// Stack: 1, Locals: 0
static int test();
0 getstatic com.ibm.oneteam.Main.second : int [18]
3 ireturn
Line numbers:
[pc: 0, line: 9]

// Method descriptor #30 ([Ljava/lang/String;)V
// Stack: 4, Locals: 1
public static void main(java.lang.String[] args);
0 getstatic java.lang.System.out : java.io.PrintStream [31]
3 new java.lang.StringBuilder [37]
6 dup
7 ldc <String "first = "> [39]
9 invokespecial java.lang.StringBuilder(java.lang.String) [41]
12 getstatic com.ibm.oneteam.Main.first : int [16]
15 invokevirtual java.lang.StringBuilder.append(int) : java.lang.StringBuilder [44]
18 invokevirtual java.lang.StringBuilder.toString() : java.lang.String [48]
21 invokevirtual java.io.PrintStream.println(java.lang.String) : void [52]
24 return
Line numbers:
[pc: 0, line: 15]
[pc: 24, line: 16]
Local variable table:
[pc: 0, pc: 25] local: args index: 0 type: java.lang.String[]
}


七、对象引用
public class TestRef {  

public static void main(String[] args) {
StringBuffer a = new StringBuffer("a");
StringBuffer b = new StringBuffer("b");
append(a, b);
System.out.println(a.toString() + "," + b.toString());
b = a;
System.out.println(a.toString() + "," + b.toString());
}

public static void append(StringBuffer a, StringBuffer b) {
a.append(b);
b = a;
}
}

ab,b
ab,ab
这段代码就十分简单了,明白了引用拷贝就知道原因了。
相关标签: Java IBM