📄 tij0052.html
字号:
<html><body>
<table width="100%"><tr>
<td>
<a href="http://www.bruceeckel.com/javabook.html">Bruce Eckel's Thinking in Java</a>
</td>
<td align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0051.html">Prev</a> | <a href="tij0053.html">Next</a>
</td>
</tr></table>
<hr>
<H2 ALIGN=LEFT>
Member
initialization
</H2>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Java
goes out of its way to guarantee that any variable is properly initialized
before it is used. In the case of variables that are defined locally to a
method, this guarantee comes in the form of a compile-time error. So if you say:
</FONT><P></DIV>
<font color="#990000"><PRE> <font color="#0000ff">void</font> f() {
<font color="#0000ff">int</font> i;
i++;
} </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You’ll
get an error message that says that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
might not have been initialized. Of course, the compiler could have given
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
a default value, but it’s more likely that this is a programmer error and
a default value would have covered that up. Forcing the programmer to provide
an initialization value is more likely to catch a bug<A NAME="Index306"></A><A NAME="Index307"></A><A NAME="Index308"></A>.</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
a <A NAME="Index309"></A><A NAME="Index310"></A><A NAME="Index311"></A>primitive
is a data member of a class, however, things are a bit different. Since any
method can initialize or use that data, it might not be practical to force the
user to initialize it to its appropriate value before the data is used.
However, it’s unsafe to leave it with a garbage value, so each primitive
data member of a class is guaranteed to get an initial value. Those values can
be seen here:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: InitialValues.java</font>
<font color="#009900">// Shows default initial values</font>
<font color="#0000ff">class</font> Measurement {
<font color="#0000ff">boolean</font> t;
<font color="#0000ff">char</font> c;
<font color="#0000ff">byte</font> b;
<font color="#0000ff">short</font> s;
<font color="#0000ff">int</font> i;
<font color="#0000ff">long</font> l;
<font color="#0000ff">float</font> f;
<font color="#0000ff">double</font> d;
<font color="#0000ff">void</font> print() {
System.out.println(
"Data type Inital value\n" +
"<font color="#0000ff">boolean</font> " + t + "\n" +
"<font color="#0000ff">char</font> " + c + "\n" +
"<font color="#0000ff">byte</font> " + b + "\n" +
"<font color="#0000ff">short</font> " + s + "\n" +
"<font color="#0000ff">int</font> " + i + "\n" +
"<font color="#0000ff">long</font> " + l + "\n" +
"<font color="#0000ff">float</font> " + f + "\n" +
"<font color="#0000ff">double</font> " + d);
}
}
<font color="#0000ff">public</font> <font color="#0000ff">class</font> InitialValues {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Measurement d = <font color="#0000ff">new</font> Measurement();
d.print();
<font color="#009900">/* In this case you could also say:
new Measurement().print();
*/</font>
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
output of this program is:
</FONT><P></DIV>
<font color="#990000"><PRE>Data type Inital value
<font color="#0000ff">boolean</font> <font color="#0000ff">false</font>
<font color="#0000ff">char</font>
<font color="#0000ff">byte</font> 0
<font color="#0000ff">short</font> 0
<font color="#0000ff">int</font> 0
<font color="#0000ff">long</font> 0
<font color="#0000ff">float</font> 0.0
<font color="#0000ff">double</font> 0.0 </PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>char</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
value is a null, which doesn’t print.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You’ll
see later that when you define an object handle inside a class without
initializing it to a new object, that handle is given a value of null.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can see that even though the values are not specified, they automatically get
initialized. So at least there’s no threat of working with uninitialized
variables.
</FONT><a name="_Toc375545285"></a><a name="_Toc408018487"></a><P></DIV>
<A NAME="Heading151"></A><H3 ALIGN=LEFT>
Specifying
initialization
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">What
happens if you want to give a variable an initial value? One direct way to do
this is simply to assign the value at the point you define the variable in the
class. (Notice you cannot do this in C++, although C++ novices always try.)
Here the field definitions in class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Measurement</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
are changed to provide initial values: <A NAME="Index312"></A><A NAME="Index313"></A></FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> Measurement {
<font color="#0000ff">boolean</font> b = <font color="#0000ff">true</font>;
<font color="#0000ff">char</font> c = 'x';
<font color="#0000ff">byte</font> B = 47;
<font color="#0000ff">short</font> s = 0xff;
<font color="#0000ff">int</font> i = 999;
<font color="#0000ff">long</font> l = 1;
<font color="#0000ff">float</font> f = 3.14f;
<font color="#0000ff">double</font> d = 3.14159; </TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black"> <font color="#009900">//. . . </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can also initialize non-primitive objects in this same way. If
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Depth</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
is a class, you can insert a variable and initialize it like so:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> Measurement {
Depth o = <font color="#0000ff">new</font> Depth();
<font color="#0000ff">boolean</font> b = <font color="#0000ff">true</font>; </TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black"> <font color="#009900">// . . . </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you haven’t given
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>o</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
an initial value and you go ahead and try to use it anyway, you’ll get a
run-time error called an
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>exception</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
(covered in Chapter 9).
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">You
can even call a method to provide an initialization value:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> CInit {
<font color="#0000ff">int</font> i = f();
<font color="#009900">//...</font>
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
method can have arguments, of course, but those arguments cannot be other class
members that haven’t been initialized yet. Thus, you can do this:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> CInit {
<font color="#0000ff">int</font> i = f();
<font color="#0000ff">int</font> j = g(i);
<font color="#009900">//...</font>
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">But
you cannot do this:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#0000ff">class</font> CInit {
<font color="#0000ff">int</font> j = g(i);
<font color="#0000ff">int</font> i = f();
<font color="#009900">//...</font>
}</PRE></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
is one place in which the compiler, appropriately,
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>does</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
complain about <A NAME="Index314"></A><A NAME="Index315"></A>forward
referencing, since this has to do with the order of initialization and not the
way the program is compiled.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
approach to initialization is simple and straightforward. It has the limitation
that
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>every</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
object of type
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Measurement</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
will get these same initialization values. Sometimes this is exactly what you
need, but at other times you need more flexibility.
</FONT><a name="_Toc375545286"></a><a name="_Toc408018488"></a><P></DIV>
<A NAME="Heading152"></A><H3 ALIGN=LEFT>
Constructor
initialization
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
constructor can be used to perform initialization, and this gives you greater
flexibility in your programming since you can call methods and perform actions
at run time to determine the initial values. There’s one thing to keep in
mind, however: you aren’t precluding the automatic initialization, which
happens before the constructor is entered. So, for example, if you say:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">class
Counter {
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
int i;
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
Counter() { i = 7; }
</FONT></TT><P><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">
// . . .
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">then
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>i
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">will
first be initialized to zero, then to 7. This is true with all the primitive
types and with object handles, including those that are given explicit
initialization at the point of definition. For this reason, the compiler
doesn’t try to force you to initialize elements in the constructor at any
particular place, or before they are used – initialization is already
guaranteed.
</FONT><A NAME="fnB21" HREF="#fn21">[21]</A><P></DIV>
<A NAME="Heading153"></A><H4 ALIGN=LEFT>
Order
of initialization
<P><A NAME="Index316"></A><A NAME="Index317"></A><A NAME="Index318"></A></H4>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Within
a class, the order of initialization is determined by the order that the
variables are defined within the class. Even if the variable definitions are
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -