Java assert

From Juneday education
Jump to: navigation, search

The assert statement allows you to write a predicate (a boolean expression which can be either true or false) about the state of your program, that you expect to always be true (otherwise your program is behaving wrong).

When the program is running (in Java you need to enable assertions using the -ea flag when running with assertions), and an assertion (the predicate) evaluates to false (contrary to what you hoped for), an error is thrown crashing the program with an error message. The message should preferably contain information on what went wrong, so that the programmers can fix the bug causing this error.

You can think of it as a safety measure based on the principle that "If this isn't true, it's better to crash the program so it can be fixed, than to continue running".

Example usage:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.List;

/* Usage:
 * To run with assertions enabled:
 * javac TestAssert.java && java -enableassertions TestAssert
 * OR:
 * javac TestAssert.java && java -ea TestAssert
 *
 * To run without assertions (nothing will happen or be printed):
 * javac TestAssert.java && java TestAssert
 */

public class TestAssert {
    static boolean isEven(int i) {
	return i % 2 == 0;
    }
    static boolean isOdd(int i) {
	return ! isEven(i);
    }

    // Unsafe add! a result larger than
    // Integer.MAX_VALUE will wrap around (and become negative)
    static int add(int a, int b) {
	return a + b;
    }
    
    // Helper method to print text when a test passes
    static void pass(String prefix, String s) {
	RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
	List<String> arguments = runtimeMxBean.getInputArguments();
        // Only print if assertions are enabled
	if (arguments.contains("-enableassertions") ||
            arguments.contains("-ea")) {
	    System.out.println(prefix + s);
	}
    }
  
    public static void main(String[] args) {
	assert isEven(2) : "\nFail: isEven(2) did not return true";
	pass("PASS: ","isEven(2) == true");
	assert isOdd(1)  : "\nFail: isOdd (1) did not return true";
	pass("PASS: ","isOdd(1)  == true");
	assert isEven(0) : "\nFail: isEven(0) did not return true";
	pass("PASS: ", "isEven(0) == true");
	assert add(1,2)==3 : "\nFail: add(1,2) did not return 3";
	pass("PASS: ","add(1,2)  == 3");

	// One property we can check is that an addition of two positive number is greater than
	// the smallest of the two numbers:
	int big   = Integer.MAX_VALUE;
	int small = 1;

        // The next statement would fail
	//assert add(big,small)>small : "Fail: add("+big+","+small+") was not greater than "+small+". Returned: "+add(big,small);
	
	// Can we use Math.abs?
	int verySmall = Integer.MIN_VALUE;
	pass("INFO: ", "Max integer value: " + big + " min integer value: "+verySmall);
	pass("INFO: ", "Is Math.abs(int i) safe from overflow?");
	pass("INFO: ", "Let's try Math.abs with a long value type first:");
	/* The smallest int value has an abs value that does not fit inside
         * an int.
         *
	 * It fits inside a long, though.
	*/
	long intMin = verySmall;
	long abs    = Math.abs(intMin);
	assert abs > 0 : "\nFail: "+abs+" was not positive.";
	pass("PASS: ", "Math.abs("+(long)verySmall + ") (value type long) is positive.");
        
	pass("INFO: ", "Let's try Math.abs(Integer.MIN_VALUE) with an int value:");
	assert Math.abs(verySmall) > 0 : "\nFail: Math.abs("+verySmall+") was not positive: "+Math.abs(verySmall);
	pass("PASS: ", "Math.abs("+verySmall+") (value type int) was positive."); // will not print!
    }
}

Read more: