1. 程式人生 > >第五週動手動腦1

第五週動手動腦1

結果:

 1 package second;
 2 
 3 public class Test {
 4     /*
 5      * 類的初始化塊
 6      */    
 7     {
 8          value=100;
 9     }
10     public int value=200;//欄位的初始值
11     
12     public Test(){
13     }
14     /*
15      * 建構函式初始化
16      */
17     public Test(int value){
18         this.value=value;
19     }
20     public static void main(String[] args){
21         Test obj=new Test();
22         System.out.println(obj.value);//結果 100
23         
24         obj=new Test(300);
25         System.out.println(obj.value);//結果  300
26     }
27 }
View Code

總結:在執行類成員定義時,指定的預設值或類的初始化塊,執行哪個?  看哪個“排在後面”

 注:類的初始化塊不接受任何引數,而且,只要建立類的物件,它們就會被執行。

所以,類的初始化塊適合於封裝那些“物件建立時,必須執行的程式碼”

二、類的靜態欄位
1.例如:

1 class Employee{
2 String name;
3 long salary;
4 static int total;
5 }
View Code

2.訪問類的靜態欄位:通過物件名或類名作為字首訪問靜態資料

2.1類名直接訪問(推薦使用):Employee.total=1;

2.2物件名訪問:

Employee newhire=new Employee();

newhire.total=1;

三、類的靜態初始化塊

1.例子

 1 package first;
 2 
 3 
 4 class Root//父類
 5 {
 6     static{
 7         System.out.println("Root的靜態初始化塊");
 8     }
 9     {
10         System.out.println("Root的普通初始化塊");
11     }
12     public Root()
13     {
14         System.out.println("Root的無引數的構造器");
15     }
16 }
17 class Mid extends Root
18 {
19     static{
20         System.out.println("Mid的靜態初始化塊");
21     }
22     {
23         System.out.println("Mid的普通初始化塊");
24     }
25     public Mid()
26     {
27         System.out.println("Mid的無引數的構造器");
28     }
29     public Mid(String msg)
30     {
31         //通過this呼叫同一類中過載的構造器
32         this();
33         System.out.println("Mid的帶引數構造器,其引數值:" + msg);
34     }
35 }
36 class Leaf extends Mid//子類
37 {
38     static{
39         System.out.println("Leaf的靜態初始化塊");
40     }
41     {
42         System.out.println("Leaf的普通初始化塊");
43     }    
44     public Leaf()
45     {
46         //通過super呼叫父類中有一個字串引數的構造器
47         super("Java初始化順序演示");
48         System.out.println("執行Leaf的構造器");
49     }
50 
51 }
52 
53 public class TestStaticInitializeBlock
54 {
55     public static void main(String[] args) 
56     {
57         new Leaf();
58     
59     }
60 }
View Code

結果:

2.總結:

2.1靜態初始化塊只執行一次。

2.2建立子型別的物件時,會導致父型別的靜態初始化塊的執行

四、類的靜態方法(類的靜態方法只能訪問類的靜態成員!!!)

1.例如

1 class Employee{
2 String name;
3 long salary;
4 short employee_id;
5 static int total;
6 static void clear(){
7 total=0;
8 }
9 }
View Code

2.如何在靜態方法中訪問類的例項成員(即沒有附加static關鍵字的欄位或方法)?

public class Example
{
 int x = 3;//類的例項變數,初始化值為3
 static int  y = 4;//類的靜態變數,初始化值為4
 public static void method()//靜態方法
  {   
   System.out.println("例項變數x = " + new Example().x);//在靜態方法中訪問類的例項變數需首先進行類的例項化
   System.out.println("靜態變數y = " + y);//在靜態方法中可直接訪問類的靜態變數
  }

 public static void main(String[] args) 
    {
         Example.method();
         Example ex = new Example();
        System.out.println("x = " + ex.x);
    }
}
View Code

解決方案:在靜態方法中訪問類的例項變數需首先進行類的例項化

類中靜態的方法或者屬性,本質上來講並不是該類的成員,在java虛擬機器裝在類的時候,這些靜態的東西已經有了物件,它只是在這個類中"寄居",不需要通過類的構造器(建構函式)類實現例項化;而非靜態

的屬性或者方法,在類的裝載是並沒有存在,需在執行了該類的建構函式後才可依賴該類的例項物件存在。

在外部呼叫靜態方法時,可以使用"類名.方法名"的方式,也可以使用"物件名.方法名"的方式。而例項方法只有後面這種方式。也就是說,呼叫靜態方法可以無需建立物件。

五、Integer的詭異性

複製程式碼
public static void main(String[] args){
Integer i1=100;
Integer j1=100;
System.out.println(i1=j1);//true

Integer i2=129;
Integer j2=129;
System.out.println(i2=j2);//false
}
複製程式碼

原因:檢視原始碼可知,在通過valueOf方法建立Integer物件的時候,如果數值在[-128,127]之間,便返回指向IntegerCache.cache中已經存在的物件的引用;否則建立一個新的Integer物件。

複製程式碼
 1    * This method will always cache values in the range -128 to 127,
 2      * inclusive, and may cache other values outside of this range.
 3      *
 4      * @param  i an {@code int} value.
 5      * @return an {@code Integer} instance representing {@code i}.
 6      * @since  1.5
 7      */
 8     public static Integer valueOf(int i) {
 9         if (i >= IntegerCache.low && i <= IntegerCache.high)
10             return IntegerCache.cache[i + (-IntegerCache.low)];
11         return new Integer(i);
12     }
複製程式碼 複製程式碼
  /**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

        private IntegerCache() {}
    }
複製程式碼