黑馬程序員_JavaSE基礎知識總結七:new、this、static關鍵字和單例模式初步


------ android培訓java培訓、期待與您交流! ----------


一、new關鍵字

Person p = new Person( )為例,創建一個對象都在內存中做了什么事情?

1:先將硬盤上指定位置的Person.class文件加載進內存。

2:執行main方法時,在棧內存中開辟了main方法的空間(壓棧-進棧),然后在main方法的棧區分配了一個變量p。

3:在堆內存中開辟一個實體空間,分配了一個內存首地址值。

4:在該實體空間中進行屬性的空間分配,並進行了默認初始化。

5:對空間中的屬性進行顯示初始化。

6:進行實體的構造代碼塊初始化。

7:調用該實體對應的構造函數,進行構造函數初始化。

8:將首地址賦值給p ,p變量就引用了該實體。(指向了該對象)

 

 

二、this關鍵字

this 關鍵字指的是當前調用的對象,如果有100 個對象,將有100 個this 對象指向各個對象

this 關鍵字可以使用在:

①當局部變量和成員變量重名的時候可以使用this 指定調用成員變量;②通過this 調用另一個構造方法。

以下為具體實例:

1.當局部變量和成員變量重名的時候可以使用this 指定調用成員變量


<span style="font-size:18px;">public class OOTest09 {
public static void main(String[] args) {
Student zhangsan = new Student();
zhangsan.setId(1001);
zhangsan.setName("張三");
zhangsan.setSex(true);
zhangsan.setAddress("北京");
zhangsan.setAge(20);
System.out.println("id=" + zhangsan.getId());
System.out.println("name=" + zhangsan.getName());
System.out.println("sex=" + zhangsan.getSex());
System.out.println("address=" + zhangsan.getAddress());
System.out.println("age=" + zhangsan.getAge());
}
}

class Student {
// 學號
private int id;
// 姓名
private String name;
// 性別
private boolean sex;
// 地址
private String address;
// 年齡
private int age;

// 設置學號
public void setId(int id) {
this.id = id;
}

// 讀取學號
public int getId() {
return id;
}

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setSex(boolean sex) {
this.sex = sex;
}

public boolean getSex() {
return sex;
}

public void setAddress(String address) {
this.address = address;
}

public String getAddress() {
return address;
}

public void setAge(int age) {
this.age = age;
}

public int getAge() {
return age;
}
}</span>

通過this 可以取得當前調用對象,采用this 明確指定了成員變量的名稱,所以就不會賦值到局部變量,這里涉及到了狹義和廣義上的javabean 概念,在這里不詳述。

2.通過this 調用另一個構造方法

①通過new 調用當前對象的構造函數(注意這樣是不對的)


<span style="font-size:18px;">public class OOTest10 {
public static void main(String[] args) {
// Student zhangsan = new Student(1001, "張三", true, "北京", 20);
// Student zhangsan = new Student(1001, "張三");
Student zhangsan = new Student(1002, "李四");
System.out.println("id=" + zhangsan.getId());
System.out.println("name=" + zhangsan.getName());
System.out.println("sex=" + zhangsan.getSex());
System.out.println("address=" + zhangsan.getAddress());
System.out.println("age=" + zhangsan.getAge());
}
}

class Student {
// 學號
private int id;
// 姓名
private String name;
// 性別
private boolean sex;
// 地址
private String address;
// 年齡
private int age;

public Student(int id, String name) {
/*
* this.id = id; this.name = name; this.sex=true; this.address="北京";
* this.age=20;
*/
// 調用構造函數,部分值采用默認值
new Student(id, name, true, "北京", 20);
}

public Student(int id, String name, boolean sex, String address, int age) {
this.id = id;
this.name = name;
this.sex = sex;
this.address = address;
this.age = age;
}

// 設置學號
public void setId(int studentId) {
id = studentId;
}

// 讀取學號
public int getId() {
return id;
}

public void setName(String studentName) {
name = studentName;
}

public String getName() {
return name;
}

public void setSex(boolean studentSex) {
sex = studentSex;
}

public boolean getSex() {
return sex;
}

public void setAddress(String studentAddress) {
address = studentAddress;
}

public String getAddress() {
return address;
}

public void setAge(int studentAge) {
if (studentAge >= 0 && studentAge <= 120) {
age = studentAge;
}
}

public int getAge() {
return age;
}
}</span>

②通過this 調用當前對象的構造函數

<span style="font-size:18px;">public class OOTest11 {
public static void main(String[] args) {
Student zhangsan = new Student(1002, "李四");
System.out.println("id=" + zhangsan.getId());
System.out.println("name=" + zhangsan.getName());
System.out.println("sex=" + zhangsan.getSex());
System.out.println("address=" + zhangsan.getAddress());
System.out.println("age=" + zhangsan.getAge());
}
}

class Student {
// 學號
private int id;
// 姓名
private String name;
// 性別
private boolean sex;
// 地址
private String address;
// 年齡
private int age;

public Student(int id, String name) {
/*
* this.id = id; this.name = name; this.sex=true; this.address="北京";
* this.age=20;
*/
// 調用構造函數,部分值采用默認值
// new Student(id, name, true, "北京", 20);
// 采用this 調用當前對象對象的構造函數,不能采用new,以上調用是錯誤的
this(id, name, true, "北京", 20);
}

public Student(int id, String name, boolean sex, String address, int age) {
this.id = id;
this.name = name;
this.sex = sex;
this.address = address;
this.age = age;
}

// 設置學號
public void setId(int studentId) {
id = studentId;
}

// 讀取學號
public int getId() {
return id;
}

public void setName(String studentName) {
name = studentName;
}

public String getName() {
return name;
}

public void setSex(boolean studentSex) {
sex = studentSex;
}

public boolean getSex() {
return sex;
}

public void setAddress(String studentAddress) {
address = studentAddress;
}

public String getAddress() {
return address;
}

public void setAge(int studentAge) {
if (studentAge >= 0 && studentAge <= 120) {
age = studentAge;
}
}

public int getAge() {
return age;
}
}</span>

注意:用this調用構造函數,必須定義在構造函數的第一行。因為構造函數是用於初始化的,所以初始化動作一定要執行。否則編譯失敗。


三、Static關鍵字

1、特點

①static 修飾符可以修飾:變量、方法和代碼塊

②想要實現對象中的共性數據的對象共享。可以將這個數據進行靜態修飾。

③被靜態修飾的成員,可以直接被類名所調用。也就是說,靜態的成員多了一種調用方式。類名.靜態方式。

④靜態隨着類的加載而加載。而且優先於對象存在。

 

2、弊端

①有些數據是對象特有的數據,是不可以被靜態修飾的。因為那樣的話,特有數據會變成對象的共享數據。這樣對事物的描述就出了問題。所以,在定義靜態時,必須要明確,這個數據是否是被對象所共享的。

②靜態方法只能訪問靜態成員,不可以訪問非靜態成員。

因為靜態方法加載時,優先於對象存在,所以沒有辦法訪問對象中的成員。

③靜態方法中不能使用this,super關鍵字。

因為this代表對象,而靜態在時,有可能沒有對象,所以this無法使用。

④主函數是靜態的。

 

3、成員變量和靜態變量的區別

①成員變量所屬於對象,所以也稱為實例變量;靜態變量所屬於類,所以也稱為類變量。

②成員變量存在於堆內存中,靜態變量存在於方法區中。

③成員變量隨着對象創建而存在,隨着對象被回收而消失;靜態變量隨着類的加載而存在,隨着類的消失而消失。

④成員變量只能被對象所調用 ,靜態變量可以被對象調用,也可以被類名調用。

所以,成員變量可以稱為對象的特有數據,靜態變量稱為對象的共享數據。

那么什么時候定義靜態成員呢?或者說:定義成員時,到底需不需要被靜態修飾呢?

成員分兩種:

①成員變量。(數據共享時靜態化)

該成員變量的數據是否是所有對象都一樣?如果是,那么該變量需要被靜態修飾,因為是共享的數據。 如果不是,那么就說這是對象的特有數據,要存儲到對象中。 

②成員函數。(方法中沒有調用特有數據時就定義成靜態)

如何判斷成員函數是否需要被靜態修飾呢?

只要參考該函數內是否訪問了對象中的特有數據即可:如果有訪問特有數據,那方法不能被靜態修飾,如果沒有訪問過特有數據,那么這個方法需要被靜態修飾。

 

4、注意事項

①靜態的生命周期很長;②靜態代碼塊只執行一次(new 多個對象就只執行一次)。③靜態代碼塊、構造代碼塊、構造函數同時存在時的執行順序:靜態代碼塊——構造代碼塊——構造函數。④靜態代碼塊如果和主函數在同一類中,優先於主函數執行。

 

5、關於主函數的說明

Public:訪問權限最大。

static:不需要對象,直接類名即可。

void:主函數沒有返回值。

Main:主函數特定的名稱。

(String[] args):主函數的參數,是一個字符串數組類型的參數,jvm調用main方法時,傳遞的實際參數是 new String[0]。

 

jvm默認傳遞的是長度為0的字符串數組,我們在運行該類時,也可以指定具體的參數進行傳遞。可以在控制台,運行該類時,在后面加入參數。參數之間通過空格隔開。jvm會自動將這些字符串參數作為args數組中的元素,進行存儲。

 

四、單例模式初步

設計模式是可以重復利用的解決方案,設計模式的提出是在1995 年,是由4 位作者提出的,稱為GoF,也就是“四人組”提出的。

設計模式從結構上分為三類:創建型、結構性、行為型。

其中最簡單的設計模式就是單例了,單例這種模式,盡量少用,也有將其稱為“反模式”。

我們知道對象實例創建完成后,會放到堆中,如果堆中的實例過多,將會存在特別多的垃圾,這樣會導致一些問題,如內存溢出等,使用單例模式后,只會創建一個實例,顯著減少對象實例的個數,同時也會提高性能,因為不會頻繁的創建對象,這只是他的一個好處,初學者只需要了解這方面即可。

單例模式的三要素:

①在類體中需要具有靜態的私有的本類型的變量;

②構造方法必須是私有的;

③提供一個公共的靜態的入口點方法。

<span style="font-size:18px;">public class SingletonPatternTest01 {
public static void main(String[] args) {
// Singleton s1 = new Singleton();
// Singleton s2 = new Singleton();
// ............
Singleton.getInstance().test();
}
}

class Singleton {
// 靜態私有的本類的成員變量
private static Singleton instance = new Singleton();

// 私有的構造方法
private Singleton() {
}

// 提供一個公共的靜態的入口點方法
public static Singleton getInstance() {
return instance;
}

public void test() {
System.out.println("----------test----------");
}
}</span>







注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com