java學習(九)static和this使用
static:翻譯爲靜態
-
所有static關鍵詞修飾的都是類相關的,不需要new對象,都是採用類名.的形式訪問,不會出現空指針異常
-
static修飾的方法稱爲靜態方法,static修飾的變量稱爲靜態變量
複習變量(引出靜態變量)
-
方法體內聲明的變量叫局部變量
-
方法體外聲明的變量叫成員變量
-
成員變量可以分爲靜態變量和實例變量,在實例變量前加static關鍵詞就是靜態變量了
-
靜態代碼塊
-
靜態代碼塊在類加載時執行,並且只執行一次。 靜態代碼塊實際上是 java 語言爲程序員準備的一個特殊的時刻,這個時刻就 是類加載時刻。
靜態代碼塊:
public class StaticTest01{ //靜態代碼塊 static{ System.out.println(111); //先執行 } public static void main(String[] args) { System.out.println("main 執行!"); //最後執行 } //靜態代碼塊 static{ System.out.println(222); //然後執行 } } //靜態代碼塊先執行,然後纔是方法執行
-
可以得知:靜態代碼塊是在main方法之前執行的,是因爲靜態代碼塊在類加載時執行,並且只執行一次。
訪問靜態變量和實例變量
public class StaticTest02{ //實例變量 int i = 100; //靜態變量 static int j = 111; static{ System.out.println(i); //java:11: 錯誤: 無法從靜態上下文中引用非靜態 變量 i System.out.println(j); //編譯成功 } public static void main(String[] args){ System.out.println("Hello World!"); } }
靜態屬性
-
當一個類的某個屬性值不會隨着對象的改變而變化的時候,建議將該屬性定義爲靜態屬性。
-
靜態變量在類加載的時候初始化,存儲在方法區當中,不需要創建對象,直接通過類名訪問
靜態方法
-
在實際的開發中,“工具類”當中的方法一般定義爲靜態方法,因爲工具類就是爲 了方便大家的使用,將方法定義爲靜態方法,比較方便調用,不需要創建對象,直接使用類名 就可以訪問。
-
當某個動作 在觸發的時候需要對象的參與,這個方法應該定義爲實例方法
java中的this是什麼,內存中存儲在哪裏,要掌握 this 在實例方法和構造方法中的 用法。
-
this 可以看做一個變量,它是一個“引用”,存儲在 Java 虛擬機堆內存的對象內部,this 這個“引用”保存了當前對象的內存地址指向自身,任何一個堆內存的 java 對象都有一個 this 。
-
this 指向“當前對象”,也可以說 this 代表“當前對象”,this 可以使用在實例方法中以及 構造方法中,語法格式分別爲“this.”和“this(..)”。this 不能出現在帶有 static 的方法當中。
public class ThisInStaticMethod{ public static void main(String[] args) { ThisInStaticMethod.method(); } public static void method(){ System.out.println("method執行"); System.out.println(this); //java:11: 錯誤: 無法從靜態上下文中引用非靜態 變量 this } }
得知:this不能出現在 static的方法當中,static 方法執行的過程中是不需要“當前對象”參與的,所以 static 的方法中不能使用 this,因爲 this 代表的 就是“當前對象”。
this:this只能在實例方法中使用,誰調用這個實例方法,this就是誰,this是當前對象和python的self差不多
public class Customer{ private String name; //無參構造方法 public Customer(){ } //有參構造方法 public Customer(String _name){ name = _name; } //set public void setName(String _name){ name = _name; } //get public String getName(){ return name; } //定義一個方法 public void shopping(){ System.out.println(name + "is shopping!"); //誰調用就打印誰 } }
調用
public class Customer{ private String name; //無參構造方法 public Customer(){ } //有參構造方法 public Customer(String _name){ name = _name; //這裏的name就是實例變量neme,_name是接收的局部變量 } //set public void setName(String _name){ name = _name; } //get public String getName(){ return name; } //定義一個實例方法 public void shopping(){ System.out.println(this.name + "is shopping!"); //誰調用就打印誰 System.out.println(name + "is shopping!"); //誰調用就打印誰 } }
得 知 :在實例方法中可以 直接訪問當前對象的實例變量,而“this.”是可以省略的。
那麼this在什麼時候不能省略?
當接收的局部變量參數和實例變量相同的時候,例:name = name;需要寫成this.name = name這裏的this就不可以省略了哈哈哈哈。【否則name = name這兩個name都會被識別成局部變量哦】
上面Customer代碼塊修改:
//定義一個實例方法 public void shopping(){ System.out.println(name + "is shopping!"); //誰調用就打印誰 System.out.println(this.name + "is shopping!"); //誰調用就打印誰 this.pay(); //省略this pay(); } //再定義一個實例方法 public void pay(){ System.out.println(name + "付錢付錢"); } } /* jackis shopping! jackis shopping! jack付錢付錢 jack付錢付錢 分界線=============================== roseis shopping! roseis shopping! rose付錢付錢 rose付錢付錢 */
得出:在一個實例方法當中可以直接去訪問其它的實例方法
代碼
public class ThisTest { int i = 10; public static void main(String[] args) { //System.out.println(i); //錯誤: 無法從靜態上下文中引用非靜態 變量 i。因爲main方法有static,i是實例變量,要用引用.去訪問 //System.out.println(this.i); // 錯誤: 無法從靜態上下文中引用非靜態 變量 this。因爲 main 方法帶有 static,不能用 this(代表當前對象) ThisTest tt = new ThisTest(); //通過引用訪問 System.out.println(tt.i); } }
得知:
-
在 static 的方法中不能直接訪問實例變量,須先自己創建一個對象,通過“引用”可以去訪問。
-
在 static 的方法中不能通過 this 訪問實例變量,因爲在 static 方 法中是不能存在 this 的。
同理:
-
main 方法中無法直接調用實例方法 ,因爲實例方法也必須要new對象,通過引用調用
this 使用在構造方法中,this(實際參數列表);調用另一個有參的構造方法
-
this();語法要在同一個類中使用
-
this();只能在構造方法第一行,前面不能有其他代碼
public class ThisTest02{ public static void main(String[] args){ //調用無參構造 Date d1 = new Date(); d1.detail(); //調用有參構造 Date d2 = new Date(2020,06,19); d2.detail(); } } class Date{ private int year; private int month; private int day; //業務要求,默認創建的日期爲 1970 年 1 月 1 日 //無參構造方法 public Date(){ /* this.year = 1970; this.month = 1; this.day = 1; */ //System.out.println("隨便寫一行代碼在this()前"); //錯誤: 對this的調用必須是構造器中的第一個語句 //無參構造方法調用有參構造方法1行代碼 this(1970,1,1); } //有參構造方法 public Date(int year,int month,int day){ this.year = year; this.month = month; this.day = day; } //定義一個打印年齡的方法 public void detail(){ System.out.println(year + "年" + month +"月" + day + "日"); } //set和get public void setYear(int year){ this.year = year; } public int getYear(){ return year; } public void setMonth(int month){ this.month = month; } public int getMonth(){ return month; } public void setDay(int day){ this.day = day; } public int getDay(){ return day; } }
小總結:
-
代碼封裝,屬性一般都私有化
-
都要有兩個構造方法,一個無參構造,一個有參構造。(對象屬性的 初始化)
-
都要有對應的set和get方法,這是封裝的規定,就算暫時用不到也要寫。
-
封裝的get方法要指定返回值的類型,不需要傳參。
-
封裝的set方法不需要返回值,所以返回值類型固定寫法void,但是需要傳參數。
-
只要調用的方法a和被調用的方法b是在同一個類裏面,this.和類名.可以省略
銀行存取款代碼:其實這3個類寫入3個文件內比較好
public class TestCustomerAccount{ public static void main(String[] args){ Account a = new Account("10086",1000,0.0023); Customer c = new Customer("smth",a); //存100 //取960 //取200 c.getAct().deposite(100); c.getAct().withdrow(960); c.getAct().withdrow(2000); } } //客戶類 class Customer{ private String name; private Account act; //構造方法 public Customer(){ } //有參構造 public Customer(String name,Account act){ this.name = name; this.act = act; } //set 和 get方法 public void setName(String name){ this.name = name; } public String getName(){ return name; } public void setAct(Account act){ this.act = act; } public Account getAct(){ return act; } } //賬號類 class Account{ private String id; private double balance; //餘額實例屬性 private double annualInterestRate; //年利率實例屬性 //無參構造 public Account(){ } //有參構造, public Account(String id, double balance, double annualInterestRate){ //構造方法是創建對象的時候,對象的屬性初始化 this.id = id; this.balance = balance; this.annualInterestRate = annualInterestRate; } //各屬性set和get,這裏是後期查詢和修改需要 //爲啥每個類都寫set和get方法,用不到也要寫,因爲這是“封裝”的規定 public String getId(){ return id; } public void setId(String id){ this.id = id; } public double getBalance(){ return balance; } public void setBalance(double balance){ this.balance = balance; } public double getAnnualInterestRate(){ return annualInterestRate; } public void setAnnualInterestRate(double annualInterestRate){ this.annualInterestRate = annualInterestRate; } //存錢方法 //存錢要傳一個參數告訴存多少錢 public void deposite(double money){ //this.balance += money; this.setBalance(this.getBalance() + money); System.out.println("存款成功" + money); } //取錢方法 //取錢需要傳一個參數告訴取多少錢 public void withdrow(double money){ if(money > this.getBalance()){ System.out.println("餘額不足,取款失敗"); return; } this.setBalance(this.getBalance() - money); System.out.println("取款成功"+ money); } }