1.早期我們經常這樣定義變量
? ? ? ? ? ? ?int value=100;
? ? ?前面的示例中這樣定義變量
? ? ? ? ? ? ?MyClass obj = new MyClass();
這兩種方式定義的變量是一樣的嗎?
?
這兩種方式定義的變量是一樣的,因為它們都是類的實例化,只是第一種是一個簡便的寫法,第二種是正常的對類進行實例化。
?
2.對象變量也可以使用“==”判斷兩變量值是否相等嗎?
當“==”施加于引用類型變量時,是比較這兩個變量是否引用同一對象,換句話說,“==”實際上相當于比較兩個引用類型變量中保存的對象地址是否相同。
在Java中要比對兩個對象的字段值,可以重寫基類的equals()方法。將其改成自己類的一個方法用來調用。
?
3.請輸入并運行以下代碼,得到什么結果?
public class Test {public static void main(String[] args) {Foo obj1=new Foo();Foo obj2=new Foo();System.out.println(obj1==obj2);}} class Foo{int value=100; }
運行結果:
原因:按照第2條,我們可知,“==”實際上相當于比較兩個引用類型變量中保存的對象地址是否相同。obj1和obj2雖然都是Foo類型的變量,但其指向的空間或者地址不同,所以輸出的是false。
?
4.
請總結一下,這個方法有哪些“與眾不同之處”,你能列出幾條?
?1.方法名與類名完全相同。
2.無返回值,也沒有void關鍵字。
?
5.以下代碼為何無法通過編譯?哪兒出錯了?
?
原因:在類中如果提供了一個構造函數,那么在進行類的實例化時,調用的就是這個構造函數。此例中,Foo類本身提供了一個有參構造函數,這就導致系統不會提供默認的構造函數,那么定義obj1時就無法調用無參構造函數,所以整個程序當中會出現錯誤。
?
?6.如果一個類中既有初始化塊,又有構造方法,同時還設定了字段的初始值,誰說了算?
例:
1 public class InitializeBlockClass { 2 3 { 4 5 field = 200; 6 7 } 8 9 public int field = 100; 10 11 public InitializeBlockClass(int value){ 12 13 this.field = value; 14 15 } 16 17 public InitializeBlockClass(){ 18 19 } 20 21 public static void main(String[] args) { 22 // TODO Auto-generated method stub 23 InitializeBlockClass obj = new InitializeBlockClass(); 24 25 System.out.println(obj.field); 26 27 28 obj = new InitializeBlockClass(300); 29 30 System.out.println(obj.field); 31 32 } 33 34 }
運行結果:
Java字段初始化的規律:
如果有多個不同地方對字段進行初始化,那么該字段的最終取值取決于最后一次初始化。
?
7.請運行TestStaticInitializeBlock.java示例,觀察輸出結果,總結出“靜態初始化塊的執行順序”。
TestStaticInitializeBlock.java
1 class Root 2 { 3 static{ 4 System.out.println("Root的靜態初始化塊"); 5 } 6 { 7 System.out.println("Root的普通初始化塊"); 8 } 9 public Root() 10 { 11 System.out.println("Root的無參數的構造器"); 12 } 13 } 14 class Mid extends Root 15 { 16 static{ 17 System.out.println("Mid的靜態初始化塊"); 18 } 19 { 20 System.out.println("Mid的普通初始化塊"); 21 } 22 public Mid() 23 { 24 System.out.println("Mid的無參數的構造器"); 25 } 26 public Mid(String msg) 27 { 28 //通過this調用同一類中重載的構造器 29 this(); 30 System.out.println("Mid的帶參數構造器,其參數值:" + msg); 31 } 32 } 33 class Leaf extends Mid 34 { 35 static{ 36 System.out.println("Leaf的靜態初始化塊"); 37 } 38 { 39 System.out.println("Leaf的普通初始化塊"); 40 } 41 public Leaf() 42 { 43 //通過super調用父類中有一個字符串參數的構造器 44 super("Java初始化順序演示"); 45 System.out.println("執行Leaf的構造器"); 46 } 47 48 } 49 50 public class TestStaticInitializeBlock 51 { 52 public static void main(String[] args) 53 { 54 new Leaf(); 55 56 57 } 58 }
執行結果:
“靜態初始化塊的執行順序”:
1.靜態初始化塊只執行一次。
2.創建子類型的對象時,也會導致父類型的靜態初始化塊的執行。
?
8.靜態方法中只允許訪問靜態數據,那么,如何在靜態方法中訪問類的實例成員(即沒有附加static關鍵字的字段或方法)?
在靜態方法中使用new進行實例化,然后再調用非靜態成員。
例:
1 public class Task { 2 3 public int a = 2; 4 5 static int b = 3; 6 7 static void display() 8 9 { 10 11 Task t1 = new Task(); 12 13 System.out.println("a="+t1.a); 14 15 } 16 public static void main(String[] args) { 17 // TODO Auto-generated method stub 18 Task t2 = new Task(); 19 20 t2.display(); 21 22 } 23 24 }
執行結果:
?
9.請看以下的神奇代碼:
public class StrangeIntegerBehavior {
public static void main(String[] args){Integer i1=100;Integer j1=100;System.out.println(i1==j1);Integer i2=129;Integer j2=129;System.out.println(i2==j2);}}
執行結果:
兩對整數明明完全一樣,為何一個輸出true,一個輸出false?
?首先,利用javap對該程序進行反匯編。結果如圖:
可以看到其調用了Integer中的valueOf方法,valueOf方法的源代碼為:
可以看到,valueOf(int i)調用了IntegerCache.cache,通過網上查找,我得到了它的源代碼如下:
1 private static class IntegerCache { 2 static final int low = -128; 3 static final int high; 4 static final Integer cache[]; 5 6 static { 7 // high value may be configured by property 8 int h = 127; 9 String integerCacheHighPropValue = 10 sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); 11 if (integerCacheHighPropValue != null) { 12 try { 13 int i = parseInt(integerCacheHighPropValue); 14 i = Math.max(i, 127); 15 // Maximum array size is Integer.MAX_VALUE 16 h = Math.min(i, Integer.MAX_VALUE - (-low) -1); 17 } catch( NumberFormatException nfe) { 18 // If the property cannot be parsed into an int, ignore it. 19 } 20 } 21 high = h; 22 23 cache = new Integer[(high - low) + 1]; 24 int j = low; 25 for(int k = 0; k < cache.length; k++) 26 cache[k] = new Integer(j++); 27 28 // range [-128, 127] must be interned (JLS7 5.1.7) 29 assert IntegerCache.high >= 127; 30 } 31 32 private IntegerCache() {} 33 }
通過這兩段代碼,我們可知,在[-128,127]這個區間中“”==”比較的是這兩個數的數值,但當超出這個范圍時,其就會創建一個新的對象,對于對象來說,我們是無法通過“==”進行比較的,因為“==”比較的是這兩個對象所指向的空間是否相同,所以第二個會輸出false。