1. 程式人生 > >傳智播客-劉意-java深入淺出精華版學習筆記Day07

傳智播客-劉意-java深入淺出精華版學習筆記Day07

成員變數和區域性變數的區別:


成員變數:類中方法外

               堆記憶體中

                隨著物件的建立存在

                隨著物件的消失而消失

                有預設初始化值

區域性變數:方法定義中或者方法宣告上

                棧記憶體中

                隨著方法的呼叫而存在

                隨著方法呼叫完畢而消失

                沒有預設初始化值,必須定義賦值,然後才能使用(error:可能未初始化變數

【注意:區域性變數名稱可以和成員變數名稱一樣,在方法中使用的時候,採用的是就近原則】

形式引數是類名的時候如何呼叫:

上節課中我們提到,基本型別中,形式引數的改變不影響實際引數,引用型別中要影響。

引用型別包括類、介面和陣列。

在上面這個demo中,studentdemo建立了method方法,這個方法的形參是student型別的,形參名是s。

下面我們在main方法中呼叫這個studentdemo類。

如果你看到了一個方法的形式引數是一個類(引用型別),這裡需要的其實是該類的物件。

匿名物件:

沒有名字的物件。

【物件的的確確被建立了,但是它沒有名字,我們也不知道它的成員變數和方法名在堆記憶體中的地址。】

匿名物件的應用場景:

1.    僅僅只呼叫一次類中的方法的時候,呼叫方法。【newStudent().show();】

這種情況下,匿名物件 呼叫完畢就是垃圾,馬上就可以被回收了。如果我只要這麼一個方法,那麼我就拿出來用一下,就可以扔了。也就是我們俗話說的【撈一筆就跑】。

2.    匿名物件可以作為引數傳遞。比如作為引數傳給上面的方法。

多個匿名物件聯動,一個呼叫一次方法,一個作為引數傳遞。

【看懂即可,一般我們不會主動用這個玩意】

封裝:隱藏物件的屬性和實現細節,僅對外提供公共訪問方式。

被private修飾的成員只能在本類中訪問,不能在物件/其他類訪問。

比如說一個student類中,我把成員變數age設為private,設一個public方法set_age來設定age,這樣在物件中我就只能通過方法來設定age。

封裝隱藏了實現細節(不給你訪問),提供公共的訪問方式,提高了程式碼的複用性和安全性。

【就像膝上型電腦的後蓋】

private關鍵字:許可權修飾符,修飾成員變數和成員方法。被其修飾的成員只能在本類中被訪問。只有自己所在的類(中的方法)可以訪問自己。物件都不行。

private標準應用格式:把成員變數用private修飾,提供對應的getXxx和setXxx用法。

this關鍵字的概述和應用:

如果成員變數和區域性變數重名了,會發生什麼事?我們之前說過,變數的使用規則是就近原則,如果重名了,就好像是把自己賦給自己,賦值這個過程無法進行。

所以,需要對name進行限定。

限定的方法:對成員變數用this關鍵字限定。

為了實現在set和get方法中也能見名知意,我們要求採用同樣的命名,也就是要求要用this這個關鍵字。

this是當前類的物件的引用。

誰呼叫這個方法,this就代表誰!

【不過注意,如果沒有和成員變數重名的區域性變數,在方法中呼叫成員變數是不需要用this的。就算是按照就近原則,最近的也是成員變數】

構造方法:

回憶建立物件的格式:

Student s = new Student()

沒有括號的叫變數,有括號的叫方法。

所以,Student()這就是個方法。也就是,我寫Student()時,我實際上時呼叫了一個方法。

這就是Student類中的構造方法。在我寫出這一句時,這個方法被呼叫了。

構造方法:給物件的資料進行初始化

格式:

方法名與類名相同;沒有返回值,連void值都沒有;沒有具體的返回值

構造方法的注意事項:

1.    如果我們沒有給出構造方法,系統將自動提供一個無參構造方法。

2.    如果我們給出了構造方法,系統將不再提供。

3.    構造方法可以帶引數,也就是我們呼叫類時,把引數寫在括號裡。

4.    構造方法可以過載,規則和之前相同,方法名相同,形式引數不同。

因此,給成員變數賦值有兩種方式:set方法和構造方法

建議永遠自己給出無參構造方法。

重新給出類的組成:成員變數/成員方法/構造方法

建立物件做了哪些事情:


圖解在記憶體中的儲存方式:

 

下面有一段非常精彩的關於“什麼時候定義成員變數”的課,但是太長了,直接複製講義過來了。

/*

定義一個類Demo,其中定義一個求兩個資料和的方法,

定義一個測試了Test,進行測試。

變數什麼時候定義為成員變數:

如果這個變數是用來描述這個類的資訊的,那麼,該變數就應該定義為成員變數。

變數到底定義在哪裡好呢?

變數的範圍是越小越好。因為能及時的被回收。

*/

//方式1

/*

class Demo {

public int sum() {

int a = 10;

int b = 20;

int c = a + b;

return c;

}

}

*/

//方式1滿足了我們的要求,但是不好。

//因為參與操作的資料現在是固定的。

//方式2

/*

class Demo {

public int sum(int a,int b) {

return a + b;

}

}

*/

//方式2可以滿足我們的要求,但是呢我們學習過來面向物件的思想。

//我就再想,a,b可不可以定義為成員變數呢?

//如果可以,我們再改進一版

class Demo {

int a;

int b;

public int sum() {

return a + b;

}

}

//雖然這種方式可以,並且好像是符合了面向物件的思想。

//但是不好。

//因為我們曾經說過:類是一組相關的屬性和行為的集合。

//並且類是通過事物轉換過來的

//而類中的成員變數就是事物的屬性

//屬性是用來描述事物的

//同理:成員變數其實是用來描述類的。

//測試類

class Test {

public static void main(String[] args) {

//建立物件

//方式1測試

/*

Demo d = new Demo();

System.out.println(d.sum());

*/

//方式2測試

/*

Demo d = new Demo();

int a = 10;

int b = 20;

System.out.println(d.sum(a,b));

*/

//方式3測試

Demo d = new Demo();

d.a = 10;

d.b = 20;

System.out.println(d.sum());

}

}

static關鍵字:

當多個物件有共同的成員變數值時,java就提供了一個關鍵字來修飾:static

當一個類中的成員變數被定義為static時,所有該類的物件共享同一個值。

特點:

1. 隨著類的載入而載入。(比如跟著Demo類一起出現的main方法)

2. 優先於物件存在。(物件在new的時候才出現)

3. 被類的所有物件共享。(例子:所有人共用飲水機,但是不能共用水杯)

5.    可以通過類名呼叫。其實它本身也可以通過物件名呼叫。(反正都是一樣的)

【為什麼main方法是靜態的?因為它是被虛擬機器呼叫的。畢竟main方法所在的類,沒有物件】

推薦使用類名呼叫。

靜態修飾的內容我們一般稱其為:與類相關的類成員。

記憶體的分配方法:方法區中專門有一個靜態區,載入方法的時候同時載入進來。

記憶體圖解:

static關鍵字注意事項:

這一塊也很精彩,直接複製講義了

對於第一點,沒有this關鍵字的意思,其實是不能訪問非靜態的成員變數。

所以第二點和第二點是一樣的。

/*

static關鍵字注意事項

A:在靜態方法中是沒有this關鍵字的

如何理解呢?

靜態是隨著類的載入而載入,this是隨著物件的建立而存在。

靜態比物件先存在。

B:靜態方法只能訪問靜態的成員變數和靜態的成員方法

靜態方法:

成員變數:只能訪問靜態變數

成員方法:只能訪問靜態成員方法

非靜態方法:

成員變數:可以是靜態的,也可以是非靜態的

成員方法:可是是靜態的成員方法,也可以是非靜態的成員方法。

簡單記:

靜態只能訪問靜態。

*/

class Teacher{

public int num = 10;

public static int num2 = 20;

public void show() {

System.out.println(num); //隱含的告訴你訪問的是成員變數

System.out.println(this.num); //明確的告訴你訪問的是成員變數

System.out.println(num2);

//function();

//function2();

}

public static void method() {

//無法從靜態上下文中引用非靜態變數 num

//System.out.println(num);

System.out.println(num2);

//無法從靜態上下文中引用非靜態方法 function()

//function();

function2();

}

public void function() {

}

public static void function2() {

}

}

classTeacherDemo {

public static void main(String[] args) {

//建立物件

Teacher t = new Teacher();

t.show();

System.out.println("------------");

t.method();

}

}

 

為什麼main方法是靜態的:

public static void main(String[] args){…}

public:訪問許可權最大(因為要被jvm呼叫)

static:可以通過類名來呼叫,不需要建立物件

void:沒有返回值(返回給jvm沒有意義)

main:約定的程式開始的地方

String[] args:這是一個字串陣列。事實上,它是一個確實存在的、長度為零的、啥也沒有的陣列。

【事實上,這個東西早期是為了接收鍵盤錄入的資料的。這個用法已經廢棄了,成為了一種約定俗成的習慣。】