⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch14.htm

📁 21天学会用JAVA开发网络游戏
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<TT>int a = 37, b = 26;<BR>
int n = a % 3 + b / 7 ^ 8;</TT>
</BLOCKQUOTE>
<P>
If you are a whiz at remembering things and you can immediately
say without a shadow of a doubt what this expression is equal
to, then good for you. For the rest of us, this is a pretty risky
piece of code because it can yield a variety of different results
depending on the precedence of the operators. Actually, it only
yields one result, based on the correct order of operator precedence
set forth by the Java language. But it's easy for programmers
to mix up the precedence and write code that they think is doing
one thing when it is doing something else.
<P>
What's the solution? The solution is to use parentheses even when
you don't technically need them, just to be safe about the precedence.
The following is the same code with extra parentheses added to
make the precedence more clear:
<BLOCKQUOTE>
<TT>int a = 37, b = 26;<BR>
int n = ((a % 3) + (b / 7)) ^ 8;</TT>
</BLOCKQUOTE>
<H4><B>Hidden Member Variables</B></H4>
<P>
Another potentially tricky bug that is common in object-oriented
game programming is the hidden member variable. A hidden member
variable is a variable that has become &quot;hidden&quot; due
to a derived class implementing a new variable of the same name.
Take a look at Listing 14.1, which contains two classes: <TT>Weapon</TT>
and <TT>Bazooka</TT>.
<HR>
<BLOCKQUOTE>
<B>Listing 14.1. The </B><TT><B><FONT FACE="Courier">Weapon</FONT></B></TT><B>
and </B><TT><B><FONT FACE="Courier">Bazooka</FONT></B></TT><B>
classes.<BR>
</B>
</BLOCKQUOTE>
<BLOCKQUOTE>
<TT>class Weapon {<BR>
&nbsp;&nbsp;int power;<BR>
&nbsp;&nbsp;int numShots;<BR>
<BR>
&nbsp;&nbsp;public Weapon() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;power = 5;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;numShots = 10;<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public void fire() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;numShots--;<BR>
&nbsp;&nbsp;}<BR>
}<BR>
<BR>
class Bazooka : extends Weapon {<BR>
&nbsp;&nbsp;int numShots;<BR>
<BR>
&nbsp;&nbsp;public Bazooka() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;super();<BR>
&nbsp;&nbsp;}<BR>
<BR>
&nbsp;&nbsp;public blastEm() {<BR>
&nbsp;&nbsp;&nbsp;&nbsp;power--;<BR>
&nbsp;&nbsp;&nbsp;&nbsp;numShots -= 2;<BR>
&nbsp;&nbsp;}<BR>
}</TT>
</BLOCKQUOTE>
<HR>
<P>
The <TT>Weapon</TT> class defines
two member variables: <TT>power</TT>
and <TT>numShots</TT>. The <TT>Bazooka</TT>
class is derived from <TT>Weapon</TT>
and also implements a <TT>numShots</TT>
member variable, which effectively hides the original <TT>numShots</TT>
inherited from <TT>Weapon</TT>. The
problem with this code is that when the <TT>Weapon</TT>
constructor is called by <TT>Bazooka</TT>
(via the call to <TT>super</TT>),
the hidden <TT>numShots</TT> variable
defined in <TT>Weapon</TT> is initialized,
not the one in <TT>Bazooka</TT>. Later,
when the <TT>blastEm</TT> method is
called in <TT>Bazooka</TT>, the visible
(derived) <TT>numShots</TT> variable
is used, which has been initialized by default to zero. As you
can probably imagine, more complex classes with this problem can
end up causing some seriously tricky and hard to trace bugs.
<P>
The solution to the problem is to simply make sure that you never
hide variables. That doesn't mean that there aren't a few isolated
circumstances in which you might want to use variable hiding on
purpose; just keep in mind the risks involved in doing so.
<a name="BugDetection"><H3><B>Bug Detection</B></H3>
<P>
Even if you rigorously employ bug avoidance techniques, you will
still have to contend with a certain number of bugs. It's just
a fact of life that programmers make mistakes, and the sheer complexity
of large programming projects often causes problems that elude
us. That's all right. Just embrace the notion that you're imperfect
and focus your attention on tracking down the mistakes. The point
is that in addition to applying bug prevention techniques as much
as possible, you must learn how to track down the inevitable bugs
that will surface when you start testing your game. Let's look
at a few techniques for hunting down bugs.
<H4><B>Standard Output</B></H4>
<P>
The age-old technique for tracking down bugs is to print information
to standard output. This approach probably sounds pretty archaic-and
in many ways it is-but if you want a quick and dirty look into
what's going on in your game, it's often your best bet. This technique
is especially useful now, because visual Java debuggers are still
rough around the edges.
<P>
Employing the standard output technique is as simple as inserting
calls to <TT>System.out.println</TT>
at appropriate locations in your code. You can use standard output
for anything from looking at the value of variables to determining
whether a method is being called; just sprinkle those <TT>println</TT>
calls wherever you need them! The primary caveat to this approach
is that you should attempt to place the <TT>println</TT>
call in an update loop, like the loop controlling the animation
in games. In this case, the <TT>println</TT>
call might slow the game to a crawl simply because of the overhead
involved in printing text to the standard output device.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Speaking of standard output devices, you might be wondering exactly where standard output goes when you are running an applet inside a Web browser such as Netscape Navigator. The truth is that nobody knows! (Just kidding!) Netscape Navigator provides a 
console window where you can see everything that is being sent to standard output. To display this window, just look under the Options menu in Navigator and select Show Java Console.</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<H4><B>Call Stack Trace</B></H4>
<P>
An indispensable tool in tracking down hard to find bugs is the
method call stack. The method <I>call stack</I> is a list of the
methods called to arrive at the currently executing code. By examining
the call stack, you can see exactly which methods were called
to get to the current piece of code in question. This information
often sheds light on a problem regarding a method being called
inadvertently.
<P>
You can view the call stack by calling the <TT>printStackTrace</TT>
method, which is a member of the <TT>Throwable</TT>
class. Because <TT>printStackTrace</TT>
is a method in <TT>Throwable</TT>,
you must have a <TT>Throwable</TT>
object to look at the call stack. It just so happens that all
exceptions are derived from <TT>Throwable</TT>,
so any time you have an exception, you can view the call stack.
Check out the following code:
<BLOCKQUOTE>
<TT>try {<BR>
&nbsp;&nbsp;int nums[] = new int[5];<BR>
&nbsp;&nbsp;for (int i = 0; i &lt; 10; i++)<BR>
&nbsp;&nbsp;&nbsp;&nbsp;nums[i] = 6670;<BR>
}<BR>
catch (ArrayIndexOutOfBoundsException e) {<BR>
&nbsp;&nbsp;System.out.println(&quot;**Exception** : &quot; +
e.getMessage());<BR>
&nbsp;&nbsp;e.printStackTrace();<BR>
}</TT>
</BLOCKQUOTE>
<P>
In this code, the array <TT>nums</TT>
is indexed out of bounds in the <TT>for</TT>
loop, generating an <TT>ArrayIndexOutOfBoundsException</TT>.
The exception is logged to standard output in the <TT>catch</TT>
clause, along with a call to <TT>printStackTrace</TT>.
The resulting output follows:
<BLOCKQUOTE>
<TT>**Exception** : 5<BR>
java.lang.ArrayIndexOutOfBoundsException: 5<BR>
&nbsp;at TravelingGecko.init(TravelingGecko.java:32)<BR>
&nbsp;at sun.applet.AppletPanel.run(AppletPanel.java:259)<BR>
&nbsp;at java.lang.Thread.run(Thread.java:294)</TT>
</BLOCKQUOTE>
<P>
Incidentally, I placed this example code in the <TT>init</TT>
method in the Traveling Gecko game, which explains the call stack
results.
<H2><A NAME="ChoosingaDebugger"><B><FONT SIZE=5 COLOR=#FF0000>Choosing
a Debugger</FONT></B></A></H2>
<P>
An important decision regarding how you finally decide to debug
your game is that of choosing a debugger. A debugger is an invaluable
tool in ridding your game of bugs, and it can directly determine
how much time you spend debugging. Therefore, you should make
sure to invest your resources wisely and choose a debugger that
fits your development style. Unfortunately, the third-party Java
debugger market is still in its infancy, so don't expect to have
lots of debuggers to choose from at this point. Nevertheless,
try to keep tabs on the latest Java development tools and how
they might impact your debugging.
<P>
A few third-party integrated development environments that include
built-in visual debuggers are available for Java. These are very
nice and usually include lots of cool features beyond the ones
you just learned about; definitely look into getting a full-featured
debugger if at all possible. You learn much more about Java development
environments, including debuggers, on Day 21, &quot;Assembling
a Game Development Toolkit.&quot; For now, just keep in mind that
choosing a debugger that fits your needs is important in determining
how successfully you can rid your code of bugs. Fortunately, nearly
all debuggers perform the basic debugging functions of single-stepping,
supporting watch variables, and using breakpoints.
<P>
The Java Developer's Kit comes standard with a debugger (jdb)
that performs basic debugging functions such as those you learned
about earlier. It is a command-line debugger, which means that
it has no fancy graphics or point-and-click features but it does
get the job done. If you aren't ready to commit to a third-party
tool, by all means try out jdb. After you get comfortable with
jdb, you might find that it serves your purposes well enough.
<P>
Before you can use jdb, you need to compile your code so that
it includes debugging information. The Java compiler switch for
doing this is <TT>-g</TT>, which causes
the compiler to generate debugging tables containing information
about line numbers and variables.
<P>
<CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>
<TR><TD><B>Note</B></TD></TR>
<TR><TD>
<BLOCKQUOTE>
Some distributions of the JDK also include an alternate Java compiler called <TT>javac_g</TT>. If you have this compiler in your distribution (look in the java/bin directory), use it, because it compiles code without using some of the internal 
optimizations performed by the <TT>javac</TT> compiler.
</BLOCKQUOTE>

</TD></TR>
</TABLE></CENTER>
<P>
<P>
Using the jdb debugger is a topic best left to the introductory
books on Java. However, there is a nice online tutorial for using
jdb to debug Java code on Sun's Java Web site, which is located
at <TT><A HREF="http://www.javasoft.com">http://www.javasoft.com</A></TT>.
<H2><A NAME="Summary"><B><FONT SIZE=5 COLOR=#FF0000>Summary</FONT></B></A>
</H2>
<P>
Today you learned about crushing bugs in Java code. You not only
learned the importance of diagnosing and putting an end to bugs
in games, you learned some valuable tips on how to help prevent
bugs before they can even appear. You began the lesson with a
somewhat formal definition of a bug, followed by some debugging
basics. You then moved on to determining how to select a debugger,
and you finished up with a look at some common debugging strategies.
<P>
The debugging strategies you learned about today are in no way
comprehensive. The reality is that debugging is an art form involving
a lot of practice, intuition, and even heartache. You will no
doubt establish your own bag of debugging tricks far beyond those
I've suggested here. I encourage you to be as crafty as possible
when it comes to ferreting out pesky bugs!
<P>
If you think debugging puts a strain on your brain, try letting
the computer think for you. Hey, that just happens to be the topic
of your next lesson: artificial intelligence. But before you move
on to that, there's some celebrating to do. You're finished with
your second week of lessons!
<H2><A NAME="QA"><B><FONT SIZE=5 COLOR=#FF0000>Q&amp;A</FONT></B></A>
<BR>
</H2>

<TABLE>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>Where does the term &quot;bug&quot; come from?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>The term &quot;bug&quot; was coined by programming pioneer Grace Hopper back in the days when programming was performed using rudimentary hardware switches. As the story goes, a computer malfunctioned and 
someone noticed that a moth had gotten caught in one of the mechanical relays in the computer, keeping the relay from closing and making contact. From that time forward, programming errors were referred to as bugs.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>Using watch variables, is it possible to watch an entire object at once?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>Yes, most debuggers provide a means of watching an entire object at once, just like any other variable.
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>Q</B></TD><TD><B>How does Java's use of automatic garbage collection impact debugging?</B>
</TD></TR>
<TR VALIGN=TOP><TD WIDTH=50><B>A</B></TD><TD>The garbage collection mechanism employed by Java, coupled with the inability to use pointers, removes a wide range of bug creation opportunities. Aside from removing the problem of dealing with null pointers, 
Java also alleviates having to contend with memory leaks, which are very common in C and C++. <I>Memory leaks</I> are chunks of memory that are allocated but inadvertently never deleted, effectively resulting in memory loss.
</TD></TR>
</TABLE>
<P>
<H2><A NAME="Workshop"><B><FONT SIZE=5 COLOR=#FF0000>Workshop</FONT></B></A>
</H2>
<P>
The Workshop section provides questions and exercises to help
you get a better feel for the material you learned today. Try
to answer the questions and at least go over the exercises before
moving on to tomorrow's lesson. You'll find the answers to the
questions in appendix A, &quot;Quiz Answers.&quot;
<H3><A NAME="Quiz"><B>Quiz</B></A></H3>
<OL>
<LI>What is the significance of single-stepping?
<LI>What is an exception?
<LI>How does a variable become &quot;hidden&quot;?
<LI>What is a method call stack?
</OL>
<H3><A NAME="Exercises"><B>Exercises</B></A></H3>
<OL>
<LI>Learn how to use the jdb debugger that comes with the Java
Developer's Kit.
<LI>Try using breakpoints and single-stepping through some of
the code in the Scorpion Roundup sample game.
<LI>See whether you can find any bugs in Scorpion Roundup, or
for that matter in any of the sample code in the book. If you
manage to find anything, be sure to e-mail me and let me know
how disappointed you are that I could be such a slacker to ship
bug-ridden code! My e-mail address is located in the author bio
at the front of the book.
</OL>
<P>
<HR WIDTH="100%"></P>

<CENTER><P><A HREF="ch13.htm"><IMG SRC="pc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="index.htm"><IMG SRC="hb.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="#CONTENTS"><IMG SRC="cc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A><A HREF="ch2rev.htm"><IMG 
SRC="nc.gif" BORDER=0 HEIGHT=88 WIDTH=140></A></P></CENTER>

<P>
<HR WIDTH="100%"></P>

</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -