如果有两个同类型的对象分别叫作a和b那么您也许不知道如何为这两个对象同时调用一个f()方法 class Banana { void f(int i) { /* */ } } Banana a = new Banana() b = new Banana(); af(); bf(); 若只有一个名叫f()的方法它怎样才能知道自己是为a还是为b调用的呢? 为了能用简便的面向对象的语法来书写代码——亦即将消息发给对象编译器为我们完成了一些幕后工作其中的秘密就是第一个自变量传递给方法f()而且那个自变量是准备操作的那个对象的句柄所以前述的两个方法调用就变成了下面这样的形式 Bananaf(a); Bananaf(b); 这是内部的表达形式我们并不能这样书写表达式并试图让编译器接受它但是通过它可理解幕后到底发生了什么事情 假定我们在一个方法的内部并希望获得当前对象的句柄由于那个句柄是由编译器秘密传递的所以没有标识符可用然而针对这一目的有个专用的关键字thisthis关键字(注意只能在方法内部使用)可为已调用了其方法的那个对象生成相应的句柄可象对待其他任何对象句柄一样对待这个句柄但要注意假若准备从自己某个类的另一个方法内部调用一个类方法就不必使用this只需简单地调用那个方法即可当前的this句柄会自动应用于其他方法所以我们能使用下面这样的代码 class Apricot { void pick() { /* */ } void pit() { pick(); /* */ } } 在pit()内部我们可以说thispick()但事实上无此必要编译器能帮我们自动完成this关键字只能用于那些特殊的类——需明确使用当前对象的句柄例如假若您希望将句柄返回给当前对象那么它经常在return语句中使用 由于increment()通过this关键字返回当前对象的句柄所以可以方便地对同一个对象执行多项操作 在构建器里调用构建器 若为一个类写了多个构建器那么经常都需要在一个构建器里调用另一个构建器以避免写重复的代码可用this关键字做到这一点 通常当我们说this的时候都是指这个对象或者当前对象而且它本身会产生当前对象的一个句柄在一个构建器中若为其赋予一个自变量列表那么this关键字会具有不同的含义它会对与那个自变量列表相符的构建器进行明确的调用这样一来我们就可通过一条直接的途径来调用其他构建器如下所示 其中构建器Flower(String sint petals)向我们揭示出这样一个问题尽管可用this调用一个构建器但不可调用两个除此以外构建器调用必须是我们做的第一件事情否则会收到编译程序的报错信息 这个例子也向大家展示了this的另一项用途由于自变量s的名字以及成员数据s的名字是相同的所以会出现混淆为解决这个问题可用thiss来引用成员数据经常都会在Java代码里看到这种形式的应用本书的大量地方也采用了这种做法 在print()中我们发现编译器不让我们从除了一个构建器之外的其他任何方法内部调用一个构建器 static的含义 理解了this关键字后我们可更完整地理解static(静态)方法的含义它意味着一个特定的方法没有this我们不可从一个static方法内部发出对非static方法的调用(注释②)尽管反过来说是可以的而且在没有任何对象的前提下我们可针对类本身发出对一个static方法的调用事实上那正是static方法最基本的意义它就好象我们创建一个全局函数的等价物(在C语言中)除了全局函数不允许在Java中使用以外若将一个static方法置入一个类的内部它就可以访问其他static方法以及static字段 ②有可能发出这类调用的一种情况是我们将一个对象句柄传到static方法内部随后通过句柄(此时实际是this)我们可调用非static方法并访问非static字段但一般地如果真的想要这样做只要制作一个普通的非static方法即可 有些人抱怨static方法并不是面向对象的因为它们具有全局函数的某些特点利用static方法我们不必向对象发送一条消息因为不存在this这可能是一个清楚的自变量若您发现自己使用了大量静态方法就应重新思考自己的策略然而static的概念是非常实用的许多时候都需要用到它所以至于它们是否真的面向对象应该留给理论家去讨论事实上即使Smalltalk在自己的类方法里也有类似于static的东西 |