📄 tij0050.html
字号:
“send a message to an object,” the compiler does some undercover
work for you. There’s a secret first argument passed to the method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>f( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and that argument is the handle to the object that’s being manipulated.
So the two method calls above become something like:
</FONT><P></DIV>
<font color="#990000"><PRE>Banana.f(a,1);
Banana.f(b,2);</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
is internal and you can’t write these expressions and get the compiler to
accept them, but it gives you an idea of what’s happening.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Suppose
you’re inside a method and you’d like to get the handle to the
current object. Since that handle is passed
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>secretly</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
by the compiler, there’s no identifier for it. However, for this purpose
there’s a keyword:
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword – which can be used only inside a method – produces the
handle to the object the method has been called for. You can treat this handle
just like any other object handle. Keep in mind that if you’re calling a
method of your class from within another method of your class, you don’t
need to use
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this;</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you simply call the method. The current
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
handle is automatically used for the other method. Thus you can say:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> Apricot {
<font color="#0000ff">void</font> pick() { <font color="#009900">/* ... */</font> }
<font color="#0000ff">void</font> pit() { pick(); <font color="#009900">/* ... */</font> }
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>pit( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>could</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this.pick( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
but there’s no need to. The compiler does it for you automatically. The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword is used only for those special cases in which you need to explicitly
use the handle to the current object. For example, it’s often used in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>return</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statements when you want to return the handle to the current object:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Leaf.java</font>
<font color="#009900">// Simple use of the "this" keyword</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Leaf {
<font color="#0000ff">private</font> <font color="#0000ff">int</font> i = 0;
Leaf increment() {
i++;
<font color="#0000ff">return</font> <font color="#0000ff">this</font>;
}
<font color="#0000ff">void</font> print() {
System.out.println("i = " + i);
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Leaf x = <font color="#0000ff">new</font> Leaf();
x.increment().increment().increment().print();
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Because
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>increment( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
returns the handle to the current object via the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword, multiple operations can easily be performed on the same object.
</FONT><P></DIV>
<A NAME="Heading145"></A><H4 ALIGN=LEFT>
Calling
constructors from constructors
<P><A NAME="Index289"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you write several constructors for a class, there are times when you’d
like to call one constructor from another to avoid duplicating code. You can do
this using the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Normally,
when you say
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
it is in the sense of “this object” or “the current
object,” and by itself it produces the handle to the current object. In a
constructor, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword takes on a different meaning when you give it an argument list: it
makes an explicit call to the constructor that matches that argument list. Thus
you have a straightforward way to call other constructors:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Flower.java</font>
<font color="#009900">// Calling constructors with "this"</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Flower {
<font color="#0000ff">private</font> <font color="#0000ff">int</font> petalCount = 0;
<font color="#0000ff">private</font> String s = <font color="#0000ff">new</font> String("<font color="#0000ff">null</font>");
Flower(<font color="#0000ff">int</font> petals) {
petalCount = petals;
System.out.println(
"Constructor w/ <font color="#0000ff">int</font> arg only, petalCount= "
+ petalCount);
}
Flower(String ss) {
System.out.println(
"Constructor w/ String arg only, s=" + ss);
s = ss;
}
Flower(String s, <font color="#0000ff">int</font> petals) {
<font color="#0000ff">this</font>(petals);
<font color="#009900">//! this(s); // Can't call two!</font>
<font color="#0000ff">this</font>.s = s; <font color="#009900">// Another use of "this"</font>
System.out.println("String & <font color="#0000ff">int</font> args");
}
Flower() {
<font color="#0000ff">this</font>("hi", 47);
System.out.println(
"<font color="#0000ff">default</font> constructor (no args)");
}
<font color="#0000ff">void</font> print() {
<font color="#009900">//! this(11); // Not inside non-constructor!</font>
System.out.println(
"petalCount = " + petalCount + " s = "+ s);
}
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Flower x = <font color="#0000ff">new</font> Flower();
x.print();
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
constructor
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Flower(String
s, int petals)
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
shows that, while you can call one constructor using
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
you cannot call two. In addition, the constructor call must be the first thing
you do or you’ll get a compiler error message.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
example also shows another way you’ll see
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
used. Since the name of the argument
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">and
the name of the member data
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are the same, there’s an ambiguity. You can resolve it by saying
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this.s</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
to refer to the member data. You’ll often see this form used in Java
code, and it’s used in numerous places in this book.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">In
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>print( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
you can see that the compiler won’t let you call a constructor from
inside any method other than a constructor.
</FONT><P></DIV>
<A NAME="Heading146"></A><H4 ALIGN=LEFT>
The
meaning of static
<P><A NAME="Index290"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">With
the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">keyword
in mind, you can more fully understand what it means to make a <A NAME="Index291"></A><A NAME="Index292"></A>method
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
It means that there is no
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
for that particular method. You cannot call non-
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods from inside
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods
</FONT><A NAME="fnB18" HREF="#fn18">[18]</A><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(although the reverse is possible), and you can call a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method for the class itself, without any object. In fact, that’s
primarily what a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method is for. It’s as if you’re creating the equivalent of a
global function (from C). Except global functions are not permitted in Java,
and putting the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method inside a class allows it access to other
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">methods
and to
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
fields.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Some
people argue that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
methods are not object-oriented since they do have the semantics of a global
function; with a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method you don’t send a message to an object, since there’s no
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
This is probably a fair argument, and if you find yourself using a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>lot</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
of static methods you should probably rethink your strategy. However,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">s
are pragmatic and there are times when you genuinely need them, so whether or
not they are “proper OOP” should be left to the theoreticians.
Indeed, even <A NAME="Index293"></A>Smalltalk
has the equivalent in its “class methods.”
</FONT><a name="_Toc375545281"></a><a name="_Toc408018483"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn17" HREF="#fnB17">[17]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
In some of the Java literature from Sun they instead refer to these with the
clumsy but descriptive name “no-arg constructors.” The term
“default constructor” has been in use for many years and so I will
use that.
</FONT><P></DIV><DIV ALIGN=LEFT><A NAME="fn18" HREF="#fnB18">[18]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
The one case in which this is possible occurs if you pass a handle to an object
into the
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
method. Then, via the handle (which is now effectively
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>this</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">),
you can call non-
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
methods and access non-
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
fields. But typically if you want to do something like this you’ll just
make an ordinary, non-
</FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black"><B>static</B></FONT><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
method.
</FONT><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0049.html">Prev</a> | <a href="tij0051.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -