The Sysadmin Notebook  

Sitemap

Java Syntax

Java Syntax Primer

Contents

Main Method

Top Bottom

To execute a Java program, a Java class-file is passed to the Java VM, which in turn looks for a method called 'main' which must have the following signature:

public static void main ( String [] args)

The 'main' methods has a 'void' return value, and arguments are passed as an array of strings. The 'main' method is the starting point for all Java applications, and when the main method exits, so does the application. The method must be declared as 'public static' so that is is globally accessible and can be called directly by name.

Comments

Top Bottom
Block comments
/* This is
a multi-line
comment */
Single Line comments
// this is a single line comment
int counter; //single line comment after a statement
Javadoc comments
/**
* Javadoc comments are designed to extracted by documentation 
* Generators such as javadoc. Lines beginning with @ denote tags 
* that are interpreted
* as special instructions for the documentation generator. 
* Beginning each line with an asterisk is optional but the preferred 
* convention
* @author Mustapha Leek
* @version 1.00, 10 Apr 2010
*/
This table lists the tags available for use in Javadoc comments
Tag Description Applies To
@see Associated class name Class, method or variable
@author Author Name Class
@version Version string Class
@param Parameter name and description Method
@return Return value description Method
@exception Exception name and description Method
@deprecated Declares an item deprecated Class, method or variable
@since Records API version when added Variable

Data Types

Top Bottom

Primitive Data Types

Top Bottom

Primitive data types are not implemented as objects, and therefore their implementation can be optimised at compile and runtime. Wrapper classes exist for the primitive data types and the compiler can automatically convert between the primitives and wrappers as needed.

Primitive Data Types in Java
Type Definition
boolean true or false
char 16-bit Unicode character
byte 8-bit, signed integer
short 16-bit, signed integer
int 32-bit, signed integer
long 64-bit, signed integer
float 32-bit, IEEE 754, floating-point value
double 64-bit IEEE 754

Variables are declared inside methods or classes and are limited in scope to their enclosing code block.

int age;
double cost, totalCost;
int age = 45, devices = 53;
int age = 055; 		//45 expressed with an octal integer literal
int age = 0x2d; 	//45 expressed with a hexidecimal integer literal
long age = 45L; 	//explicitly declare integer literal as a type long
long age = 45; 		//integer literal implicitly converted to long before assignment
boolean isOK = false;

byte smallish = 42;
int biggish = 34; 
int result = b * i; 	//byte value implicitly promoted to int before operation

byte smallish = (byte) biggish;	//explicitly cast larger data type to smaller data type

double cost = 9.57;
float cost = 9.57f; 	//explicitly declare double literal as type float
float cost = 9.57; 	//double literal implicitly convert to float before assignment

char a = 'a'; 		//single-quoted literal character
char tab = '\t'; 	//escaped ascii character literal
char enya = '\u241'  	//unicode character literal ñ

Reference Types

Top Bottom

An object variable is a reference to an object and reference types always point to objects. Assigning the value 'null' to a reference deletes the object. Objects are created using the 'new' operator:

Robot r = new Robot();

Classes define complex data types and new classes can be created from primitive types and other classes. Classes inherit the functionality of parent classes, and are thus subtypes of the parent class. The subtype can be considered as an extension of the parent class (subtype polymorphism) and objects of the subtype can be used anywhere an object of the parent type can used.

Methods

Top Bottom

Methods are code blocks that take parameters and can be called by name. Methods are defined within a class and have a signature that specifies its parameters and return type. The '.' operator is used to call a method on an object and multiple '.' operators can be used to created a chained method call:

System.out.println("Using the println method");

Conditional Statements

Top Bottom

The curly braces surrounding the code block of a conditional statement are optional if the code block consists of only one statement

If-Else

Top Bottom

The basic syntax for an if else statement is:

if (condition) {
  statements;
} 
else {
  statements;
}

The curly braces are optional if there is only one statement following the if. The else clause is also optional:

if ( condition ) statement;

If-Else statements can be nested allowing for more complicated decision trees:

public class testing {
	public static void main (String[] args) {
		int x = 10;   
		if (x > 10) 
			System.out.println("x is larger than 10");
		else 
			if (x < 10) 
				System.out.println("x is less than 10");
		        else 
				System.out.println("x is equal to 10");
	}
}

While

Top Bottom
while (condition) {
  statements;
}
public class testing {
	public static void main (String[] args) {
		int x = 10;
		while (x < 15) 
			System.out.println("x is now: " + x++);

	}
}

The do..while guarantees the code will execute at least once

do {
  statements; 
} while (condition);
public class testing {
	public static void main (String[] args) {
		int x = 15;
		do 
			System.out.println("x is now: " + x);
		while (x++ < 15) ;

	}
}

For

Top Bottom
for (initialisation; condition; incrementor) {
  statements;
}
public class testing {
	public static void main (String[] args) {
		int i = 0;
		int f = 5;
		for (int j = f; j > 1; j--) {
			if (i == 0) i = f; 
			else i *= j;
		}
		System.out.println("Factorial " + f + " equals " + i);
			
	}
}

And the 'enhanced' for loop:

for ( varDeclaration : iterableObject) {
  statements;
}
public class testing {
	public static void main (String[] args) {
		int [] aInts = new int [] {6, 5, 4, 3, 2 };
		int i = 0, f = 0; 
		for (int j : aInts) {
			if (f == 0) { 
				i = f = j;
			}
			else 
				f *= j;
		}
		System.out.println("Factorial " + i + " equals " + f);
			
	}
}

Switch

Top Bottom

Multiple 'If-Else'statements are inefficient if testing the same variable against multiple conditions. The 'Switch' statement provides a more efficient control structure for such situations:

public class testing {
	public static void main (String[] args) {
		int day = 8;

		switch (day)
		{
			case (1):
			case (2):
			case (3):
			case (4):
				System.out.println("It's a weekday");
				break;
			case (5):
				System.out.println("Thank God it's Friday");
				break;
			case (6):
			case (7):
				System.out.println("The weekend has arrived");
				break;
			default:
				System.out.println("You seem to be using an extended Calendar");
				break;
		}
	}
}

The 'test-condition' for a switch loop can be a variable name or any other expression that can be evaluated, and can include enumerations.

public class testing {
	enum Day {Mon, Tue, Wed, Thu, Fri, Sat, Sun};
	public static void main (String[] args) {
		Day day = Day.Mon;
		switch (day)
		{
			case Mon:
			case Tue:
			case Wed:
			case Thu:
				System.out.println("It's a weekday");
				break;
			case Fri:
				System.out.println("Thank God it's Friday");
				break;
			default:
				System.out.println("The weekend has arrived");
				break;
		}
	}
}

Without the 'break' statements, the switch block will test each case even after a matching case is found. Break can also be used to exit other conditional loops.

Continue

Top Bottom

Continue statements can be used in while and for loops to halt execution of the current block and begin the loop with the next iteration. Break can be used to exit the loop completely. Both break and continue support 'labels' to either continue from or break out from a specified labelled loop.

public class testing {
	public static void main (String[] args) {
		int candidate = 1, j = 3056;
		int largest = 1;
OuterLoop:
		while (++candidate < j) {
			if ((candidate % 2) == 0)  continue; // even factor not worth testing
			if ((candidate * 2) >= j)  break; // too large to be a factor
			int k = candidate; // is the candidate factor a prime number
			while (k-- > 2) {
				if ((candidate % k) == 0) continue OuterLoop; 
			}	
			if ((j % candidate) == 0) { // is the candidate factor a factor of j
				largest = candidate;
				System.out.println(candidate + " is a prime factor of " + j);
			}
		}
		if (largest == 1) 
			System.out.println(j + " is a prime number with no prime factors");
		else 
			System.out.println("Largest Prime factor of " + j + " is " + largest);
	}
}

The ternary operator

Top Bottom
int k = ((candidate % 2) == 0) ? (candidate / 2) : ((candidate + 1) / 2);

If the test expression ((candidate % 2)) == 0) evaluates to true, k is set to (candidate / 2), otherwise k is set to ((candidate + 1) / 2).

Operators

Top Bottom

Arithmetic

Top Bottom
Arithmetic Operators
Operator Operation Notes
+ addition or concatenation Adds numbers, concatenates strings. If one operator is a string, then the other is converted to a string and concatenation is applied. Operator has left-to-right associativity
- subtraction
* multiplication
/ division
% modulus division Returns the remainder of dividing the left operand by the right operand
++ increment
-- decrement

Comparison

Top Bottom
comparison operators
operator operation notes
== is equal to tests equality of value for primitive data types or equality of reference for objects
!= not equal to tests equality of value for primitive data types or equality of reference for objects
> greater than
>= greater than or equal to
< less than
<= less than or equal to
instanceof is an instance of evaluates to true if left object operand is an instance of the right-side class operand

logical

Top Bottom
logical and bitwise operators
operator operation notes
&& conditional and
|| conditional or
! not logical complement
& and boolean or bitwise: sets bit to 1 if bit is set to 1 in both left and right operand
| or boolean or bitwise: sets bit to 1 if bit is set to 1 in either left and right operand
~ bitwise not reverses all bits in its argument
<< shift left shifts bits in left operand to the left by the number specified in right operand. equivalent to multiplication by 2 to the power of right operand
>> shift right shifts bits in left operand to the right by the number specified in right operand. equivalent to integer division by 2 to the power or right operand. preserves sign of original left operand
>>> shift right shifts bits in left operand to the right by the number specified in right operand. fills left bits with ones. does not preserve sign of original left operand

others

Top Bottom
miscellaneous operators
operator operation notes
?: conditional the ternary operator
(type) cast operand to different type
new object constructor and initialiser returns an object of type specified with optional parenthesised argument list as initialisers
[] array element access
. object element access used to access both object and class variables and methods
() function call
= assignment operator assigns rvalue to lvalue. compound assignments possible: j = ( i = 10 )

Error Handling

Top Bottom

During execution of code, if an exception occurs an exception object is created containing a full stack trace plus additional information provided by the method itself. The exception object is then passed as an argument to the handler code.

Java provides a 'try-catch' statement to handle errors that may be thrown by a program:

public class testing {
	public static void main (String[] args) {
		int i = 7;
		int factorial = i;
		int [] aInts = new int [i];
		for (int j = 0; j <= aInts.length - 1; j++) aInts[j] = j + 1;
		int [] arrCopy = new int [aInts.length - 1];
		try {
			System.arraycopy(aInts, 0, arrCopy, 0, aInts.length);
		}
		catch (ArrayIndexOutOfBoundsException e) {
			System.out.println("Expected error occurred");
			e.printStackTrace(System.err);
		}
		finally {
			System.arraycopy(aInts, 0, arrCopy, 0, aInts.length - 1);
		}
		for (int k : arrCopy) factorial *= k;
		System.out.println("Factorial " + i + " equals " + factorial);
	}
}

The 'try' block surrounds the code that is to be protected by the exception handlers in the 'catch' blocks. Code within the try block executes normally unless an exception or error is thrown, at which point no further code in the 'try' block is executed. Instead Java searches for a catch block that matches the exception thrown. If an error is thrown in a block with no matching handler defined, the exception is passed up to the caller, and continues propagating up the call stack until a handler is found or if none is found, the program terminates with a runtime error.

Even when no catch block traps the error, the 'finally' block always executes. Once the handler finishes processing the error and the (optional) finally block executes, the program continues processing from the end of the try-catch-finally blocks.

Java methods must specify the types of exceptions they can throw, using a 'throws' clause in the method signature, and the compiler ensures that users of the method contain handlers for those exceptions.

Both Exceptions and Errors are subtypes of 'Throwable' - a class of objects that can be thrown with a 'throw' statement.

public class testing {
	public static void main (String[] args) {
		try {
  			for (int i = 0; i <= 11 ; i++) {
  				if (i == 10) {
  			  	throw new IllegalArgumentException("Interger i is now " + i);
  				}
  				System.out.println(i);
  		  	}
  		}
		catch (IllegalArgumentException e) {
			System.out.println(e.getMessage());
			//e.printStackTrace(System.err);
		}
	}
}

The Exception object Subclasses are:

Unrecoverable errors are objects of type java.lang.Error and, by their 'unrecoverable' nature, should not be caught by exception handlers. The subclasses of Error are:

Other packages provide their own exception classes that extend the Exception class such as:

IOException
from the java.io package
Network exceptions
from the java.net package
RemoteException
from the java.rmi package

Assertions

Top Bottom

Assertions provide a mechanism for testing runtime logic: if an assertion fails, then an Assertion error is thrown and the program is terminated, but only when assertions are enabled. They can thus be used when developing code to test expected behaviour is produced, but will have no effect on released code (unless run with assertions enabled).

Assertions are created using the 'assert' statement with a Boolean condition and an optional expression:

public class testing {
	public static void main (String[] args) {
		int i = 0;
		while (i++ < 10) {
			System.out.println("i is now: " + i);
			assert i < 10 : "i is not less than 10";
		}
		System.out.println("This message won't appear if you " +
			"run this program with assertions enabled.\n " +
			"Use 'java -ea testing' to turn on assertions");
	}
}

Assertions are normally turned off, and thus should not be used for essential program logic