📄 tij0057.html
字号:
shown in Chapter 17)
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">that
used a different class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>P</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.
Because it was used as a tool, it was
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>sometimes</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
placed in the classpath, and other times it wasn’t. When it was, the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>P</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>CodePackager.java
</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">was
found first by Java when executing a program in which it was looking for the
class in
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>com.bruceeckel.tools</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
and the compiler would say that a particular method couldn’t be found.
This was frustrating because you can see the method in the above class
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>P</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
and no further diagnostics were reported to give you a clue that it was finding
a completely different class. (That wasn’t even
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>public.</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">)</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">At
first this could seem like a compiler bug, but if you look at the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>import</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement it says only “here’s where you
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>might</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
find
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>P</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">.”
However, the compiler is supposed to look anywhere in its classpath, so if it
finds a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>P</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
there it will use it, and if it finds the “wrong” one
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>first</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
during a search then it will stop looking. This is slightly different from the
case described on page
<A HREF=" PAGE#collisions_name">196</A>
because there the offending classes were both in packages, and here there was a
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>P</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that was not in a package, but could still be found during a normal classpath
search.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">If
you’re having an experience like this, check to make sure that
there’s only one class of each name anywhere in your <A NAME="Index376"></A>classpath.</FONT><a name="_Toc408018497"></a><a name="_Toc375545294"></a><P></DIV>
<A NAME="Heading168"></A><H3 ALIGN=LEFT>
Using
imports to change behavior
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">A
feature that is missing from Java is C’s
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>conditional
compilation
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
which allows you to change a switch and get different behavior without changing
any other code. The reason such a feature was left out of Java is probably
because it is most often used in C to solve cross-platform issues: different
portions of the code are compiled depending on the platform that the code is
being compiled for. Since Java is intended to be automatically cross-platform,
such a feature should not be necessary.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">However,
there are other valuable uses for conditional compilation. A very common use is
for debugging code. The debugging features are enabled during development, and
disabled for a shipping product. Allen Holub (www.holub.com) came up with the
idea of using packages to mimic conditional compilation. He used this to create
a Java version of C’s very useful
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>assertion
mechanism
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
whereby you can say “this should be true” or “this should be
false” and if the statement doesn’t agree with your assertion
you’ll find out about it. Such a tool is quite helpful during debugging.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Here
is the class that you’ll use for debugging:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Assert.java</font>
<font color="#009900">// Assertion tool for debugging</font>
<font color="#0000ff">package</font> com.bruceeckel.tools.debug;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Assert {
<font color="#0000ff">private</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> perr(String msg) {
System.err.println(msg);
}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> is_true(<font color="#0000ff">boolean</font> exp) {
<font color="#0000ff">if</font>(!exp) perr("Assertion failed");
}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> is_false(<font color="#0000ff">boolean</font> exp){
<font color="#0000ff">if</font>(exp) perr("Assertion failed");
}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font>
is_true(<font color="#0000ff">boolean</font> exp, String msg) {
<font color="#0000ff">if</font>(!exp) perr("Assertion failed: " + msg);
}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font>
is_false(<font color="#0000ff">boolean</font> exp, String msg) {
<font color="#0000ff">if</font>(exp) perr("Assertion failed: " + msg);
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">This
class simply encapsulates boolean tests, which print error messages if they
fail. In Chapter 9, you’ll learn about a more sophisticated tool for
dealing with errors called
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>exception
handling
</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">,
but the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>perr( )</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
method will work fine in the meantime.
</FONT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">When
you want to use this class, you add a line in your program:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">import
com.bruceeckel.tools.debug.*;
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">To
remove the assertions so you can ship the code, a second
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>Assert</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
class is created, but in a different package:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: Assert.java</font>
<font color="#009900">// Turning off the assertion output </font>
<font color="#009900">// so you can ship the program.</font>
<font color="#0000ff">package</font> com.bruceeckel.tools;
<font color="#0000ff">public</font> <font color="#0000ff">class</font> Assert {
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> is_true(<font color="#0000ff">boolean</font> exp){}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> is_false(<font color="#0000ff">boolean</font> exp){}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font>
is_true(<font color="#0000ff">boolean</font> exp, String msg) {}
<font color="#0000ff">public</font> <font color="#0000ff">final</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font>
is_false(<font color="#0000ff">boolean</font> exp, String msg) {}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">Now
if you change the previous
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>import</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement to:
</FONT><P></DIV><DIV ALIGN=LEFT><TT><FONT FACE="Courier New" SIZE=3 COLOR="Black">import
com.bruceeckel.tools.*;
</FONT></TT><P></DIV><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">The
program will no longer print out assertions. Here’s an example:
</FONT><P></DIV>
<font color="#990000"><PRE><font color="#009900">//: TestAssert.java</font>
<font color="#009900">// Demonstrating the assertion tool</font>
<font color="#0000ff">package</font> c05;
<font color="#009900">// Comment the following, and uncomment the</font>
<font color="#009900">// subsequent line to change assertion behavior:</font>
<font color="#0000ff">import</font> com.bruceeckel.tools.debug.*;
<font color="#009900">// import com.bruceeckel.tools.*;</font>
<font color="#0000ff">public</font> <font color="#0000ff">class</font> TestAssert {
<font color="#0000ff">public</font> <font color="#0000ff">static</font> <font color="#0000ff">void</font> main(String[] args) {
Assert.is_true((2 + 2) == 5);
Assert.is_false((1 + 1) == 2);
Assert.is_true((2 + 2) == 5, "2 + 2 == 5");
Assert.is_false((1 + 1) == 2, "1 +1 != 2");
}
} <font color="#009900">///:~ </PRE></font></font><DIV ALIGN=LEFT><P></DIV><DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">By
changing the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>package</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
that’s imported, you change your code from the debug version to the
production version. This technique can be used for any kind of conditional code.
</FONT><a name="_Toc408018498"></a><P></DIV>
<A NAME="Heading169"></A><H3 ALIGN=LEFT>
Package
caveat
</H3>
<DIV ALIGN=LEFT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">It’s
worth remembering that anytime you create a package, you implicitly specify a <A NAME="Index377"></A><A NAME="Index378"></A>directory
structure when you give the package a name. The package
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><I>must</I></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
live in the directory indicated by its name, which must be a directory that is
searchable starting from the CLASSPATH. Experimenting with the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>package</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
keyword can be a bit frustrating at first, because unless you adhere to the
package-name to directory-path rule, you’ll get a lot of mysterious
run-time messages about not being able to find a particular class, even if that
class is sitting there in the same directory. If you get a message like this,
try commenting out the
</FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black"><B>package</B></FONT><FONT FACE="Carmina Md BT" SIZE=3 COLOR="Black">
statement, and if it runs you’ll know where the problem lies.
</FONT><a name="_Toc375545295"></a><a name="_Toc408018499"></a><P></DIV>
<HR><DIV ALIGN=LEFT><A NAME="fn23" HREF="#fnB23">[23]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
There’s nothing in Java that forces the use of an interpreter. There
exist native-code Java compilers that generate a single executable file.
</FONT><P></DIV><DIV ALIGN=LEFT><A NAME="fn24" HREF="#fnB24">[24]</A><FONT FACE="Carmina Md BT" SIZE=2 COLOR="Black">
ftp://ftp.internic.net
</FONT><P></DIV>
<div align="right">
<a href="tij_c.html">Contents</a> | <a href="tij0056.html">Prev</a> | <a href="tij0058.html">Next</a>
</div>
</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -