java的this要害字
假如有两个同范例的工具,别离叫作a和b,那么您也许不知道如作甚这两个工具同时挪用一个f()要领:
class Banana { void f(int i) { /* … */ } }
Banana a = new Banana(), b = new Banana();
a.f(1);
b.f(2);
若只有一个名叫f()的要领,它奈何才气知道本身是为a照旧为b挪用的呢?
为了能用轻便的、面向工具的语法来书写代码——亦即“将动静发给工具”,编译器为我们完成了一些幕后事情。个中的奥秘就是第一个自变量通报给要领f(),并且谁人自变量是筹备操纵的谁人工具的句柄。所以前述的两个要领挪用就酿成了下面这样的形式:
Banana.f(a,1);
Banana.f(b,2);
这是内部的表达形式,我们并不能这样书写表达式,并试图让编译器接管它。可是,通过它可领略幕后到底产生了什么工作。
假定我们在一个要领的内部,并但愿获恰当前工具的句柄。由于谁人句柄是由编译器“奥秘”通报的,所以没有标识符可用。然而,针对这一目标有个专用的要害字:this。this要害字(留意只能在要领内部利用)可为已挪用了其要领的谁人工具生成相应的句柄。可象看待其他任何工具句柄一样看待这个句柄。但要留意,假使筹备从本身某个类的另一个要领内部挪用一个类要领,就不必利用this。只需简朴地挪用谁人要领即可。当前的this句柄会自动应用于其他要领。所以我们能利用下面这样的代码:
class Apricot {
void pick() { /* … */ }
void pit() { pick(); /* … */ }
}
在pit()内部,我们可以说this.pick(),但事实上无此须要。编译器能帮我们自动完成。this要害字只能用于那些非凡的类——需明晰利用当前工具的句柄。譬喻,假使您但愿将句柄返回给当前工具,那么它常常在return语句中利用。
//: Leaf.java // Simple use of the "this" keyword public class Leaf { private int i = 0; Leaf increment() { i++; return this; } void print() { System.out.println("i = " + i); } public static void main(String[] args) { Leaf x = new Leaf(); x.increment().increment().increment().print(); } } ///:~
由于increment()通过this要害字返回当前工具的句柄,所以可以利便地对同一个工具执行多项操纵。
1. 在构建器里挪用构建器
若为一个类写了多个构建器,那么常常都需要在一个构建器里挪用另一个构建器,以制止写反复的代码。可用this要害字做到这一点。
凡是,当我们说this的时候,都是指“这个工具”可能“当前工具”。并且它自己会发生当前工具的一个句柄。在一个构建器中,若为其赋予一个自变量列表,那么this要害字会具有差异的寄义:它会对与谁人自变量列表相符的构建器举办明晰的挪用。这样一来,我们就可通过一条直接的途径来挪用其他构建器。如下所示:
//: Flower.java // Calling constructors with "this" public class Flower { private int petalCount = 0; private String s = new String("null"); Flower(int petals) { petalCount = petals; System.out.println( "Constructor w/ int arg only, petalCount= " + petalCount); } Flower(String ss) { System.out.println( "Constructor w/ String arg only, s=" + ss); s = ss; } Flower(String s, int petals) { this(petals); //! this(s); // Can't call two! this.s = s; // Another use of "this" System.out.println("String & int args"); } Flower() { this("hi", 47); System.out.println( "default constructor (no args)"); } void print() { //! this(11); // Not inside non-constructor! System.out.println( "petalCount = " + petalCount + " s = "+ s); } public static void main(String[] args) { Flower x = new Flower(); x.print(); } } ///:~
个中,构建器Flower(String s,int petals)向我们展现出这样一个问题:尽量可用this挪用一个构建器,但不行挪用两个。除此以外,构建器挪用必需是我们做的第一件工作,不然会收到编译措施的报错信息。
这个例子也向各人展示了this的另一项用途。由于自变量s的名字以及成员数据s的名字是沟通的,所以会呈现夹杂。为办理这个问题,可用this.s来引用成员数据。常常城市在Java代码里看到这种形式的应用,本书的大量处所也回收了这种做法。
在print()中,我们发明编译器不让我们从除了一个构建器之外的其他任何要领内部挪用一个构建器。
2. static的寄义
领略了this要害字后,我们可更完整地领略static(静态)要领的寄义。它意味着一个特定的要领没有this。我们不行从一个static要领内部发出对非static要领的挪用(注释②),尽量反过来说是可以的。并且在没有任何工具的前提下,我们可针对类自己发出对一个static要领的挪用。事实上,那正是static要领最根基的意义。它就好象我们建设一个全局函数的等价物(在C语言中)。除了全局函数不答允在Java中利用以外,若将一个static要领置入一个类的内部,它就可以会见其他static要领以及static字段。
②:有大概发出这类挪用的一种环境是我们将一个工具句柄传到static要领内部。随后,通过句柄(此时实际是this),我们可挪用非static要领,并会见非static字段。但一般地,假如然的想要这样做,只要建造一个普通的、非static要领即可。
有些人诉苦static要领并不是“面向工具”的,因为它们具有全局函数的某些特点;操作static要领,我们不必向工具发送一条动静,因为不存在this。这大概是一个清楚的自变量,若您发明本身利用了大量静态要领,就应从头思考本身的计策。然而,static的观念长短常实用的,很多时候都需要用到它。所以至于它们是否真的“面向工具”,应该留给理论家去接头。事实上,纵然Smalltalk在本身的“类要领”里也有雷同于static的对象。