Java中this關鍵字 & static關鍵字
1. this關鍵字
this關鍵字主要有以下三個方面的用途:
- this呼叫本類屬性
- this呼叫本類方法
- this表示當前物件
1.1 this呼叫本類屬性
先看一段程式碼:
class Person{
private String name;
private int age;
public Person(String name, int age)
{
name = name;
age = age;
}
public String getPersonInfo()
{
return "姓名:" + name + " 年齡:" + age;
}
}
public class Test{
public static void main(String[] args){
Person per = new Person("張三", 20);
System.out.println(per.getPersonInfo());
}
}
執行結果如下: 大家會發現,明明例項化物件時,Person(“張三”, 20); 但是得出的結果卻是不是我們想要的結果。我們再看構造方法有了下面的程式碼:
name = name;
age = age;
通過以上程式碼我們可以發現,當引數中屬性同名是,類中屬性無法被正確賦值。此時我們加上this關鍵字便可正確給物件屬性賦值。
this.name = name;
this.age = age;
只要在類中方法訪問類中屬性,一定要加上this關鍵字。
1.2 this呼叫本類方法
this呼叫本類方法有一下兩種情況:
- 呼叫普通方法
this.方法名稱(引數);
- 呼叫構造方法
this.引數;
1.2.1 this呼叫普通方法
舉例:
class Person{
private String name;
private int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
this.print();//呼叫普通方法
}
public String getPersonInfo()
{
return "姓名:" + name + " 年齡:" + age;
}
public void print()
{
System.out.println("*******************");
}
}
public class Test{
public static void main(String[] args){
Person per = new Person("張三", 20);
System.out.println(per.getPersonInfo());
}
}
執行結果如下: 雖然呼叫本類普通方法不需要加上this也可以正常呼叫。但強烈建議加上,加上this的目的可以區分方法定義的來源(在繼承中有用)。
1.2.2 this呼叫構造方法
舉例:先觀察構造方法中存在的問題
class Person{
private String name;
private int age;
public Person()
{
System.out.println("********產生一個新的Person物件*******");
}
public Person(String name)
{
System.out.println("********產生一個新的Person物件*******");
this.name = name;
}
public Person(String name, int age)
{
System.out.println("********產生一個新的Person物件*******");
this.name = name;
this.age = age;
}
public String getPersonInfo()
{
return "姓名:" + name + " 年齡:" + age;
}
}
public class Test{
public static void main(String[] args){
Person per1 = new Person();
Person per2 = new Person("李四");
Person per3 = new Person("張三", 20);
System.out.println(per1.getPersonInfo());
System.out.println(per2.getPersonInfo());
System.out.println(per3.getPersonInfo());
}
}
上述程式碼在構造方法中出現了一些程式碼重複問題,想要解決此類問題,就需要用到this. 在Java中,支援構造方法的互相呼叫(this)。 修改程式碼如下:
class Person{
private String name;
private int age;
public Person()
{
System.out.println("********產生一個新的Person物件*******");
}
public Person(String name)
{
this();//呼叫本類無參構造
this.name = name;
}
public Person(String name, int age)
{
this();//呼叫本類有一個引數的構造方法
this.age = age;
}
public String getPersonInfo()
{
return "姓名:" + name + " 年齡:" + age;
}
}
public class Test{
public static void main(String[] args){
Person per1 = new Person();
Person per2 = new Person("李四");
Person per3 = new Person("張三", 20);
System.out.println(per1.getPersonInfo());
System.out.println(per2.getPersonInfo());
System.out.println(per3.getPersonInfo());
}
}
執行結果如下: 使用this呼叫構造方法時請注意:
- 只能在構造方法中使用this呼叫其他的構造方法,不能再成員方法中使用。
- 在構造方法中,使用this呼叫構造方法的語句必須位於第一行,且只能出現一次。下面的寫法時非法的,必須在寫程式碼時注意。
Public Person(String name, int age) {
this.age = age;
this(name); //呼叫有參的構造方法。由於不在第一行,編譯錯誤。
}
執行結果如下:
- 不能在一個類的兩個構造方法中使用this互相呼叫,下面的寫法編譯會報錯。
public Person(){
this("lisi");//呼叫有參的構造方法
System.out.println("****無參構造****");
}
public Person(String name){
this(); //呼叫無參的構造方法
System.out.println("****有參構造****");s
}
執行結果如下:
1.3 this表示當前物件
舉例:this表示當前物件
class Person{
public void print(){
System.out.println("[PRINT]方法:" + this);
}
}
public class Test{
public static void main(String[] args){
Person per1 = new Person();
System.out.println("[MAIN]方法: " + per1);
per1.print();
System.out.println("************************");
Person per2 = new Person();
System.out.println("[MAIN]方法: " + per2);
per2.print();
}
}
只要呼叫了本類中的方法,這個this就表示當前執行的物件。
2. static關鍵字
在Java類中定義了一個static關鍵字,它用於修飾類的成員,如成員變數、成員方法以及程式碼塊等。
2.1 static屬性(類屬性)
在定義一個類時,只是在描述某類事物的特徵和行為並沒有產生具體的資料。只有通過new關鍵字建立該類的例項物件後,系統才會為每個物件分配記憶體空間,儲存各自的資料。 但是有時候需要某些特定的資料在記憶體中只有一份,而且能夠被一個類的所有例項物件所共享。 舉例:例項屬性的記憶體分析
class Person{
String country = "中國";
String name;
int age;
public void getPersonInfo(){
System.out.println("姓名:" + this.name + ",年齡:" + this.age + ",國家:" + this.country);
}
}
public class Test{
public static void main(String[] args){
Person per1 = new Person();
per1.name = "zhangsan";
per1.age = 10;
Person per2 = new Person();
per2.name = "lisi";
per2.age = 20;
per1.getPersonInfo();
per2.getPersonInfo();
}
}
執行結果如下: 記憶體分析圖如下: 傳統屬性所具備的特徵:儲存在堆記憶體中,且每個物件獨享屬性。 描述共享屬性,只需在屬性前新增static關鍵字即可。 static屬性又稱為類屬性,儲存在全域性資料區的記憶體之中,所有物件都可以進行該資料區的訪問。 修改上述程式碼:
static String country = "中國";
此時的記憶體分析圖如下所示: 結論:
- 訪問static屬性應使用 類名稱 . 屬性名
- 所有的非static屬性(例項變數)必須在物件例項化後使用,而static屬性不收物件例項化控制
- 修改static屬性,所有物件都同步此屬性。應使用一下方法修改:
Person.country = "中國";
定義類時,如何選擇例項變數和類屬性呢?
- 在定義類時,99%的情況都不會考慮static屬性,以非static屬性(即例項變數)為主
- 如果需要描述共享屬性的概念,或者不受物件例項化控制,使用static
注意: static關鍵字只能用於修飾成員變數,不能用於修飾區域性變數,否則編譯會報錯,下面程式碼時非法的:
2.2 static方法(類方法)
使用static定義的方法,直接通過類名進行訪問。 類名稱 . 方法名 舉例:觀察static方法
class Person{
private static String country;
private String name;
private int age;
public Person(String name, int age){
this.name = name;
this.age = age;
}
public static void setCountry(String s){
country = s;
}
public void getPersonInfo(){
System.out.println("姓名:"+this.name+",年齡:"+this.age+"國家:"+this.country);
}
}
public class Test{
public static void main(String[] args){
Person per = new Person("zhangsan", 20);
per.getPersonInfo();
Person.setCountry("中國");
per.getPersonInfo();
}
}
關於static方法有以下兩點說明:
- 所有的static方法不允許呼叫非static定義的屬性或方法
- 所有的非static方法允許訪問static方法或屬性
使用static定義的方法只有一個目的:某些方法不希望受到類的控制,即可以在沒有例項化物件的時候執行(廣泛存在於工具類中)。 注意: 在一個靜態方法中只能訪問用static修飾的成員,原因在於沒有被static修飾的成員需要先建立物件才能訪問,而靜態方法被呼叫時可以不建立任何物件。 例項物件同樣可以呼叫靜態方法。
public class Test{
public static void main(String[] args){
//類名.方法的方式呼叫靜態方法
Person.setCountry("中國");
Person per = new Person("zhangsan", 20);
per.getPersonInfo();
//例項化物件的方式來呼叫靜態方法
per.setCountry("China");
per.getPersonInfo();
}
}
執行結果如下所示:
由static修飾的還有程式碼塊,稱為 靜態程式碼塊, 這些我們在後面的總結會寫到。