Java's primitive types, character and numeric literals. How to declare variables, arrays of variables, and arrays of objects. How to initialise variables. Java expressions and type conversions. How to access members of a class, including overloaded methods. Integer and floatingpoint arithmetic. Java's ++, relational, bitwise, conditional, assignment operators and their precedence. Java's flow control
boolean
 either true or false
 

char  16bit Unicode 1.1.5 character  
byte  8bit signed two'scomplement integer  
short  16bit signed two'scomplement integer  
int  32bit signed two'scomplement integer  
long  64bit signed two'scomplement integer  
float  32bit IEEE 7541985 floatingpoint number  
double  64bit IEEE 7541985 floatingpoint number 
short
and byte
are always promoted to int
before being evaluated. They are only stored, never operated upon.
MIN_VALUE
= minimum value predefined for the type concernedMAX_VALUE
= maximum value predefined for the type concerned
float
and double
can also have stored values of:
NEGATIVE_INFINITY
POSITIVE_INFINITY
NaN
means 'not a number'. It indicates that the number is an invalid result such as the result of dividing by zero. This can be tested for by the method (function) isNan()
.
null
 an as yet uncreated, or an invalid, Object Reference  

true, false  the two possible values of a boolean variable  
29  int constant  decimal representation  
035  int constant  octal (base 8) representation  
0x1D  int constant  hexadecimal (base 16) representation 
When an int
constant (as above) is assigned to a byte
variable or a short
variable, it is automatically converted to byte
or short
as appropriate (provided its value lies within the valid range for that type).
29L long
constant  decimal representation035L long
constant  octal (base 8) representation0x1DL long
constant  hexadecimal (base 16) representation18.0F float
constant  the.0
is optional, theF
is mandatory1.8E1F float
constant  exponent form, the F is mandatory.18E2F float
constant  exponent form, the F is mandatory18.0D double
constant  the .0 and the D are optional1.8E1D double
constant  exponent form the D is optional.18E2D double
constant  exponent form the D is optional
Zero can be positive or negative. These are numerically equal but give different results in certain calculations eg:
A nonfloat constant such as a double cannot be assigned to a float variable. You must use a float literal viz:
float x = 18.9F;
Character literals appear between single quote marks viz:
char c = 'a'; //make character variable c contain the letter 'a'
Certain special characters are represented by the following escape sequences (which are also placed between single quote marks in assignment statements).
\n
 \u000A
 newline  

\t  \u0009  tab  
\b  \u0008  backspace  
\r  \u000D  return  
\f  \u000C  formfeed  
\\  \u005C  backslash  
\'  \u0027  single quote  
\"  \u0022  double quote  
\ddd  d = 0 to 7  character's octal value  
\udddd  d = 0 to F  character's hexadecimal value 
String literals appear between double quote marks viz:
String s = "help"; /* make string variable s point to a string
array containing the letters 'help' */
To break a line within a quoted string, you must insert a \n into the string, not simply start a new line in your source file. Be careful of how you place octal character entities in strings. For instance:
\0116
is rendered as \t6
(ie a tab
followed by a character 6
)
\116
is rendered as N
.
private
 variable is visible only within the immediate class in which it is declared.  

public
 variable is visible from anywhere from which the class within which it is declared is visible.  
protected
 variable is visible to classes which extend the class in which it is declared. 
static
 variable retains its value after the method in which it is declared terminates.  

synchronized
 variable is locked from access by other program threads while a particular thread is updating it.  
final
 variable can only be assigned a value once, that is, when it is initialised just before the first pass of the method code. 
The order in which the modifiers are placed in the declaration of a variable are, by convention:
The form of a complete variabledeclaration is therefore as follows:
The following statement declares three interger variables x, y, z:
private static final int x, y, z;
A variable can be declared anywhere in a Java source file. It takes effect from the point at which it is declared to the end of the 'namespace' within which it was declared.
function( ) { }
A namespace is the space between the braces {} of a source block. This is deemed to include the space between the brackets ( ) of the function to which the source block pertains where present. Here, the term function is used as a generic term for method, constructor, exception handler etc..
An array is declared and created as follows:
int[] a; /* declares a reference 'a' to an interger array of unspecified dimension */ a = new int[3]; /* creates an array object with 3 interger elements */
The declaration and creation can be combined as follows:
This creates an array of integers as follows:
A different size of interger array object can be assigned to the array reference 'a' at any time as follows:
a = new int[256];
Java's builtin automatic garbage collection service gets rid of the old dereferenced 3element array.
The size or length of the object currently referenced by reference variable 'a' is always available in the length variable a.length
. This is illustrated in the program below which prints out the contents of the array.
for(int i = 0; i < a.length; i++) System.out.println(i + ": " + a[i]);
Arrays can contain objects other than Java's primitive types like int, float
etc. For instance, you can create an array of objects of a class called X
as follows:
X[] a = new X[32];
Suppose that X
is a name and address class containing a person's name, job title, company, premises name, street name, town, county, postcode. Now suppose that Class Y extends X to define a Contact Record class which includes all of the above plus phone and fax numbers, Email address and Web Site. You can create an array of objects of Class Y as follows:
Y[] b = new Y[1024];
Each element of b[]
contains everything that each element of a[]
contains and more. The X
fields of each element of an array of Y
objects can therefore be processed by any method()
which has been designed to process arrays of pure X
objects. Therefore a reference to a Y
object can be used anywhere that a reference to an X
object can be used.
The sense in which an array is an object is limited in that an array cannot itself be extended. You can only extend objects which can later become elements of an array of the extended objects. For example, to create an array of actual objects of type X
, you have to proceed as follows:
X[] x = new X[12]; /*create a 12element array of pointers to objects of Class X. The elements of this array initially contain null pointers. */ for(int i = 0; i < x.length; i++) x[i] = new X(names[i], jobtits[i], ... );
Each pass of the for
loop creates an object of Class X which becomes an element of the array x[]
. During this process, the address of each new object is put in the i^{th}
element of the array of references (pointers) x[]
.
Only singledimensional arrays of primitive types or objects exist in Java. Multidimensional arrays are effected by creating arrays of pointers to sets of singledimensional arrays. For example, to declare a 4 x 5 array of float
variables, m
, you write:
float[][] m = new float[4][]; for(int i = 0; i < m.length; i++) m[i] = new float[5];
The first statement generates a 4element array of pointers to floats
whose elements are all initialised to null
. Each pass of the for
loop then generates a 5element array of floats
, the start address of which is placed in the appropriate element of the pointer array created earlier. The structure thus generated is shown below:
It is not necessary that all the arrays of floats
be the same length. You can for example create a 2dimensional array of objects whose rows are of different lengths. To print out the elements of the above array write:
for(int i = 0; i < m.length; i++) { for(int j = 0; j < m[i].length; j++) System.out.print(m[i][j] + " "); System.out.println(); }
A variable can be initialised in its declaration statement: eg.
final double p = 3.14159d float r = 1.0f
Variables which are fields of a class are automatically initialised to default values as follows:
boolean:  false
 

char:  'u0000'
 
interger (byte, short, int, long):  0
 
floatingpoint (float, double):  +0.0f, +0.0d
 
object reference:  null

However, Java doesn't initialise the local variables in a block to the above defaults. You must initialise them explicitly. Local variables are initialised each time their declarations are executed. Object fields and array elements are initialised when they are created with a new
. All static
variables within the bounds of a class are initialised before any code in that class is run.
To declare and initialise a string array you can write for example:
String[] d = new String[3]; d[0] = "Lions"; d[1] = "Tigers"; d[2] = "Bears";
But this can be shorthanded to:
String[] d = {"Lions", "Tigers", "Bears"};
To initialise a 4 x 4 matrix of doubles using this shorthand form, write:
double[][] m = { {1.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 1.0} };
postfix operators:  x[] x. (x,y,z) x++ x−−  
prefix operators:  ++x −−x +x −x ~x [bitwise NOT] !x  
creation operator:  new x  
cast operator:  (type)x 
multiplicative operators:  * / %  

additive operators:  + −  
shift operators:  << >> >>> [unsigned rightshift]  
relational operators:  < > >= <= instanceof  
equality operators:  == !=  
bitwise AND:  &  
bitwise exclusive OR:  ^  
bitwise inclusive OR:    
logical AND:  &&  
logical OR:    
conditional operators:  ? : 
= += −= *= /= %= >>= <<= &= ^= =
Use parentheses to override precedence where necessary eg:
while((v = stream.next()) != null) process(v);
Expressions are evaluated strictly lefttoright. For example, x + y + z
is evaluated in the following order.
This order of evaluation is guaranteed. This can matter when the operands are results returned by embedded function calls.
The type of the result of an expression evaluation is determined as follows:
int + int = int int + long = long float + int = float float + long = float float + float = float float + double = double
where +
represents any arithmetic or bitwise operator.
string + any type = string string += any type = string
Any interger type less than 32 bits long is promoted to a 32bit int
before it takes part in the evaluation of an expression as follows:
byte: top 24 bits filled with the value of the sign bit short: top 16 bits filled with the value of the sign bit char: top 16 bits set to zero
int x = 5; //x is a 32bit interger int y = 40; //y is another 32bit interger long z = x + y; //z is a 64bit interger
Implicit type conversions take place automatically in the third line above as illustrated below:
long z = (long)x + (long)y; float x = 29.5; //x is a 32bit IEEE floating point value float y = .00037; //y is a 32bit IEEE floating point value double z = x + y; //z is a 64bit IEEE floating point value
Implicit type conversions take place automatically in the third line above as illustrated below:
double z = (double)x + (double)y; long x = 0x7effffffffffffffL; //x has 64bit precision float y = x; /* but y's mantissa has only 24bit precision */
y
can accommodate the range, but not the precision of x
. Some of x
's 64bit precision therefore is lost when its value is assigned to y
.
double x = 7.99; //48bit mantissa + 16bit exponent long y = (long)x; //cast to a 64bit interger
Although it can accommodate greater precision, y
holds only the truncated value of x
, namely 7. That is why this conversion is not automatically allowed, but must be explicitly written into the code.
double x = BigNum; /* double has a greater range and precision than float */ float y = (float)x; /* so this conversion must be forced explicitly */
Can result in a serious loss of both range and precision if you aren't careful.
long x = 0x0f0fffff; //a long whose lower 16 bits are all set char y = (char)x; //lower 16bits only used so y = \uffff short c = (short)y; //same length but the value in c = 1 int z = (int)y; //top 16 bits filled with zeros z = 65535
An object reference (what most of us know as a pointer) can be converted to refer to different types of object.
Obgekt p = null; ExtendedObgekt q = p; //this assignment conversion is implicit ExtendedObgekt p = null; Obgekt q = (Obgekt)p; //but this conversion must be explicit
However, the above can be forced by explicitly typecasting the extended object as an object, for example:
teeshirt p = TeeShirts[x]; clothing q = (clothing)p;
This is valid when you want to perform a function on a teeshirt object which could be equally well performed on an item of clothing of any kind, such as reading its washing label viz:
ReadWashingLabel(q = (clothing)p);
where the above is a method within the Class Clothing{ }
of which the Class TeeShirt{ }
is an extension.
To test whether teeshirt is an extension of clothing, thus avoiding a possible error use the test:
if(teeshirt instanceof clothing) q = (clothing)p;
long x = 23.789; string y = "Output Value = " + x;
This is interpreted as:
string y = "Output Value = " + toString(long x);
A toString()
method is defined for all primitive types and one can be written into the class code for any object.
Members (or elements) of an array are accessed by using the []
operator. The following accesses the i
^{th} member of the interger array X
:
int x = X[i];
Members (fields) of objects are accessed using the .
operator as follows:
int lat = NavStn.lat; //access latitude of a navigation station int lng = NavStn.lng; //access its longitude also
where NavStn
is an object reference pointing to an instance of the class of objects called NavStns{ }
.
Members of the class itself — i.e. fields which pertain to the class as a whole rather than to individual objects of that class — are accessed in the same way. But, this time you use the class name instead of an object reference:
int NumStns = NavStns.NumStns; /*access the number of navigation stations currently on file */
Methods are also members of classes. Consequently they are accessed in the same way. The following example finds a station's current bearing:
int brg = NavStns.GetBrg(lat, lng);
Exceptions: If you access an object or array with a reference whose value happens to be null
, then a NullPointerException
is thrown. If you specify an array element number which is out of range (e.g. you ask for the 23rd element of an array which has only 16 elements), then an IndexOutOfBoundException
is thrown. Java omits this check if at compile time it can be determined that the index cannot ever go out of range (e.g. in a loop of defined limits).
A chocolate cake is a specific kind of cake. A cake is a specific kind of dessert. A buttered scone is a specific kind of scone. A scone is a specific kind of dessert.
Suppose we have three methods all with the same name and each with the same number of parameters. However, the parameters are of different object types:
 void arrange(Dessert d, Scone s);
 void arrange(Cake c, Dessert d);
 void arrange(ChocolateCake cc, Scone s);
Which version of the method will the following statements invoke?
arrange(dessertRef, sconeRef);
It invokes No 1 because the parameter types are an exact match.
arrange(chocolateCakeRef, dessertRef);
This invokes No 3 because chocolate cake is a more specific form of cake and scone is a more specific kind of dessert.
arrange(chocolateCakeRef, butteredSconeRef);
This invokes No 3 because chocolate is an exact match and buttered scone is a more specific type of scone.
arrange(cakeRef, sconeRef);
This would tend to invoke Nos 1 and 2 equally and therefore cannot invoke either. It is an invalid invocation.
The same rules apply to primitive types. E.g. an int
is assignable to a float
just as a buttered scone is assignable to a scone. But if you declare two methods which both compute the distance to a navigation station:
int dist(int lat, int lng){ } short dist(int lat, int lng){ }
and then you invoke one of them by the statement:
double d = dist(lat, lng);
the compiler has no way of knowing which one to invoke here — even if the two methods throw different exceptions.
The moral is that when in doubt use the method's complete class reference.
0111  +7  
0110  +6  
0101  +5  
0100  +4  
0011  +3  
0010  +2  
0001  +1  
0000  +0  
1111  −1  
1110  −2  
1101  −3  
1100  −4  
1011  −5  
1010  −6  
1001  −7  
1000  −8 
int
and long
) cannot overflow or underflow: it simply wraps round and comes full circle.
The figures at the left illustrate the principle of two's complement arithmetic on which all interger arithmetic in JAVA is based.
Notice how the bits change around zero. Minus 1 is all bits set, zero is no bits set, plus 1 is the least significant bit set. Notice too that two's complement arithmetic wraps round from + 7 to −8! One more numerically.
The full range of values is shown for only a 4bit two's complement register so that the full range can be illustrated in half a page.
To convert a negative number to its positive equivalent and vice versa, invert all the bits then add 1.
Java's int
is a 32bit register. Its critical wrapping at
zero and at its numerical maxima are shown below.
Around zero it behaves as follows:
00000000000000000000000000000010 +2 00000000000000000000000000000001 +1 00000000000000000000000000000000 +0 11111111111111111111111111111111 1 11111111111111111111111111111110 2Around its maximum values it behaves as follows:
10000000000000000000000000000010 4294967294 10000000000000000000000000000001 4294967295 10000000000000000000000000000000 4294967296 01111111111111111111111111111111 +4294967295 01111111111111111111111111111110 +4294967294
A short
(16bit), int
(32bit), and long
(64bit) arithmetic all follow the same rules. Arithmetic performed on a char
(16bit Unicode) converts implicitly to int
before applying the actual arithmetic operations.
The arithmetic operations which can be performed on integers are:
x + y  add x to y (always wraps)
 
x  y  subtract y from x
 
x * y  multiply x by y
 
x / y  divide x by y
 
x % y  gives the remainder when x is divided by y

The action of the remainder operator is to repeatedly subtract y from x until it cannot get a complete y. It then returns what is left. Eg: 15 % 4 works out as:
15  4 = 11 11  4 = 7 7  4 = 3 3  4 cannot go so it returns 3 as the answer.
The remainder function is defined formally by the identity:
( x / y ) * y + x % y == x
Interger multiplication wraps. Interger division truncates towards zero: eg:
+7 / 2 = +3 and 7 / 2 = 3
x / 0
and x % 0
are invalid and throw an ArithmeticException
.
Java arithmetic also supports the 'minus' unary operator to negate the value to which it is applied e.g. 3
For symmetry it also supports the unary 'plus' operator e.g. +3
An IEEE 7541985 subset:
Underflows to zero:  +0 −0  if decrementing to zero from the positive side if incrementing to zero from the negative side  

Overflows to infinity:  +∞ −∞ 
if incrementing upwards to infinity if decrementing downwards to minusinfinity 
You can initialise a variable to infinity for example:
float x = float.NEGATIVE_INFINITY;initialises the IEEE 32bit floatingpoint variable
x
to minusinfinity.
A Java floatingpoint variable can also hold a value called NaN
which stands for 'not a number'. It results when the outcome of a floatingpoint arithmetic operation is what mathematicians call 'indeterminate'. The behaviour of Java's floatingpoint arithmetic in operations involving signed zeros and infinities is illustrated by the following identities:
+∞ + +∞ ≡ ∞  +∞ − +∞ ≡ NaN  

−∞ + −∞ ≡ −∞  −∞ − −∞ ≡ NaN  
+∞ + −∞ ≡ NaN  +∞ − −∞ ≡ ∞  
x ÷ ±0 ≡ ±∞  x % 0 ≡ NaN  
x ÷ ±∞ ≡ ±0  x % ±∞ ≡ x  
0 ÷ 0 ≡ NaN  0 % 0 ≡ NaN  
±∞ ÷ x ≡ ±∞  ±∞ % x ≡ NaN  
±∞ ÷ ±∞ ≡ NaN  ±∞ % ±∞ ≡ NaN 
Java floatingpoint arithmetic does not throw exceptions like invalid operations, division by zero, overflow, underflow or inexact. Nor does it signal the occurrence of a NaN
result. It just carries on by rounding results of operations towards zero or the nearest representable value, preferring values with the leastsignificant bit set to zero.
Also, you cannot use things like <=
or >=
in Java floating point. E.g. you must use if(!(x < y))
instead of if(x >= y)
.
The statements i++;
and ++i;
both increase the value of i
by 1
.
The statements i;
and i;
both decrease the value of i
by 1
.
Therefore both i++;
and ++i;
are equivalent to i = i + 1;
and both i;
and i;
are equivalent to i = i  1;
However there is a difference:
x = a[++i];
is equivalent to i = i + 1; x = a[i];
is equivalent to
x = a[i++];x = a[i]; i = i + 1;
If instead of incrementing the index of an array, we increment the contents of one of its elements, then both a[i]++;
and ++a[i]
are equivalent to a[i] = a[i] + 1;
and a[i];
and a[i]
are equivalent to a[i] = a[i]  1;
However, if i
is obtained from a method m( ) which returns a different value each time it is called as in a[m(i)]++;
, then a[m(i)]++;
is not equivalent to a[m(i)] = a[m(i)] + 1;
and a[m(i)];
is not equivalent to a[m(i)] = a[m(i)]  1;
The statement a[m(i)]++;
increments a particular element of a[]
while the statement a[m(i)] = a[m(i)] + 1;
sets the value of one element of a[]
to one more than the value of some other element of a[]
.
Illustration of the effects of ++i
and i++
:
class IncOrder { public static void main( String[] args ) { int i = 16; System.out.print(++i + " " + i++ + " " + i); } }
Output is 17 17 18
.
These operators return a boolean result true
or false
.
>  greater than  

<  less than  
>=  greater than or equal to  
<=  less than or equal to  
==  equal to  
!=  not equal to 
Only the last two can be used in expressions relating boolean variables. The prefix operator ! means 'not'. It inverts the boolean result of what immediately follows it.
These operators return a boolean value indicating whether a particular relationship between two variables is true
or false
.
For example, in the test: if(x < y)
Java evaluates the expression x < y
as a behindthescenes boolean variable b
whose value is either true
or false
. It then uses the value of b
in the implied statement if(b == true)
to determine which route to take.
Test boolean values directly:
If x
and y
are boolean variables, use a test of the form: if(x  !y ){ ... }
instead of: if(x == true  y == false){ ... }
Single expressions which evaluate to a boolean value can be joined to form a composite expression using: && (conditional AND) and  (conditional OR). For example:
if( x && y ) { ... }
Java evaluates as little as it has to in order to obtain a valid result. For instance, in
if(i >= 0 && i < a.length && a[i] != 0){ ... }
if i
is negative, the other two expressions are not evaluated.
Because ==
and !=
can only relate boolean values, they can be used to construct an exclusive OR or XOR test as follows:
if(x < 0 == y < 0) SameSign(); else DiffSign();
x != NaN
always returns true
x # NaN
always returns false
where #
is any relational operator other than !=
.
If s1
and s2
are string pointers, the expression s1 == s2
is true only if s1
and s2
point to the same string array: it does not test to see if two different string arrays have the same content.
&  bitwise AND  

  bitwise OR  
^  bitwise exclusive OR ie XOR  
~  bitwise inverter, eg ~1101 becomes 0010 
<<  Shift left (shifting zero bits in from the right)  

>>  Shift right (shifting with sign bits in from the left)  
>>>  Shift right (shifting zero bits in from the left) 
1101  <<  2 becomes 0100  
1101  >>  2 becomes 1111  

1101  >>>  2 becomes 0011 
The number of bitplaces shifted (the right operand) is the number you provide masked by (the size of the type of the lefthand operand)  1. So if the lefthand operand is a 32bit int
, the mask is 31
so a shift of  +35  00000000000000000000000000100011  

or a shift of  −29  11111111111111111111111111100011  
masked by  31  00000000000000000000000000011111  
both yield  +3  00000000000000000000000000000011 
Bitwise operators &
and 
can be used on boolean variables in place of &&
and 
. However unlike &&
and 
, &
and 
always evaluate both operands before returning their result — so beware.
A converse logical XOR test can be constructed using the bitwise XOR operator ^
which returns a true
if the expressions evaluate to opposite boolean states and false
if to the same boolean state as in:
if((x < 0)^(y < 0)) DiffSign(); else SameSign();
value = UserSetIt ? UsersValue : DefaultValue;
is equivalent to:
if(UserSetIt) value = UsersValue; else value = DefaultValue;Consider the types of the variables involved.
double scale = halveIt ? 1 : 0.5;
The types of the second and third operands must be the same as, or assignable to, the type of the value (i.e. the left side of the = sign).
The most basic assignment operator is '='.
However, in Java, any arithmetic or bitwise operator can be joined to '=' to form a composite assignment operator. For example:
a[func()] += 1; is equivalent to a[func()] = a[func()] + 1;
However, in the first case, func() is called only once. Since it may return a new value when called a second time, we cannot be sure whether or not it is the same array element that is being referred on both the left and right hand sides of the '=' sign. The composite '+=' operator is therefore clearer and more predictable in operation when a function is used as an array indexer.
If var
is a variable of type Type
, then
var op= expr
is equivalent to var = (Type)((var) op (expr))
Note that the whole of expr
is bound tightly. For example:
a *= b + 1; is equivalent to a = a * (b + 1); not a = a * b + 1;
Although a += 1;
is the same as ++a;
the ++
is traditionally the preferred coding.
A statement:  assignment;  
A block:  {assignment; assignment; ... } 
if(boolean condition) statement; or {block} else //an 'else' is always associated with the most recent 'if' statement; or {block} switch x { case A: statement; or {block} //fall through case B: statement; or {block} //fall through case C: statement; or {block} break; //skip default default: statement; or {block} } while(condition) statement; or {block} do statement; or {block} while(condition) for(initializers; condition; incrementers) statement; or {block} label: statement; or {block}
break;  exit the innermost block in which it occurs  

break label;  exit the labelled block called 'label'  
continue;  immediately start the next pass of the innermost loop  
continue label;  immediately start the next pass of the labelled loop  
return;  return from the current method to its caller  
return(x);  return from the current method, passing the value of x to its caller. The 'type' of 'x' must be the return type declared for this method.

NOTE: There's no 'goto' statement in Java because 'break' and 'continue' can express more formally what 'goto' is used for in other languages.