Header Ads

Assertion Concept Simplified In Java

In our day to day coding we frequently use System.out.println() statement to debug our code. This is very popular and simple way to debug our development code or test code.One problem of this approach, we can not keep these System.out.println() statement as it is. we need to remove this statement before releasing this code. It is basically overhead for any coder. To overcome this problem Java has come up with a concept called Assertion in java 1.4. prior to java 1.4, in Java 1.3 version it was declared as Indentifier.
The concepts are as follows..

  • The main advantage of assertion is like System.out.println statement, we don't need to delete these statements  as they do not get executed by default.
  • Secondly after release if any bug has come to that particular module we need to fix that. Post bug fix or during debugging again we don't need to enter System.out.println   or Assert statement. It is already available inside the code hence only enabling that will reduce our work.
  • So it exists in development and test instance but not in production environment
  • It is a better alternative for System.out.println statement.
Let us see more details:
class assertTest
{
public static void main(String[] args)
{
int assert=13;
System.out.println(assert);

}
}

Compiler will throw errors saying:

javac E:\myProgram\assertTest.java


E:\myProgram\assertTest.java:5: error: as of release 1.4, 'assert' is a keyword,and may not be used as an identifier
int assert=13;
     ^
(use -source 1.3 or lower to use 'assert' as an identifier)
E:\myProgram\assertTest.java:6: error: as of release 1.4, 'assert' is a keyword,and may not be used as an identifier
System.out.println(assert);
                            ^
(use -source 1.3 or lower to use 'assert' as an identifier)
2 errors
But if we compile against java 1.3, it will compile fine but with warning.


javac -source 1.3 E:\myProgram\assertTest.java
warning: [options] bootstrap class path not set in conjunction with -source 1.3
E:\myProgram\assertTest.java:5: warning: as of release 1.4, 'assert' is a keywor
d, and may not be used as an identifier
int assert=13;
^
(use -source 1.4 or higher to use 'assert' as a keyword)
E:\myProgram\assertTest.java:6: warning: as of release 1.4, 'assert' is a keywor
d, and may not be used as an identifier
System.out.println(assert);
^
(use -source 1.4 or higher to use 'assert' as a keyword)
3 warnings


let us see one more example..
class assertTest
{
public static void main(String[] args)
{
assert(false);
System.out.println(assert);

}
}


For this case if we compile with source -1.3, we will get compiler error. but similarly if we compile against 1.4 or upgraded version of java. We will not get the compilation error.
Conclusion: assert could have been used as an identifier in java 1.2 or java 1.3 and in java 1.4 it was promoted as a keyword.So, now ,java 1.4 onward assert can not be used as an identifier. 
Types of Assert:

  • Simple
  • Augmented
Simple Assertion:
The syntax for simple assertion is
assert(b)
Where b should be Boolean.
It signifies that up to assert statement if b value calculated as true then rest of the statements (below assert statements will be executed). If the assert value calculated as false then it will throw an assertion error and terminate the program.
let us check out one sample program
class assertTest{
public static void main(String... args)
{
int a=12;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
assert(a>12);
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
System.out.println(a); 
}
}
The output for this program will be:

javac assertTest.java
java assertTest
output:12
now ..
java -ea assertTest
output:Assertion Error
Exception in thread "main" java.lang.AssertionError
at assertTest.main(assertTest.java:6)


Why?
By default the assertions are disabled , but by using "-ea" we are enabling the assertion.
Now if you see the output of the previous program, by seeing the console it is very tough to understand what went wrong.If it is small program then it is ok.We can identify the problem.But think about a scenario where thousands of lines are getting executed.
To get more clarity to the program java has come up with upgrade version of assertion called Augmented version assertion

Augmented Assertion:
So the main advantage of augmented version is that in the console we can append some description with assertion error.
The syntax for the augmented assertion is assert(b):c;
where b is boolean and c can be any data type
Now let us modify our previous program little bit:
class assertTest{
public static void main(String... args)
{
int a=12;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
assert(a>12):"The value of a should be greater than 12";
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
System.out.println(a); 
}
}
javac assertTest.java
java assertTest
output:12
now ..
java -ea assertTest
The output:
Exception in thread "main" java.lang.AssertionError: The value of a should be greater than 12
at assertTest.main(assertTest.java:6)
So we are getting bit more clarity from the code.
Augment Assertion Rule-1
For this augmented assertion if the first argument is true(value of b)then the second argument c(some string output for this case) will not be evaluated.
lets see that:
class assertTest{
public static void main(String... args)
{
int a=12;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
assert(a==12):++a;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
System.out.println(a); 
}
}
javac assertTest.java
java assertTest
output:12
now ..
java -ea assertTest
output:12
This time the assertion passed hence ++a was not executed .

Now let us see the same example by failing the assertion condition ...this time b fails so c should get executed
class assertTest{
public static void main(String... args)
{
int a=12;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
assert(a>12):++a;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
System.out.println(a);
}
} 
javac assertTest.java
java assertTest
output:12
now ..
java -ea assertTest
output:Exception in thread "main" java.lang.AssertionError: 13
at assertTest.main(assertTest.java:6)

So a value is now incremented by one and got printed.
Augment Assertion Rule-2
The second argument c can be a method call,and very logically that method should not be a void type.

So the syntax should be assert(b):method_name();
let us check out via code:
class assertTest{
public static void main(String... args)
{
int a=12;
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
assert(a>12):methodxyz();
//do some calculation
//do some calculation
//do some calculation
//do some calculation
//do some calculation
System.out.println(a);
}
public static int methodxyz()
{
return 65;
}
} 

javac assertTest.java
java assertTest
output:12
now ..
java -ea assertTest
output:Exception in thread "main" java.lang.AssertionError: 65
at assertTest.main(assertTest.java:6)

Now if we change the return type of that function as void , we are going to get compile time error.
The error details:
E:\myProgram\assertTest.java:6: error: 'void' type not allowed here
assert(a>12):methodxyz();
^
1 error

Various Possible Runtime Flags
Let us check what are the flags available--

Flags

Description
-ea/-enableassertions To enable assertion in every non-system classes
-da/-diaableassrtions To disable assertion in every non-system classes
-esa/-enablesystemassertions To enable assertion in every system classes
-dsa/-deletesystemassertions To disble assertion in every non-system classes


In general normal java developers use assertion for non-system classes and java-API developers use assertion for system classes.
we can use the above flags simultaneously then JVM will consider these flags from left to right.
java -ea -esa -da -ea-esa-da -dsa -ea testAssert
the above written syntax is valid.
Let us check out few more examples:

In our real time coding we might require to enable assertion against customized classes .
if our package structure is the picture above then..

Objective

Required Code

To enable assertions only for B class

java -ea:package1:B

To enable assertions only in B and D classes

java -ea:package1:B -ea:package1.package2.D

To enable assertion everywhere inside package1 except B class

java -ea:package1... -da:package1.B

To enable assertion everywhere inside package1 except package2 classes

java -ea:package1... -da:package1.package2...

To enable assertions everywhere inside package1

java -ea:package1...

Conclusion:
So we can enable or disable assertions classwise or package wise.

Powered by Blogger.