epubjs
Version:
Render ePub documents in the browser, across many devices
112 lines (111 loc) • 14.7 kB
HTML
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Assertions</title><link rel="stylesheet" href="core.css" type="text/css"/><meta name="generator" content="DocBook XSL Stylesheets V1.74.0"/></head><body><div class="sect1" title="Assertions"><div class="titlepage"><div><div><h1 class="title"><a id="learnjava3-CHP-4-SECT-6"/>Assertions</h1></div></div></div><p>An assertion is a simple pass/fail test of some condition, performed
while your application is running. Assertions can be used to “sanity
check” your code anywhere you believe certain conditions are guaranteed by
correct program behavior. Assertions are distinct from other kinds of
tests because they check conditions that should never be violated at a
logical level: if the assertion fails, the application is to be considered
broken and generally halts with an appropriate error message. Assertions
are supported directly by the Java language and they can be turned on or
off at runtime to remove any performance penalty of including them in your
code.</p><p>Using assertions to test for the correct behavior of your
application is a simple but powerful technique for ensuring software
quality. It fills a gap between those aspects of software that can be
checked automatically by the compiler and those more generally checked by
“unit tests” and human testing. Assertions test assumptions about program
behavior and make them guarantees (at least while they are
activated).</p><p>If you have programmed before, you may have written something like
the following:</p><a id="I_4_tt188"/><pre class="programlisting"> <code class="k">if</code> <code class="o">(</code> <code class="o">!</code><code class="n">condition</code> <code class="o">)</code>
<code class="k">throw</code> <code class="k">new</code> <code class="nf">AssertionError</code><code class="o">(</code><code class="s">"fatal error: 42"</code><code class="o">);</code></pre><p>An assertion in Java is equivalent to this example, but is performed
with the <a id="I_indexterm4_id686677" class="indexterm"/><code class="literal">assert</code> language keyword.
It takes a Boolean condition and an optional expression value. If the
assertion fails, an <a id="I_indexterm4_id686689" class="indexterm"/><code class="literal">AssertionError</code> is thrown,
which usually causes Java to bail out of the application.</p><p>The optional expression may evaluate to either a primitive or object
type. Either way, its sole purpose is to be turned into a string and shown
to the user if the assertion fails; most often you’ll use a string message
explicitly. Here are some examples:</p><a id="I_4_tt189"/><pre class="programlisting"> <code class="k">assert</code> <code class="kc">false</code><code class="o">;</code>
<code class="k">assert</code> <code class="o">(</code> <code class="n">array</code><code class="o">.</code><code class="na">length</code> <code class="o">></code> <code class="n">min</code> <code class="o">);</code>
<code class="k">assert</code> <code class="n">a</code> <code class="o">></code> <code class="mi">0</code> <code class="o">:</code> <code class="n">a</code> <code class="c1">// shows value of a to the user</code>
<code class="k">assert</code> <code class="n">foo</code> <code class="o">!=</code> <code class="kc">null</code> <code class="o">:</code> <code class="s">"foo is null!"</code> <code class="c1">// shows message "foo is null!" to user</code></pre><p>In the event of failure, the first two assertions print only a
generic message, whereas the third prints the value of <code class="literal">a</code> and the last prints the <code class="literal">foo is null!</code> message.</p><p>Again, the important thing about assertions is not just that they
are more terse than the equivalent <code class="literal">if</code>
condition, but that they can be enabled or disabled when you run the
application. Disabling assertions means that their test conditions are not
even evaluated, so there is no performance penalty for including them in
your code (other than, perhaps, space in the class files when they are
loaded).</p><div class="sect2" title="Enabling and Disabling Assertions"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-6.1"/>Enabling and Disabling Assertions</h2></div></div></div><p><a id="idx10135" class="indexterm"/> <a id="idx10184" class="indexterm"/>Assertions are turned on or off at runtime. When disabled,
assertions still exist in the class files but are not executed and
consume no time. You can enable and disable assertions for an entire
application or on a package-by-package or even class-by-class basis. By
default, assertions are turned off in Java. To enable them for your
code, use the <code class="literal">java</code> command flag
<a id="I_indexterm4_id686787" class="indexterm"/><a id="I_indexterm4_id686794" class="indexterm"/><code class="literal">-ea</code> or <code class="literal">-enableassertions</code>:</p><a id="I_4_tt191"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="o">-</code><code class="n">ea</code> <code class="n">MyApplication</code></code></strong></pre><p>To turn on assertions for a particular class, append the class
name:</p><a id="I_4_tt192"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="o">-</code><code class="nl">ea:</code><code class="n">com</code><code class="o">.</code><code class="na">oreilly</code><code class="o">.</code><code class="na">examples</code><code class="o">.</code><code class="na">Myclass</code> <code class="n">MyApplication</code></code></strong></pre><p>To turn on assertions just for particular packages, append the
package name with trailing ellipses (. . .):</p><a id="I_4_tt193"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="o">-</code><code class="nl">ea:</code><code class="n">com</code><code class="o">.</code><code class="na">oreilly</code><code class="o">.</code><code class="na">examples</code><code class="o">...</code></code></strong><strong class="userinput"><code><code class="n">MyApplication</code></code></strong></pre><p>When you enable assertions for a package, Java also enables all
subordinate package names (e.g., <code class="literal">com.oreilly.examples.text</code>). However, you can
be more selective by using the corresponding <a id="I_indexterm4_id686870" class="indexterm"/><code class="literal">-da</code> or <a id="I_indexterm4_id686883" class="indexterm"/><code class="literal">-disableassertions</code> flag
to negate individual packages or classes. You can combine all this to
achieve arbitrary groupings like this:</p><a id="I_4_tt194"/><pre class="programlisting"> <code class="o">%</code> <strong class="userinput"><code><code class="n">java</code> <code class="o">-</code><code class="nl">ea:</code><code class="n">com</code><code class="o">.</code><code class="na">oreilly</code><code class="o">.</code><code class="na">examples</code><code class="o">...</code>
<code class="o">-</code><code class="nl">da:</code><code class="n">com</code><code class="o">.</code><code class="na">oreilly</code><code class="o">.</code><code class="na">examples</code><code class="o">.</code><code class="na">text</code></code></strong><strong class="userinput"><code><code class="o">-</code><code class="nl">ea:</code><code class="n">com</code><code class="o">.</code><code class="na">oreilly</code><code class="o">.</code><code class="na">examples</code><code class="o">.</code><code class="na">text</code><code class="o">.</code><code class="na">MonkeyTypewriters</code>
<code class="n">MyApplication</code></code></strong></pre><p>This example enables assertions for the <code class="literal">com.oreilly.examples</code> package as a whole,
excludes the package <code class="literal">com.oreilly.examples.text</code>, and then turns
exceptions on for just one class, <code class="literal">MonkeyTypewriters</code>, in that package.<a id="I_indexterm4_id686938" class="indexterm"/><a id="I_indexterm4_id686945" class="indexterm"/></p></div><div class="sect2" title="Using Assertions"><div class="titlepage"><div><div><h2 class="title"><a id="learnjava3-CHP-4-SECT-6.2"/>Using Assertions</h2></div></div></div><p><a id="idx10136" class="indexterm"/> <a id="idx10185" class="indexterm"/>An assertion enforces a rule about something that should
be unchanging in your code and would otherwise go unchecked. You can use
an assertion for added safety anywhere you want to verify your
assumptions about program behavior that can’t be checked by the
compiler.</p><p>A common situation that cries out for an assertion is testing for
multiple conditions or values where one should always be found. In this
case, a failing assertion as the default or “fall through” behavior
indicates the code is broken. For example, suppose we have a value
called <code class="literal">direction</code> that should always
contain either the constant value <code class="literal">LEFT</code> or <code class="literal">RIGHT</code>:</p><a id="I_4_tt195"/><pre class="programlisting"> <code class="k">if</code> <code class="o">(</code> <code class="n">direction</code> <code class="o">==</code> <code class="n">LEFT</code> <code class="o">)</code>
<code class="n">doLeft</code><code class="o">();</code>
<code class="k">else</code> <code class="nf">if</code> <code class="o">(</code> <code class="n">direction</code> <code class="o">==</code> <code class="n">RIGHT</code> <code class="o">)</code>
<code class="n">doRight</code><code class="o">()</code>
<code class="k">else</code>
<code class="k">assert</code> <code class="kc">false</code> <code class="o">:</code> <code class="s">"bad direction"</code><code class="o">;</code></pre><p>The same applies to the default case of a switch:</p><a id="I_4_tt196"/><pre class="programlisting"> <code class="k">switch</code> <code class="o">(</code> <code class="n">direction</code> <code class="o">)</code> <code class="o">{</code>
<code class="k">case</code> <code class="nl">LEFT:</code>
<code class="n">doLeft</code><code class="o">();</code>
<code class="k">break</code><code class="o">;</code>
<code class="k">case</code> <code class="nl">RIGHT:</code>
<code class="n">doRight</code><code class="o">();</code>
<code class="k">break</code><code class="o">;</code>
<code class="k">default</code><code class="o">:</code>
<code class="k">assert</code> <code class="kc">false</code><code class="o">;</code>
<code class="o">}</code></pre><p>In general, you should not use assertions for checking the
validity of arguments to methods because you want that behavior to be
part of your application, not just a test for quality control that can
be turned off. The validity of input to a method is called its
<a id="I_indexterm4_id687041" class="indexterm"/><span class="emphasis"><em>preconditions</em></span>, and you should usually
throw an exception if they are not met; this elevates the preconditions
to part of the method’s “contract” with the user. However, checking the
correctness of results of your methods with assertions before returning
them is a good idea; these are called <a id="I_indexterm4_id687055" class="indexterm"/><span class="emphasis"><em>post-conditions</em></span>.</p><p>Sometimes determining what is or is not a precondition depends on
your point of view. For example, when a method is used internally within
a class, preconditions may already be guaranteed by the methods that
call it. Public methods of the class should probably throw exceptions
when their preconditions are violated, but a private method might use
assertions because its callers are always closely related code that
should obey the correct behavior.</p><p>Finally, note that assertions can not only
test simple expressions but perform complex validation as well. Remember
that anything you place in the condition expression of an <a id="I_indexterm4_id687080" class="indexterm"/><code class="literal">assert</code> statement is not
evaluated when assertions are turned off. You can make helper methods
for your assertions that may contain arbitrary amounts of code. And,
although it suggests a dangerous programming style, you can even use
assertions that have side effects to capture values for use by later
assertions—all of which will be disabled when assertions are turned off.
For example:</p><a id="I_4_tt197"/><pre class="programlisting"> <code class="kt">int</code> <code class="n">savedValue</code><code class="o">;</code>
<code class="k">assert</code> <code class="o">(</code> <code class="n">savedValue</code> <code class="o">=</code> <code class="n">getValue</code><code class="o">())</code> <code class="o">!=</code> <code class="o">-</code><code class="mi">1</code><code class="o">;</code>
<code class="c1">// Do work...</code>
<code class="k">assert</code> <code class="nf">checkValue</code><code class="o">(</code> <code class="n">savedValue</code> <code class="o">);</code></pre><p>Here, in the first <code class="literal">assert</code>, we
use the helper method <code class="literal">getValue()</code> to
retrieve some information and save it for later. Then, after doing some
work, we check the saved value using another assertion, perhaps
comparing results. When assertions are disabled, we’ll no longer save or
check the data. Note that it’s necessary for us to be somewhat cute and
make our first <code class="literal">assert</code> condition into
a Boolean by checking for a known value. Again, using assertions with
side effects is a bit dangerous because you have to be careful that
those side effects are seen only by other assertions. Otherwise, you’ll
be changing your application behavior when you turn them off.<a id="I_indexterm4_id687136" class="indexterm"/><a id="I_indexterm4_id687143" class="indexterm"/></p></div></div></body></html>