Java Online Tutorial
BASIC SYNTAX AND FUNDAMENTAL CONCEPTS - Part I
The material presented in this chapter often will cover
an entire book (no kidding !) and has been condensed
here but the subjects have lost none of their clarity
or their wholeness. This chapter also covers a portion
commonly encountered during the Sun Java Certification
Exam or Sun Certified Java Professional Exam (SCJP -
310 025) and must be covered before embarking on any
expedition in programming in java. Much of the java
syntax and therefore concepts are borrowed heavily from
C++ and this chapter will be familiar to C++ programmers
but for budding java programmers this chapter contains
all the essential know-how which should precede any
programming activity. Lastly, I would like to mention
that this whole tutorial (including this chapter) was
developed for the programmer who has absolutely no
programming knowledge whatsoever.
LANGUAGE FUNDAMENTALS
OPERATORS AND ASSIGNMENTS
LANGUAGE FUNDAMENTALS
Keywords and
identifiers
For a list of the keywords and reserved words you can
look up any java book, so I will not mention them here.
Suffice to know that public, static, protected, catch,
throw and finally are some of them. An identifier
is a word used by programmers to name a variable, method,
class or label. Keywords and reserved words may not
be used as identifiers. An identifier must begin with
a letter, a dollar sign ($), or an underscore (_). Subsequent
characters may be letters, dollar signs, underscores
or digits. Identifiers may not begin with a digit. Some
examples are
|
foobar
|
//legal
|
|
BIGinterface
|
//legal: embedded keywords are OK
|
|
$incomeAfterExpenses
|
//legal
|
|
8moves
|
//illegal: starts with a digit
|
|
&start
|
//illegal: must start with letter, $ or
_
|
Identifiers are case sensitive. For example,
radius and Radius
are two distinct identifiers.
Back to TOP
Primitive Data Types
Java's primitive data types are
- boolean
- char
- byte
- short
- int
- long
- float
- double
The sizes of these types are listed below.
|
Type
|
Representation Size (bits)
|
Minimum
|
Maximum
|
|
boolean
|
1
|
Can be only true or false
|
|
char
|
16
|
Unsigned type in range 0 to 216-1
|
|
byte
|
8
|
-2 7
|
27 - 1
|
|
short
|
16
|
-215
|
215-1
|
|
int
|
32
|
-231
|
231-1
|
|
long
|
64
|
-263
|
263-1
|
|
float
|
32
|
See the jdk docs for this one
|
|
double
|
64
|
See the jdk docs for this one
|
Back
to TOP
Arrays
A Java array is an ordered collection of primitives,
object references or other arrays. Java arrays are homogeneous:
except as allowed by polymorphism, all elements of an
array must be of the same type. That is, when you create
an array you specify the element type, and the resulting
array can contain only elements that are instances of
that class or sub-classes of that class. To create and
use an array, you must follow three steps:
- Declaration
- Construction
- Initialization
Declaration tells the compiler what the array's name
is and what the type of its elements will be. For example
- int ints[];
- double dubs[];
- Dimension dims[];
- float twoD[] [];
The square brackets can come before or after the array
name.
int ints[]
is the same as
int [] ints
Notice that the declaration does not specify
the size of the array. Size is specified at runtime,
when the array is allocated via the new keyword. For
example
int ints[]; // Declaration to the compiler
ints=new int[25]; // Run time construction
Since array size is not used until runtime, it is legal
to specify size with a variable rather than a literal:
int size= 110 *500
int blocks[];
blocks = new int[size];
Declaration and construction may be performed in a
single line:
int ints[] = new int[25];
When an array is constructed, its elements are automatically
initialized exactly as for object member variables.
Numerical elements are initialized to zero; non-numerical
elements are initialized to values similar to zero,
as shown below.
|
ElementType
|
Initial value
|
ElementType
|
InitialValue
|
|
byte
|
0
|
short
|
0
|
|
int
|
0
|
long
|
0L
|
|
float
|
0.0f
|
double
|
0.0d
|
|
char
|
'\u0000'
|
boolean
|
false
|
|
object reference
|
null
|
If you want to initialize an array to values other
than those shown in the above table, you can combine
declaration, construction and initialization into a
single step. For example
float sizes[] = {1.2f, 2.4f, 3.6f, 4.8f, 6.0f};
The array size is inferred from the number of elements
within the curly braces. Of course, an array can also
be initialized by explicitly assigning a value to each
element like this
long square[];
square = new Long[100];
for (int i=0; i<square.length; i++)
square[i] = i*i;
Note: Java indexes always start from 0.
Back
to TOP
The table below shows us the operators available in
Java.
|
Unary
|
++ -- +
- ! ~
()
|
|
Arithmetic
|
* / %
+ -
|
|
Shift
|
<< >>
>>>
|
|
Comparison
|
== !=
|
|
Bitwise
|
& ^ |
|
|
Short-circuit
|
&& ||
|
|
Ternary
|
?:
|
|
Assignment
|
= "op="
|
Back
to TOP
Unary Operators
Most operators take two operands. When you multiply,
for example, you work with two numbers. Unary operators
take only a single operand.
The unary + and - are simple enough to understand,
but ++ and -- often leads to great confusion.
See the following case-study
|
Initial Value of x
|
Expression
|
Final value of y
|
Final Value of x
|
|
5
|
y = x++
|
5
|
6
|
|
5
|
y = ++x
|
6
|
6
|
|
5
|
y = x--
|
5
|
4
|
|
5
|
y = --x
|
4
|
4
|
Back
to TOP
The Bitwise
Inversion Operator : ~
The ~ operator performs bitwise inversion on
integral types.
For example, applying this operator to a byte containing
00111100 would result in the value 11000011. The same
simple logic applies no matter how many bits are there
in the value being operated upon.
Back
to TOP
The Boolean
Complement Operator : !
The ! operator inverts the value of a boolean expression.
So !true gives false and !false gives true.
This operator is often used in the test part of an
if() statement.
Back
to TOP
The Cast Operator
: (type)
Casting is used for explicit conversion of the type
of an expression. There are rules governing such conversion
and for a discussion of these I would leave you to peruse
more detailed journals than this one. For now, suffice
to know that casts can be applied to change to type
of primitive values, for example, forcing a double into
an int like this.
int circumference = (int)(Math.PI * diameter);
Here the compiler would reject the above assignment
without the explicit cast to (int) because a double
value as returned by the arithmetic here cannot be represented
accurately by an int variable.
The cast is the programmer's way to say to the compiler,
"I know this is risky, but trust me - I'm a programmer."
Of course, if the result loses value or precision to
the extent that the program does not work properly,
then you are on your own.
Casts can also be applied to object references. This
often happens when you use containers such as the Vector
object. If you put, for example, String objects into
a Vector, then when you can extract them, the return
type of the elementAt() method is simply Object. To
use the recovered value as String reference, a cast
is needed, like this:
Vector v = new Vector();
v.addElement("Hello");
String s = (String)v.elementAt(0);
Back
to TOP
Arithmetic operators
Multiplication and division are fairly familiar operations
and for that reason they will not be covered here. However,
one point to note is that integer division by zero throws
an ArithmeticException but float and double division
by zero do not.
The less well-known modulo operator is discussed
in the next section.
Addition and subtraction (+/-), although basically
familiar, the + operator has some capabilities beyond
simple addition, so they will be discussed here.
Back
to TOP
The Modulo Operator
The modulo operator gives the value which is related
to the remainder of a division. It is generally applied
to two integers, although it can be applied to floating
point numbers too. In school, we learnt that 7 divided
by 4 gives 1 remainder 3. In Java, we say x = 7 % 3;
and expect x will have the value 3.
Some more examples.
17 % 5:
5*3 is 15, remainder 2
So 17 % 5 is 2
----------------------
-5 % 2:
2 * (-2) is -4, remainder -1
So -5 % 2 is -1
----------------------
7.6 % 2.9
2.9 * 2 is 5.8, remainder 1.8
so 7.6 % 2.9 is 1.8
Back
to TOP
The + operator
in Detail
Where either of the operands of a + expression is a
String object, the meaning of the + operator is changed
from numeric addition to concatenation of text. In order
to achieve this, both operands must be handled as text.
If both operands are in fact String objects, this is
simple. If, however, one of the operands is not a String
object, then the non-string operand is converted to
a String object before the concatenation of text takes
place.
For example.
5 + 6 = 11;
5 + "this" = "5this";
"this" + "and" + "that" = "thisandthat";
5 + "6" = 56;
Back
to TOP
The Shift Operators:
<<, >>, and >>>
Shifting is, on the face of it, a simple operation.
It involves taking the binary representation of a number
and moving the bit pattern left or right.
The shift operators may be applied to arguments of
integral types only. In fact they should generally be
applied only to operands of either int or long type.
See the next section on "Arithmetic promotion of
Operands" following this discussion.
Some examples.
7 << 2
= 0111 << 2
= 1100
= 12
----------------
7 >> 1
= 0111 >> 1
= 0011
= 3
----------------
-6 >> 1
= 1010 >> 1
= 1101
= -3
----------------
-5 << 2
= 1011 << 2
= 1100
= -4
Note A In the case of right shift
of negative numbers bits which move in from the left
edge will contain 1's, in all other cases, 0's will
be propagated. Typically the result will contain the
same number of bits as in the original expression. Bits
which move off either end are discarded.
Note B When positive numbers are
shifted left one bit, the effect is that of multiplying
the number by two, provided none of the bits fall off
the end. Similarly right shifting is equivalent to division
by two, provided none of the bits fall off the ends.
Shifting negative numbers, however, yield unpredictable
results.
Back
to TOP
Arithmetic
Promotion of Operands
Arithmetic promotion of operands takes place before
any binary operator is applied so that all numeric operands
are at least int type. This has an important consequence
for the unsigned right-shift operator when applied to
values that are narrower than int.
This example shows the process by which a byte is shifted
right. First the byte is promoted to an int, which is
done by treating the byte as a signed quantity. Next,
the shift occurs, and zero bits are indeed propagated
into the top bits of the result - but these bits are
not part of the original byte. When the result is cast
down to a byte again, the high-order bits of that byte
appear to have been created by a signed right shift,
rather than an unsigned one. This is why you should
generally not use the logical right-shift operator with
operands smaller than an int. It is unlikely to produce
the result you expect.
CALCULATION FOR -64 >>> 4
Original data (-64 decimal) 11000000
promote to int gives: |11111111|11111111|11111111|11000000
Unsigned right shift gives: |00001111|11111111|11111111|11111100
Truncate to byte gives: | | | |11111100
Expected result was: | | | |00001100
Back
to TOP
The Comparison
Operators
Comparison operators all return a boolean
result, i.e either true or false.
For example, given these declarations,
int p = 9;
int q = 65;
int r = -12;
float f = 9.0f;
char c = 'A';
the following tests all return true.
p < q
f < q
f <= c
c > r
c >= r
Notice that
arithmetic promotions are applied when these operators
are used. For example, although it is an error to
attempt to assign a float value of 9.0f to a char
variable c, it is perfectly legal to compare the two.
To achieve the result, Java promotes the smaller type
to the larger type, hence the char value 'A' (represented
by Unicode value 65) is promoted to a float 65.0f.
The comparison is then performed on the resulting
float values.
Although
the >, <, >=, and <= operators operate
satisfactorily on dissimilar numeric types, including
char, they are not applicable to any non-numeric types.
They cannot take boolean or any class-type operands.
Note The
char type is actually a 16 bit unsigned int type.
Back
to TOP
The instanceof
Operator
The instanceof operator tests the class of an object at runtime. The
left-hand argument can be any object reference expression,
usually a variable or an array element, while the right-hand
operand must be a class, interface or array type. However,
you cannot use a java.lang.Class object or its string
name as the right-hand operand.
public class Classroom {
public Hashtable inTheRoom = new Hashtable();
public void enterRoom(Person p) {
inTheRoom.put(p.getName(), p);
}
public Person getParent(String name) {
Object p = inTheRoom.get(name);
if (p instanceof Parent) {
return (Parent)p;
}
else {
return null;
}
}
}
The instanceof operator returns
true if the class of the left-hand argument is the same as, or is some
subclass of, the class specified by the right-hand operand.
The right-hand operand may well
be an interface. In such a case, the test determines if the object at the
left-hand argument implements the specified interface.
You can also use the instanceof
operator to test if a reference refers to an array. The test for an array
type looks like this:
if (x instanceof Component[])
Since an array of Button
objects is also an array of Component objects, the above holds true if x
is an array of Button objects. However, the following is not legal.
if (x instanceof [])
If the left-hand argument is a
null value, the instanceof test simply returns false - it does not cause
an exception.
Back
to TOP
The
Equality Comparison Operators: == and !=
The operators == and != test for equality and non-equality respectively,
returning a boolean value. For primitive types, the
concept of equality is simple enough and is subject
to promotion rules so that, for example, a float value
10.0f is equal to a byte value of 10.
However, for variables of object type, the "value"
is taken as a reference to the object; typically this
is the memory address. You should not use these operators
to compare the contents of objects, such as strings,
because they will return true if two references refer
to the same object, rather than if if the two objects
have an equivalent meaning.
To achieve a content or semantic comparison, for example, so that
two different String objects containing the text "hello"
are considered equal, you must use the equals()
method rather than the == or != operators.
Back
to TOP
The Bitwise Operators:
&, ^, and |
The bitwise operators &, ^ and | provide bitwise AND, X-OR and
OR operations respectively. They can also operate on
boolean values and the rules for these are the same
as bitwise operations. Since they are relatively straight
forward, they will not be discussed here.
Back
to TOP
The
Short Circuit Logical Operators: || and &&
The short circuit logical operators && and || provide logical AND and OR operations on
boolean types. They cannot be applied to integral types. The main points
about them, which include an ability to "short-circuit" a
calculation if the result is definitely known, are summarized below.
- They accept only boolean operands.
- They only evaluate the
right-hand operand if the outcome is not certain based solely on the
left-hand operand.
- For an AND operation, if
one operand is false, the result is false without regard to the
other operand.
- For an OR operation, if
one operand is true, the result is true, without regard to the
other operand.
Back
to TOP
The Ternary Operator:
?
The ternary or conditional operator ?: provides a way to code simple conditions (if/else) into a
single expression. The (boolean) expression left of the ? is evaluated. If
true, the result of the whole expression is the value of the
sub-expression to the left of the colon; otherwise it is the value of the
sub-expression to the right of the colon. The sub-expressions on either
side of the colon must have the same type.
For example, if a, b, and c are int variables, and x is a boolean, then
the statement a = x? b : c; is directly equivalent to
the longer version:
if (x) {
a = b;
}
else {
a = c;
}
To use this operator properly,
we need to remember the following points:
- The types of the expressions
b and c should be compatible and are made identical through
conversion.
- The type of the expression x should be boolean.
- The type of the expressions
b and c should be assignment compatible with the type of a.
- The value assigned to a will
be b if x is true or will be c if x is false.
Back
to TOP
The Assignment
Operators: = and op=
The key points about the assignment operators are:
- Simple assignment, using =, assigns the value of the right-hand operand to the left-hand operand.
- The value of an object is its reference, not its contents.
- The right-hand operand must be a type that is assignment compatible with the left-hand operand.
- The assignment operators all
return a value, so that they can be used within larger expressions.
The value returned is the value that was assigned to the left-hand
operand.
- The compound assignment
operators, of the form op=, when applied in an expression like a op=
b; appear to behave like a = a op b; except that the expression a, and
any of its side-effects, is evaluated only once.
Compound assignment operators exist for all binary non-boolean operators:
*=, /=, %=, +=, -=, <<=, >>=, >>>=,
&=, ^=, and |=.
Back
to TOP
Now on to the next chapter Basic
Syntax and Language Fundamentals - Part II
All questions and comments can be addressed to the
author.
All material appearing within this website is copyright
protected and may not be reproduced elsewhere without
the express written permission of the author (Sanjeev
Dasgupta)
|