the java assert statement. 2 assert a java statement in jdk 1.4 & newer intent: enables code to...
Post on 19-Dec-2015
226 views
TRANSCRIPT
2
Assert
• A Java statement in JDK 1.4 & newer
• Intent: enables code to test assumptions. E.g., a method that calculates a particle’s speed, asserts:
speed < c (speed of light).
• Has a boolean expression whose truth is “asserted” when the assert statement executes.– If it is false, the system throws an error.
– assert confirms assumptions about program behavior.Increases confidence that the program is error-free.
3
Assert …
• Assert: Detecting bugs is quicker when
asserts are included in the code.
• Assert also documents the program,
enhancing maintainability.
4
Outline
• Introduction
• Using Assert
• Compiling Files That Use Assert
• Enabling & Disabling Asserts
5
Introduction
• The assertion statement has 2 forms:
assert Expression; // Expression is boolean
Meaning:
if ( ! Expression )
{
throw AssertionError // no message
}
6
Introduction …
assert Expression1 : Expression2 ; where: – Expression1 is boolean– Expression2 has a value
Cannot be the returned value of a void method.
Meaning:
if ( ! Expression1 )
{
throw new AssertionError ( Expression2 )
}// Expression2.toString() is the message.
7
The Message
• Should convey details of the assert failure
• Is not a user-level message
• Need not be understandable in isolation
• Is intended for use with:
– a full stack trace
– the source code.
8
Introduction …
• The stack trace gives the file/line# of the
failed assertion.
• Use the message form only to add
information that helps diagnose the failure.
E.g., if Expression1 involves a relationship between
variables x & y, use the message form.
E.g.,
assert x < y : “x: “ + x + “, y: “ + y ;
9
Introduction …
• Asserts are enabled/disabled when the JVM
starts.
• Asserts are disabled by default.
• Disabled asserts are equivalent to empty
statements in semantics & performance.
10
Outline
• Introduction
• Using Assertions
• Compiling Files That Use Assertions
• Enabling & Disabling Assertions
11
Using Assertions
• Do not use assertions for
argument checking in public methods, ifArgument checking is part of the method’s specification
Specifications are obeyed whether or not assertions are enabled.
• Assert’s expression should have no side-effects.
Exception: assertions can modify state used only from within other assertions (illustrated later).
12
Internal Invariants
Replace
if ( i % 3 == 0 )
{ ... }
else if ( i % 3 == 1 )
{ ... }
else
{
// i % 3 == 2
...
}
With
if ( i % 3 == 0 )
{ ... }
else if ( i % 3 == 1 )
{ ... }
else
{
assert i > 0 && i % 3 == 2 ;
...
}
13
Preconditions
• Do not assert method specification/** * Sets the refresh rate. * @param rate refresh rate, in frames per second. * @throws IllegalArgumentException if rate <= 0 or * rate > MAX_REFRESH_RATE. */ public void setRefreshRate( int rate ) { // Enforce specified precondition in public method
if (rate <= 0 || rate > MAX_REFRESH_RATE) throw new IllegalArgumentException("Illegal rate: "
+ rate); setRefreshInterval(1000/rate);
}
14
Preconditions …
• You may assert a nonpublic method's precondition
– Or log the error and continue, if that is possible.
• An assertion is appropriate in the following “helper”
method invoked by the previous method.
15
/**
* Sets the refresh interval (to a legal frame rate).
* @param interval refresh interval in milliseconds.
*/
private void setRefreshInterval( int interval )
{
// preconditions in nonpublic method
assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;
... // Set the refresh interval
}
16
Postconditions
Replace
void push( Object o )
{
…
stack.add( ++top, o );
// top == stack.size();
}
With
void push( Object o )
{
…
stack.add( ++top, o );
assert top == stack.size() : “top: ”
+ top + “, size: ” + stack.size();
}
17
Class State Invariants
• Class state invariant: an invariant that applies to all instances at the beginning & ending of all methods.E.g., in a balanced tree, a class invariant is that the tree is
balanced.
• Style: combine the expressions that check required constraints into an private method.
// Returns true if this tree is properly balanced private boolean isBalanced() { ... }
• Assert class invariant just prior to return from public methods & constructors:assert isBalanced();
18
Outline
• Introduction
• Using Assertions
• Compiling Files That Use Assertions
• Enabling & Disabling Assertions
• Compatibility with Existing Programs
19
Compiling Files That Use Assertions
To tell javac to accept assertions, use
-source 1.4 command-line option:
javac -source 1.4 MyClass.java
20
Outline
• Introduction
• Using Assertions
• Compiling Files That Use Assertions
• Enabling & Disabling Assertions
21
Enabling & Disabling Assertions
• By default, assertions are disabled. • Enable assertions, using the -ea, switch. • Disable assertions, using the -da, switch. • Specify granularity as the switch argument:
• no arguments Enables/disables assertions in all classes except system classes.
• packageName... Enables/disables assertions in the package & any subpackages.
• ... Enables/disables assertions in the unnamed package in the current working directory.
• className Enables/disables assertions in the named class.
22
Enabling & Disabling Assertions
• To run BatTutor, with assertions enabled only in package com.wombat.fruitbat & its subpackages:
java -ea:com.wombat.fruitbat... BatTutor
• To run BatTutor with assertions: – enabled in package com.wombat.fruitbat – disabled in class com.wombat.fruitbat.Brickbat:
java -ea:com.wombat.fruitbat... -da:com.wombat.fruitbat.Brickbat BatTutor
24
Control-Flow InvariantsUse: assert false; // an unreachable point
Replacevoid foo()
{
for (...)
{
if (...) return;
}
// unreachable point
}
With
void foo()
{
for (...)
{
if (...) return;
}
assert false; // unreachable
}
25
Control-Flow InvariantsUse: assert false; // an unreachable point
• The foregoing only makes sense if reaching a point is possible but erroneous.
• If it is impossible, the compiler handles it.
• If it is possible, you may always throw an exception
Not just when assertions are enabled.
Replace “assert false;”
with “throw new AssertionError();”
26
Lock-Status Precondition
Originalprivate Object[] a;
public synchronized int find(Object key)
{ return find(key, a, 0, a.length);
} // Recursive helper method:
always has lock on thisprivate int find(Object key,
Object[] arr, int start, int len) { ... }
Assert lock status: // Recursive helper method:
always has lock on this.
private int find(Object key, Object[] arr, int start, int len)
{
// lock-status assertion
assert Thread.holdsLock(this);
...
}
27
Postconditions …
• An assert’s expression may need state.void foo(int[] array) {
// Manipulate array ... // At this point, array contents == itself// prior to manipulation
}Replace the above with the following.
28
Postconditions …
void foo(final int[] array) { // Inner class that saves state & performs final consistency check class DataCopy {
private int[] arrayCopy; DataCopy() { arrayCopy = ( int[] ) array.clone(); } boolean isConsistent() { return Arrays.equals( array, arrayCopy ); }
} DataCopy copy = null; // Always succeeds; has side effect of saving a copy of array assert ( ( copy = new DataCopy() ) != null ); // copy only if ea... // Manipulate array // Ensure array has same ints in same order as before. assert copy.isConsistent();
}