我們來看看this是否可以出現(xiàn)在static的方法當(dāng)中,請(qǐng)看以下代碼以及編譯結(jié)果:
public class ThisInStaticMethod {
public static void main(String[] args) {
ThisInStaticMethod.method();
}
public static void method(){
System.out.println(this);
}
}
編譯報(bào)錯(cuò),如下圖所示:
圖11-2:static的方法中不能使用this
通過以上的測(cè)試得知this不能出現(xiàn)在static的方法當(dāng)中,這是為什么呢?首先static的方法,在調(diào)用的時(shí)候是不需要?jiǎng)?chuàng)建對(duì)象的,直接采用“類名”的方式調(diào)用,也就是說static方法執(zhí)行的過程中是不需要“當(dāng)前對(duì)象”參與的,所以static的方法中不能使用this,因?yàn)閠his代表的就是“當(dāng)前對(duì)象”。
大家是否還記得在之前的“封裝”過程中,曾編寫屬性相關(guān)的set和get方法,set和get方法在聲明的時(shí)候不允許帶static關(guān)鍵字,我們把這樣的方法叫做實(shí)例方法,說到實(shí)例方法,大家肯定想到了實(shí)例變量,沒錯(cuò),實(shí)例變量和實(shí)例方法都是對(duì)象相關(guān),必須有對(duì)象的存在,然后通過“引用”去訪問。
為什么set和get方法設(shè)計(jì)為實(shí)例方法呢?那是因?yàn)閟et和get方法操作的是實(shí)例變量,“不同的對(duì)象”調(diào)用get方法最終得到的數(shù)據(jù)是不同的,例如zhangsan調(diào)用getName()方法得到的名字是zhangsan,lisi調(diào)用getName()方法得到的名字是lisi,顯然get方法是一個(gè)對(duì)象級(jí)別的方法,不能直接采用“類名”調(diào)用,必須先創(chuàng)建對(duì)象,再通過“引用”去訪問。
this可以出現(xiàn)在實(shí)例方法當(dāng)中,因?yàn)閷?shí)例方法在執(zhí)行的時(shí)候一定是對(duì)象去觸發(fā)的,實(shí)例方法一定是對(duì)象才能去調(diào)用的,而this恰巧又代表“當(dāng)前對(duì)象”,所以“誰”去調(diào)用這個(gè)實(shí)例方法this就是“誰”。測(cè)試一下,請(qǐng)看以下代碼:
public class Customer {
private String name;
public Customer(){
}
public Customer(String _name){
name = _name;
}
public void setName(String _name){
name = _name;
}
public String getName(){
return name;
}
public void shopping(){
System.out.println("shopping() --> " + this);
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer jack = new Customer("jack");
System.out.println("main() ---> " + jack);
jack.shopping();
System.out.println("====================");
Customer rose = new Customer("rose");
System.out.println("main() ---> " + rose);
rose.shopping();
}
}
運(yùn)行結(jié)果如下圖所示:
圖11-3:測(cè)試this
以上代碼的輸出結(jié)果具體是什么不重要,重要的是可以看出誰和誰是相等的。運(yùn)行結(jié)果和代碼結(jié)合起來分析一下this:
圖11-4:this指向了當(dāng)前對(duì)象
通過以上內(nèi)容的學(xué)習(xí)得知,this可以使用在實(shí)例方法當(dāng)中,它指向當(dāng)前正在執(zhí)行這個(gè)動(dòng)作的對(duì)象。
大家是否還記得實(shí)例變量怎么訪問?正規(guī)的訪問方式是采用“引用.”去訪問。請(qǐng)看下面的代碼:
public class Customer {
private String name;
public Customer(){
}
public Customer(String _name){
name = _name;
}
public void setName(String _name){
name = _name;
}
public String getName(){
return name;
}
public void shopping(){
System.out.println(name + " is shopping!");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer jack = new Customer("jack");
jack.shopping();
Customer rose = new Customer("rose");
rose.shopping();
}
}
運(yùn)行結(jié)果如下圖所示:
圖11-5:測(cè)試結(jié)果
將以上部分代碼片段取出來進(jìn)行分析:
public class Customer {
private String name; //實(shí)例變量
...
public void shopping(){
//jack調(diào)用shopping,當(dāng)前對(duì)象是jack
//rose調(diào)用shopping,當(dāng)前對(duì)象是rose
//name是實(shí)例變量,不用“引用”可以訪問?(以上結(jié)果表示可以)
System.out.println(name + " is shopping!");
//正規(guī)的訪問方式應(yīng)該是“引用.name”,比如
//System.out.println(jack.name + " is shopping!");
//或者
//System.out.println(rose.name + " is shopping!");
//對(duì)不起,jack和rose在main方法當(dāng)中,在這里不可見,不能用
//難道是這樣???
System.out.println(this.name + " is shopping!");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer jack = new Customer("jack");
jack.shopping();
Customer rose = new Customer("rose");
rose.shopping();
}
}
把完整的代碼拿過來:
public class Customer {
private String name;
public Customer(){
}
public Customer(String _name){
name = _name;
}
public void setName(String _name){
name = _name;
}
public String getName(){
return name;
}
public void shopping(){
System.out.println(name + " is shopping!");
System.out.println(this.name + " is shopping!");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer jack = new Customer("jack");
jack.shopping();
System.out.println("=======================");
Customer rose = new Customer("rose");
rose.shopping();
}
}
運(yùn)行結(jié)果如下圖所示:
通過以上的測(cè)試我們得知:System.out.println(name + " is shopping!")和System.out.println(this.name + " is shopping!")是等效的。也就是說在shopping()這個(gè)“實(shí)例方法”當(dāng)中直接訪問“實(shí)例變量”name就表示訪問當(dāng)前對(duì)象的name。換句話說在實(shí)例方法中可以直接訪問當(dāng)前對(duì)象的實(shí)例變量,而“this.”是可以省略的。“this.”什么時(shí)候不能省略呢?請(qǐng)看以下代碼:
public class Customer {
private String name;
public Customer(){
}
public Customer(String _name){
name = _name;
}
public void setName(String _name){
name = _name;
}
public String getName(){
return name;
}
public void shopping(){
System.out.println(name + " is shopping!");
}
}
你有沒有看到name=_name這樣的代碼很丑陋,怎樣可以優(yōu)雅一些呢?請(qǐng)看:
public class Customer {
private String name;
public Customer(){
}
public Customer(String name){
this.name = name;//這里的“this.”不能省略
}
public void setName(String name){
this.name = name;//這里的“this.”不能省略
}
public String getName(){
return name; //這里的“this.”可以省略
}
public void shopping(){
//這里的“this.”可以省略
System.out.println(name + " is shopping!");
}
}
以上代碼當(dāng)中this.name = name,其中this.name表示實(shí)例變量name,等號(hào)右邊的name是局部變量name,此時(shí)如果省略“this.”,則變成name = name,這兩個(gè)name都是局部變量(java遵守就近原則),和實(shí)例變量name無關(guān)了,顯然是不可以省略“this.”的。
最終的結(jié)論是,this不能出現(xiàn)在static的方法中,可以出現(xiàn)在實(shí)例方法中,代表當(dāng)前對(duì)象,大部分情況下this都是可以省略的,只有當(dāng)在實(shí)例方法中區(qū)分局部變量和實(shí)例變量的時(shí)候不能省略。
接下來我們?cè)賮頂U(kuò)展一下this的使用,請(qǐng)看代碼:
public class Customer {
private String name;
public Customer(){
}
public Customer(String name){
this.name = name;
}
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
//實(shí)例方法
public void shopping(){
System.out.println(name + " is shopping!");
System.out.println(name + " 選好商品了!");
//pay()支付方法是實(shí)例方法,實(shí)例方法需要使用“引用”調(diào)用
//那么這個(gè)“引用”是誰呢?
//當(dāng)前對(duì)象在購物,肯定是當(dāng)前對(duì)象在支付,所以引用是this
this.pay();
//同樣“this.”可以省略
pay();
}
//實(shí)例方法
public void pay(){
System.out.println(name + "支付成功!");
}
}
public class CustomerTest {
public static void main(String[] args) {
Customer jack = new Customer("jack");
jack.shopping();
System.out.println("=======================");
Customer rose = new Customer("rose");
rose.shopping();
}
}
運(yùn)行結(jié)果如下圖所示:
圖11-7:測(cè)試結(jié)果
通過以上的測(cè)試,可以看出在一個(gè)實(shí)例方法當(dāng)中可以直接去訪問其它的實(shí)例方法,方法是對(duì)象的一種行為描述,實(shí)例方法中直接調(diào)用其它的實(shí)例方法,就表示“當(dāng)前對(duì)象”完成了一系列行為動(dòng)作。例如在實(shí)例方法shopping()中調(diào)用另一個(gè)實(shí)例方法pay(),這個(gè)過程就表示jack在選購商品,選好商品之后,完成支付環(huán)節(jié),其中選購商品是一個(gè)動(dòng)作,完成支付是另一個(gè)動(dòng)作。接下來繼續(xù)擴(kuò)展,請(qǐng)看以下代碼:
public class ThisTest {
int i = 10;
public static void main(String[] args) {
System.out.println(i);
}
}
以上代碼編譯報(bào)錯(cuò)了,請(qǐng)看:
圖11-8:編譯錯(cuò)誤提示信息
為什么會(huì)編譯報(bào)錯(cuò),在main方法中為什么無法直接訪問變量i?我們來分析一下,首先i變量是實(shí)例變量,實(shí)例變量要想訪問必須先創(chuàng)建對(duì)象,然后通過“引用”去訪問,main方法是static的方法,也就是說main方法是通過“類名”去調(diào)用的,在main方法中沒有“當(dāng)前對(duì)象”的概念,也就是說main方法中不能使用this,所以編譯報(bào)錯(cuò)了。那應(yīng)該怎么修改呢?請(qǐng)看:
public class ThisTest {
int i = 10;
public static void main(String[] args) {
//這肯定是不行的,因?yàn)閙ain方法帶有static,不能用this
//System.out.println(this.i);
//可以自己創(chuàng)建一個(gè)對(duì)象
ThisTest tt = new ThisTest();
//通過引用訪問
System.out.println(tt.i);
}
}
運(yùn)行結(jié)果如下圖所示:
圖11-9:測(cè)試結(jié)果
通過以上的測(cè)試得知,在static的方法中不能直接訪問實(shí)例變量,要訪問實(shí)例變量必須先自己創(chuàng)建一個(gè)對(duì)象,通過“引用”可以去訪問,不能通過this訪問,因?yàn)樵趕tatic方法中是不能存在this的。其實(shí)這種設(shè)計(jì)也是有道理的,因?yàn)閟tatic的方法在執(zhí)行的時(shí)候是采用“類名”去調(diào)用,沒有對(duì)象的參與,自然也不會(huì)存在當(dāng)前對(duì)象,所以static的方法執(zhí)行過程中不存在this。那么在static方法中能夠直接訪問實(shí)例方法嗎?請(qǐng)看以下代碼:
public class ThisTest {
public static void main(String[] args) {
doSome();
}
public void doSome(){
System.out.println("do some...");
}
}
編譯報(bào)錯(cuò)了,請(qǐng)看下圖:
圖11-10:編譯報(bào)錯(cuò)提示信息
為什么在main方法中無法直接調(diào)用實(shí)例方法doSome()呢?很簡(jiǎn)單,因?yàn)閷?shí)例方法必須先創(chuàng)建對(duì)象,通過引用去調(diào)用,在以上的main方法中并沒有創(chuàng)建對(duì)象,更沒有this。所以在main方法中無法直接訪問實(shí)例方法。結(jié)論就是:在static的方法中不能直接訪問實(shí)例方法。怎么修改呢?同樣需要先創(chuàng)建對(duì)象,請(qǐng)看:
public class ThisTest {
public static void main(String[] args) {
ThisTest tt = new ThisTest();
tt.doSome();
}
public void doSome(){
System.out.println("do some...");
}
}
運(yùn)行結(jié)果如下圖所示:
圖11-11:運(yùn)行結(jié)果
綜上所述,我們需要記住這樣的一個(gè)結(jié)論:this不能使用在static的方法中,可以使用在實(shí)例方法中,代表當(dāng)前對(duì)象,多數(shù)情況下this是可以省略不寫的,但是在區(qū)分局部變量和實(shí)例變量的時(shí)候不能省略,在實(shí)例方法中可以直接訪問當(dāng)前對(duì)象實(shí)例變量以及實(shí)例方法,在static方法中無法直接訪問實(shí)例變量和實(shí)例方法。