1. 程式人生 > 其它 >java 初始化

java 初始化

初始化

這裡的主要內容是 初始化相關的內容,其中還會穿插其他的內容

  1. 構造器初始化
  2. 靜態資料初始化
  3. 顯示的靜態初始化
  4. 非靜態例項初始化

穿插內容

  1. 構造器
  2. 方法過載
  3. this關鍵字
  4. static 關鍵字

構造器初始化

構造器

​ 構造器是在建立物件時被呼叫的特殊方法。(構造器是一個方法只不過它是特殊的),之所以特殊是因為構造器沒有返回值。與返回空(void)不同。一個簡單的說法,普通方法就算是void,還是可以掉的,但構造器沒得改。構造器是一個靜態的方法,

​ 構造器中的方法名與它所在的類名相同。這是因為為了讓編譯器能夠知道該呼叫那個方法。在建立物件時,編譯器將為物件分配儲存空間,並呼叫相應的構造器,這保證了你在操作物件之前,恰當的初始化了。

public class Apple {
    // 預設構造器
    Apple(){
        System.out.println("Hello Word");
    }
}

class Test{
    public static void main(String[] args){
        Apple apple = new Apple();
    }
}

​ 沒有引數出入的構造器叫預設構造器,術語是無參構造器,有引數的叫有參構造器。

public class Apple {
    //有參構造器
    Apple(String a){
        System.out.println(a);
    }
}

class Test{
    public static void main(String[] args){
        Apple apple = new Apple("Hello Word");
    }
}

​ 如果 Apple(String) 是類裡唯一一個構造器,那麼你在建立物件時必須傳入引數。

注意:在java中初始與建立是捆綁在一起的,二者不能分離

​ 預設構造器在沒有其它的構造器時,編譯器會自動建立一個預設構造器,如果類中有了構造器(無論是否有引數),編譯器就不會自動建立了。如果沒有構造器,就無法建立物件。

​ 像下邊這麼寫就會編譯器會報錯,因為 編譯器沒有找到 new Apple(); 沒有引數的構造器

public class Apple {
    Apple(String a){
        System.out.println(a);
    }

    public void t(){
        return;
    }
}

class Test{
    public static void main(String[] args){
        Apple apple = new Apple();
    }
}

像下邊加一個無參構造器即可。

public class Apple {
    Apple(){
        System.out.println("Hello Word");
    }
    Apple(String a){
        System.out.println(a);
    }

    public void t(){
        return;
    }
}

class Test{
    public static void main(String[] args){
        Apple apple = new Apple();
    }
}

​ 在上邊的 Apple 類中,兩個構造器它們名字相同,傳入的引數不同,這種寫法叫 方法過載,在普通方法中也同樣適用

方法過載

​ 方法過載就好比相同的詞可以表達不同的含義,過載方法名字要相同其中一個重要原因是因為構造器,的名字要與類名相同,這樣只有一個構造器名,就可用多種方式建立一個物件。普通方法的過載也和構造器一樣。

public class Apple {
    /*   過載構造器   */
    Apple(){
        
    }
    
    Apple(String name){
        
    }
    
    Apple(String name, Integer num){
        
    }
    
    Apple(Integer num, String name){
        
    }
    
    

    /*   過載的方法  */

    /**
     * 獲取蘋果
     */
    public void getApple(){
        
    }

    /**
     * 獲取特定品種的蘋果
     * @param type 品種
     */
    public void getApple(String type){
        
    }

    /**
     * 獲取特定品種,即某一數量的蘋果
     * @param type 蘋果品種
     * @param num 蘋果數量
     */
    public void getApple(String type, Integer num){
        
    }

    /**
     * 獲取特定品種,即某一數量的蘋果
     * @param num 蘋果品種
     * @param type 蘋果數量
     */
    public void getApple(Integer num, String type){
        
    }
    
}

​ java區分方法名相同的方法,是根據每個方法的獨一無二的引數列表去區分的。

​ 如下這種情況雖然java允許 ,也最好不要用,因為會使得程式難以維護

    
    Apple(String name, Integer num){
        
    }
    
    Apple(Integer num, String name){
        
    }
	
	/**
     * 獲取特定品種,即某一數量的蘋果
     * @param type 蘋果品種
     * @param num 蘋果數量
     */
    public void getApple(String type, Integer num){
        
    }

    /**
     * 獲取特定品種,即某一數量的蘋果
     * @param num 蘋果品種
     * @param type 蘋果數量
     */
    public void getApple(Integer num, String type){
        
    }
    

拓展:java為什麼不用返回區過載方法。

​ 有的時候並不需要一個方法返回東西,只需要方法本身的作用。

    public void test(){
        a();
    }
    public void test(String name){
        b(name);
    }

this 關鍵字

​ this關鍵字只能在方法內部使用,表示“呼叫方法的那個物件”。比如在Apple類的後一個方法中使用了this,this代表的就是Apple類。

public class Apple {


    public void getApple(){

    }

    public void juice(){
        this.getApple();
    }
}

注意:在上邊的 juice() 方法中有呼叫,同一個類中的方法 getApple() ,在這裡是沒有必要加 this的,因為編譯器會自動幫忙加上。雖然手動加也可以,不過高階語言之所以高階,其中一個原因就是它可以幫助我們省略一些重複的事情。

​ 只用當需要指明當前物件時才需要使用 this

public class AppleNum {

    private int appleNum = 0;

    public AppleNum sumAppleNum(){
        appleNum ++;
        return this;
    }

    public void print(){
        System.out.println("總和:" + appleNum);
    }

    public static void main(String[] args) {
        AppleNum appleNum = new AppleNum();
        appleNum.sumAppleNum().sumAppleNum().sumAppleNum().print();
    }

}

​ 如上程式碼 sumAppleNum() 方法返回的 appleNum 物件的引用,從而使得可以迴圈呼叫 sumAppleNum() 方法。

​ this 可以有引數列表用於構造器呼叫構造器,構造器不能使用方法名呼叫構造器,也不能在普通方法普通方法中。在同一個構造其中 this只能呼叫一個構造器。

    AppleNum(){
        this("a");
        
    }
    AppleNum(String type){
        this(3);
    }
    AppleNum(Integer i){

    }


    public AppleNum sumAppleNum(){
        // this(3)  編譯器會報錯
    }

成員初始化

​ 如果類中的基本型別欄位沒有初始化,那java會為他們賦上預設值

public class Apple {

    boolean t ;
    char c;
    byte b;
    short s;
    int i;
    long l;
    float f;
    double d;
    Apple apple;

    public void get(){
        System.out.println(t);
        System.out.println(c);
        System.out.println(b);
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(apple);
    }

    public static void main(String[] args) {
        Apple apple = new Apple();
        apple.get();
    }

}

從上邊程式碼可以看出,基本型別變數沒賦值,java會預設賦上初始值。物件賦上 null,初始化的順序,影響著程式的正確性。

靜態資料初始化

​ 除非用 new 建立物件,否則實際上並未獲得任何物件。如果不想建立物件也能呼叫某一方法或屬性,就可以使用static 關鍵字。當宣告一個事物是 static 時,就意味著這個域或方法不會它所在的類的物件例項關聯在一起。

static關鍵字

加上了 static關鍵字,即為靜態成員變數。

public class Apple {
    
    static int i = 1;
    
    public static void get(){
        
    }

    public static void main(String[] args) {
        Apple.get();
        int num = Apple.i;
    }

}

上邊展示了 static 關鍵字的基本用法,不用 new 物件也可以呼叫方法,雖然不用建立物件也可以呼叫方法,並不是說每個方法都加上 static, 如果你的程式碼是這樣,那你就得考慮一些你程式碼的設計問題了。

​ 下邊是加了 static,與沒加 static 的區別

public class Apple {

    static int i = 1;
    int b = 2;

    public void get() {
        System.out.println(i);
        System.out.println(b);
    }

    public void  set(int b){
        // 這裡因為入參的名字,與欄位名相同 一般使用 this 將其區分
        this.b = b;
    }

    public static void main(String[] args) {
        Apple a = new Apple();
        Apple b = new Apple();
        a.get();
        b.get();

        /*====*/
        System.out.println(" /*====*/ ");
        Apple.i = 10;
        b.set(3);
        a.set(4);

        a.get();
        b.get();
    }
}

通過上邊的輸出返現 , a b 兩個物件在輸出 i 時是相同的,a.i b.i指向了同一個記憶體地址。這也說明多了無論建立多少物件,靜態資料都只佔一份儲存區域。

​ 靜態初始化只有在必要時刻才會進行,例如,如果建立 Apple 物件 或者 不呼叫 Apple.i 那靜態的 i 永遠不會被創建出來。

顯示的靜態初始化

多個靜態初始化,可以簡化成一個靜態塊

public class Apple {
    static {
        int i;
        char a;
        Apple c= new Apple()
    }
}

上邊這麼寫,因為是在大括號裡,意味著是區域性變數除非將物件返回出去,否則外邊的方法,裡邊的屬性

public class Apple {
    Apple c;
    static {
        c = new Apple();
    }
}

非靜態例項初始化

非靜態例項初始化,看起來和靜態塊非常像,區別就是沒有 static 關鍵字

public class Apple {
    Apple c;
    {
        int i;
        char a;
        c = new Apple();
    }
}

這個寫法的非靜態初始化主要是為了匿名內部類準備的。這保證了不管呼叫那個構造器這部分程式碼都會被自行

public class Apple {
    Apple(){
        System.out.println("5");
    }

    {
        System.out.println("2");
    }
    static {
        System.out.println("1");
    }

    {
        System.out.println("4");
    }

    {
        System.out.println("3");
    }


    public static void main(String[] args) {
        Apple apple = new Apple();
    }
}

從上邊的程式碼執行輸出可以看出,靜態塊先被執行,然後是非靜態塊,最後是,構造器