Java Basics - Java Programming Tutorial PDF
Java Basics - Java Programming Tutorial PDF
| HOME
Below is a simple Java program that demonstrates the three basic programming constructs: sequential, loop, and conditional. Read "Introduction To Java
Programming for Firsttime Programmers" if you need help in understanding this program.
1 /*
2 *Sumtheoddnumbersandtheevennumbersfromalowerboundtoanupperbound
3 */
4 publicclassOddEvenSum{//Saveas"OddEvenSum.java"
5 publicstaticvoidmain(String[]args){
6 intlowerbound=1,upperbound=1000;
7 intsumOdd=0;//Foraccumulatingoddnumbers,initto0
8 intsumEven=0;//Foraccumulatingevennumbers,initto0
9 intnumber=lowerbound;
10 while(number<=upperbound){
11 if(number%2==0){//Even
12 sumEven+=number;//SameassumEven=sumEven+number
13 }else{//Odd
14 sumOdd+=number;//SameassumOdd=sumOdd+number
15 }
16 ++number;//Nextnumber
17 }
18 //Printtheresult
19 System.out.println("Thesumofoddnumbersfrom"+lowerbound+"to"+upperbound+"is"+sumOdd);
20 System.out.println("Thesumofevennumbersfrom"+lowerbound+"to"+upperbound+"is"+sumEven);
21 System.out.println("Thedifferencebetweenthetwosumsis"+(sumOddsumEven));
22 }
23 }
Thesumofoddnumbersfrom1to1000is250000
Thesumofevennumbersfrom1to1000is250500
Thedifferencebetweenthetwosumsis500
1.2Comments
Comments are used to document and explain your codes and your program logic. Comments are not programming statements. They are ignored by the compiler
and have no consequences to the program execution. Nevertheless, comments are VERY IMPORTANT for providing documentation and explanation for others to
understand your programs and also for yourself three days later.
I recommend that you use comments liberally to explain and document your codes. During program development, instead of deleting a chunk of statements
irrevocably, you could commentout these statements so that you could get them back later, if needed.
For examples,
//Eachofthefollowinglinesisaprogrammingstatement,whichendswithasemicolon(;)
intnumber1=10;
intnumber2,number3=99;
intproduct;
product=number1*number2*number3;
System.out.println("Hello");
Block : A block is a group of statements surrounded by a pair of curly braces {}. All the statements inside the block is treated as one single unit. Blocks are used
as the body in constructs like class, method, ifelse and forloop, which may contain multiple statements but are treated as one unit one body. There is no need to
put a semicolon after the closing brace to end a compound statement. Empty block i.e., no statement inside the braces is permitted. For examples,
//Eachofthefollowingsisa"complex"statementcomprisingoneormoreblocksofstatements.
//Noterminatingsemicolonneededaftertheclosingbracetoendthe"complex"statement.
//Takenotethata"complex"statementisusuallywrittenoverafewlinesforreadability.
if(mark>=50){
System.out.println("PASS");
System.out.println("WellDone!");
System.out.println("KeepitUp!");
}
if(number==88){
System.out.println("Gotit!");
}else{
System.out.println("TryAgain!");
}
i=1;
while(i<8){
System.out.print(i+"");
++i;
}
publicstaticvoidmain(String[]args){
...statements...
}
You need to use a white space to separate two keywords or tokens to avoid ambiguity, e.g.,
intsum=0;//Cannotwriteintsum=0.Needatleastonewhitespacebetween"int"and"sum"
doubleaverage;//Again,needatleastawhitespacebetween"double"and"average"
Additional white spaces and extra lines are, however, ignored, e.g.,
//sameasabove
intsum
=0;
doubleaverage;
Formatting Source Codes : As mentioned, extra white spaces are ignored and have no computational significance. However, proper indentation with tabs
and blanks and extra empty lines greatly improves the readability of the program. This is extremely important for others and yourself three days later to
understand your programs.
For example, the following oneline helloworld program works. But can you read and understand the program?
publicclassHello{publicstaticvoidmain(String[]args){System.out.println("Hello,world!");}}
Braces : Java's convention is to place the beginning brace at the end of the line, and align the ending brace with the start of the statement.
/*
*RecommendedJavaprogrammingstyle
*/
publicclassClassName{//Placethebeginningbraceattheendofthecurrentline
publicstaticvoidmain(String[]args){//Indentthebodybyanextra3or4spacesforeachlevel
//Useemptylineliberallytoimprovereadability
//Sequentialstatements
statement;
statement;
//Conditionalstatement
if(test){
statements;
}else{
statements;
}
//loop
init;
while(test){
statements;
update;
}
}
}//endingbracealignedwiththestartofthestatement
2.Variables and Types
2.1Variables
Computer programs manipulate or process data. A variable is used to store a piece of data for processing. It is called variable because you can change the value
stored.
More precisely, a variable is a named storage location, that stores a value of a particular data type. In other words, a variable has a name, a type and stores a value.
A variable has a name aka identifier, e.g., radius, area, age, and height. The name is needed to uniquely identify each variable, so as to assign a value to the
variable e.g., radius=1.2, as well as to retrieve the value stored e.g., radius*radius*3.1419265.
A variable can store a value of that particular data type. It is important to take note that a variable in most programming languages is associated with a type,
and can only store value of the particular type. For example, a int variable can store an integer value such as 123, but NOT real number such as 12.34, nor
string such as "Hello".
The concept of type was introduced in the early programming languages to simplify interpretation of data made up of binary numbers 0's and 1's. The type
determines the size and layout of the data, the range of its values, and the set of operations that can be applied.
The following diagram illustrates three types of variables: int, double and String. An int variable stores an integer or whole number or fixedpoint number; a
double variable stores a floatingpoint number or real number; a String variable stores texts.
2.2Identifiers or Names
An identifier is needed to name a variable or any other entity such as a method or a class. Java imposes the following rules on identifiers:
An identifier is a sequence of characters, of any length, comprising uppercase and lowercase letters (az,AZ), digits (09), underscore "_", and dollar sign
"$".
White space blank, tab, newline and other special characters such as +, , *, /, @, &, commas, etc. are not allowed. Take note that blank and dash are not
allowed, i.e., "maxvalue" and "maxvalue" are not valid names. This is because blank creates two tokens and dash crashes with minus sign!
An identifier must begin with a letter (az,AZ) or underscore _. It cannot begin with a digit (09) because that could confuse with a number. Identifiers
begin with dollar sign $ are reserved for systemgenerated entities.
An identifier cannot be a reserved keyword or a reserved literal e.g., class, int, double, if, else, for, true, false, null.
Caution : Programmers don't use blank character in names. It is either not supported e.g., in Java and C/C++, or will pose you many more challenges.
Recommendations
1. It is important to choose a name that is selfdescriptive and closely reflects the meaning of the variable, e.g., numberOfStudents or numStudents, but not n
or x, to store the number of students. It is okay to use long names!
2. Do not use meaningless names like a, b, c, d, i, j, k, i1, j99.
3. Avoid singleletter names like i, j, k, a, b, c, which is easier to type but often meaningless. Exception are common names like x, y, z for coordinates, i for
index. Long names are harder to type, but selfdocument your program. I suggest you spend sometimes practicing your typing.
4. Use singular and plural nouns prudently to differentiate between singular and plural variables. For example, you may use the variable row to refer to a single
row number and the variable rows to refer to many rows such as an array of rows to be discussed later.
2.3Variable Declaration
To use a variable in your program, you need to first "introduce" it by declaring its name and type, in one of the following syntaxes. The act of declaring a variable
allocates a storage of size capable of holding a value of the type.
Syntax Example
//Declareavariableofaspecifiedtype
typeidentifier; intoption;
//Declaremultiplevariablesofthesametype,separatedbycommas
typeidentifier1,identifier2,...,identifierN; doublesum,difference,product,quotient;
//Declareavariableandassignaninitialvalue
typeidentifier=initialValue; intmagicNumber=88;
//Declaremultiplevariableswithinitialvalues
typeidentifier1=initValue1,...,identifierN=initValueN; StringgreetingMsg="Hi!",quitMsg="Bye!";
finaldoublePI=3.1415926;//Needtoinitialize
Constant Naming Convention: Use uppercase words, joined with underscore. For example, MIN_VALUE, MAX_SIZE.
2.5Expressions
An expression is a combination of operators such as addition '+', subtraction '', multiplication '*', division '/' and operands variables or literals, that can be
evaluated to yield a single value of a certain type. For example,
1+2*3//evaluatedtoint7
intsum,number;
sum+number//evaluatedtoanintvalue
doubleprincipal,interestRate;
principal*(1+interestRate)//Evaluatedtoadoublevalue
2.6Assignment
An assignment statement:
1. assigns a literal value of the RHS to a variable of the LHS, e.g., x=1; or
2. evaluates an expression of the RHS and assign the resultant value to a variable of the LHS, e.g., x=(y+z)/2.
Syntax Example
//Assigntheliteralvalue(oftheRHS)tothevariable(oftheLHS)
variable=literalValue; number=88;
//Evaluatetheexpression(RHS)andassigntheresulttothevariable(LHS)
variable=expression; sum=sum+number;
The assignment statement should be interpreted this way: The expression on the righthandside RHS is first evaluated to produce a resultant value called rvalue
or rightvalue. The rvalue is then assigned to the variable on the lefthandside LHS or lvalue. Take note that you have to first evaluate the RHS, before
assigning the resultant value to the LHS. For examples,
number=8;//Assignliteralvalueof8tothevariablenumber
number=number+1;//Evaluatetheexpressionofnumber+1,
//andassigntheresultantvaluebacktothevariablenumber
8=number;//INVALID
number+1=sum;//INVALID
In Java, the equal symbol '=' is known as the assignment operator. The meaning of '=' in programming is different from Mathematics. It denotes assignment of
the LHS value to the RHS variable, instead of equality of the RHS and LHS. The RHS shall be a literal value or an expression that evaluates to a value; while the LHS
must be a variable.
Note that x = x + 1 is valid and often used in programming. It evaluates x + 1 and assign the resultant value to the variable x. x = x + 1 illegal in
Mathematics.
While x+y=1 is allowed in Mathematics, it is invalid in programming because the LHS of an assignment statement must be a variable.
Some programming languages use symbol ":=", ">" or "<" as the assignment operator to avoid confusion with equality.
2.7Primitive Types
In Java, there are two broad categories of types: primitive types e.g., int, double and reference types e.g., objects and arrays). We shall describe the primitive
types here and the reference types classes and objects in the later chapters on "ObjectOriented Programming".
TYPE DESCRIPTION
byte Integer 8bit signed integer
The range is [2^7,2^71]=[128,127]
char Character
Represented in 16bit Unicode '\u0000' to '\uFFFF'.
Can be treated as 16bit unsigned integers in the range of [0,65535] in arithmetic operations.
boolean Binary
Takes a value of either true or false.
The size of boolean is not defined in the Java specification, but requires at least one bit.
Java introduces a new binary type called "boolean", which takes a value of either true or false.
Example : The following program can be used to print the maximum, minimum and bitlength of the primitive types. The maximum, minimum and bitsize of int
are kept in constants INTERER.MIN_VALUE, INTEGER.MAX_VALUE, INTEGER.SIZE.
/*
*Printtheminimum,maximumandbitlengthforprimitivetypes
*/
publicclassPrimitiveTypesMinMax{
publicstaticvoidmain(String[]args){
//int(32bitsignedinteger)
System.out.println("int(min)="+Integer.MIN_VALUE);
System.out.println("int(max)="+Integer.MAX_VALUE);
System.out.println("int(bitlength)="+Integer.SIZE);
//byte(8bitsignedinteger)
System.out.println("byte(min)="+Byte.MIN_VALUE);
System.out.println("byte(max)="+Byte.MAX_VALUE);
System.out.println("byte(bitlength)="+Byte.SIZE);
//short(16bitsignedinteger)
System.out.println("short(min)="+Short.MIN_VALUE);
System.out.println("short(max)="+Short.MAX_VALUE);
System.out.println("short(bitlength)="+Short.SIZE);
//long(64bitsignedinteger)
System.out.println("long(min)="+Long.MIN_VALUE);
System.out.println("long(max)="+Long.MAX_VALUE);
System.out.println("long(bitlength)="+Long.SIZE);
//char(16bitcharacteror16bitunsignedinteger)
System.out.println("char(min)="+(int)Character.MIN_VALUE);
System.out.println("char(max)="+(int)Character.MAX_VALUE);
System.out.println("char(bitlength)="+Character.SIZE);
//float(32bitfloatingpoint)
System.out.println("float(min)="+Float.MIN_VALUE);
System.out.println("float(max)="+Float.MAX_VALUE);
System.out.println("float(bitlength)="+Float.SIZE);
//double(64bitfloatingpoint)
System.out.println("double(min)="+Double.MIN_VALUE);
System.out.println("double(max)="+Double.MAX_VALUE);
System.out.println("double(bitlength)="+Double.SIZE);
}
}
int(min)=2147483648
int(max)=2147483647
int(bitlength)=32
byte(min)=128
byte(max)=127
byte(bitlength)=8
short(min)=32768
short(max)=32767
short(bitlength)=16
long(min)=9223372036854775808
long(max)=9223372036854775807
long(bitlength)=64
char(min)=0
char(max)=65535
char(bitlength)=16
float(min)=1.4E45
float(max)=3.4028235E38
float(bitlength)=32
double(min)=4.9E324
double(max)=1.7976931348623157E308
double(bitlength)=64
String
Another commonlyused type is String, which represents texts a sequence of characters such as "Hello,world". String is not a primitive type, and will be
further elaborated later. In Java, a char is enclosed by single quotes e.g., 'A', '0', while a String is enclosed by double quotes e.g., "Hello". For example,
Stringmessage="Hello,world!";//stringsareenclosedindoublequotes
chargender='m';//charisenclosedinsinglequotes
Rules of Thumb
Use int for integer and double for floating point numbers. Use byte, short, long and float only if you have a good reason to choose that specific precision.
Use int for counting and indexing, NOT floatingpoint type float or double. This is because integer type are precise and more efficient in operations.
Use an integer type if possible. Use a floatingpoint type only if the number contains a fractional part.
Data Representation
Read "Data Representation" if you wish to understand how the numbers and characters are represented inside the computer memory. In brief, It is important to
take note that char '1' is different from int 1, byte 1, short 1, float 1.0, double 1.0, and String "1". They are represented differently in the computer
memory, with different precision and interpretation. For example, byte 1 is "00000001", short 1 is "00000000 00000001", int 1 is "00000000 00000000
0000000000000001", long 1 is "0000000000000000000000000000000000000000000000000000000000000001", float 1.0 is "0011111110000000
00000000 00000000", double 1.0 is "0 01111111111 0000 00000000 00000000 00000000 00000000 00000000 00000000", char '1' is "00000000
00110001", and String "1" is a complex object.
Furthermore, you MUST know the type of a value before you can interpret a value. For example, this value "00000000000000000000000000000001" cannot
be interpreted unless you know its type or its representation.
Example Variable Names and Types: Paul has bought a new notebook of "abc" brand, with a processor speed of 3.2GHz, 4 GB of RAM, 500GB hard
disk, with a 15inch monitor, for $1650.45. He has chosen service plan 'B' among plans 'A', 'B' and 'C', plus onsite servicing. Identify the data types and name the
variables.
Stringname="Paul";
Stringbrand="abc";
doubleprocessorSpeedInGHz=3.2;//orfloat
doubleramSizeInGB=4;//orfloat
intharddiskSizeInGB=500;//orshort
intmonitorInInch=15;//orbyte
doubleprice=1650.45;
charservicePlan='B';
booleanonSiteService=true;
Exercise Variable Names and Types: You are asked to develop a software for a college. The system shall maintain information about students. This
includes name, address, phone number, gender, date of birth, height, weight, degree pursued e.g., B.Sc., B.A., year of study, average GPA, with/without tuition
grant, is/is not a scholar. Each student is assigned a unique 8digit number as id. Identify the variables. Assign a suitable name to each variable and choose an
appropriate type. Write the variable declaration statements.
intnumber=123;
intsum=1234567890;//Thisvalueiswithintherangeofint
intbigSum=8234567890;//ERROR:thisvalueisoutsidetherangeofint
An int literal may precede with a plus + or minus sign, followed by digits. No commas or special symbols e.g., $ or space is allowed e.g., 1,234 and $123
are invalid. No preceding 0 is allowed too e.g., 007 is invalid.
You can use a prefix '0' zero to denote a value in octal, and prefix '0x' or '0X' for a value in hexadecimal, e.g.,
intnumber=1234;//Decimal
intnumber=01234;//Octal1234,Decimal2322
intnumber=0x1abc;//hexadecimal1ABC,decimal15274
JDK 1.7 From JDK 7, you can use prefix '0b' or '0B' to specify a value in binary. You are also permitted to use underscore _ to break the digits into groups to
improve the readability. But you must start and end the literal with a digit. For example,
intnumber1=0b01010000101000101101000010100010;
intnumber2=0b0101_0000_1010_0010_1101_0000_1010_0010;//breakthedigitswithunderscore(JDK1.7)
intnumber3=2_123_456;//breakthedigitswithunderscore(JDK1.7)
A long literal above the int range requires a suffix 'L' or 'l' avoid lowercase, which confuses with the number one, e.g., 123456789012L, 9876543210l. In
Java, the range of 64bit long literals is 9,223,372,036,854,775,808L 2^63 to 9,223,372,036,854,775,807L 2^631. For example,
longbigNumber=1234567890123L;//Suffix'L'needed
longsum=123;//int123autocaststolong123L
No suffix is needed for byte and short literals. But you can only use integer values in the permitted range. For example,
bytesmallNumber=12345;//ERROR:thisvalueisoutsidetherangeofbyte.
bytesmallNumber=123;//Thisiswithintherangeofbyte
shortmidSizeNumber=12345;
You can optionally use suffix 'd' or 'D' to denote double literals.
You MUST use a suffix of 'f' or 'F' for float literals, e.g., 1.2345F. For example,
floataverage=55.66;//Error!RHSisadouble.Needsuffix'f'forfloat.
floataverage=55.66f;
For example,
charletter='a';//Sameas97
charanotherLetter=98;//Sameastheletter'b'
System.out.println(letter);//'a'printed
System.out.println(anotherLetter);//'b'printedinsteadofthenumber
anotherLetter+=2;//100or'd'
System.out.println(anotherLetter);//'d'printed
Nonprintable and control characters can be represented by a socalled escape sequence, which begins with a backslash \ followed by a pattern. The commonly
used escape sequences are:
\t Tab 0009H(9D)
Notes:
Newline 000AH and CarriageReturn 000DH, represented by the escape sequence \n, and \r respectively, are used as line delimiter or endofline, or EOL.
Take note that Unixes and Mac use \n 0AH as EOL, while Windows use \r\n 0D0AH.
To represent a backslash char, you need to write '\\', instead of '\', as a backslash begins an escape sequence. Similarly, to include a backslash in a
doublequoted string, you need to write \\.
To represent a singlequote char, you need to write '\'' to distinguish it from the closing singlequote. But you can write doublequote directly, i.e., '"'.
To place a doublequote in a doublequoted string, you need to use \" to distinguish it from the closing doublequote, e.g., "\"hello\"". But you can
write singlequote directly, e,g, "'hello'".
Other less commonlyused escape sequences are: \a for alert or bell, \b for backspace, \f for formfeed, \v for vertical tab. These may not be supported in
some consoles.
String Literals
A String literal is composed of zero of more characters surrounded by a pair of double quotes, e.g., "Hello,world!", "Thesumis:". For example,
StringdirectionMsg="TurnRight";
StringgreetingMsg="Hello";
StringstatusMsg="";//anemptystring
String literals may contains escape sequences. Inside a String, you need to use \" for doublequote to distinguish it from the ending doublequote, e.g.
"\"quoted\"". Singlequote inside a String does not require escape sequence. For example,
System.out.println("Use\\\"toplace\na\"within\ta\tstring");
Use\"toplace
a"within a string
Exercise: Write a program to print the following animal picture using multiple System.out.println(). Take note that you need to use escape sequences to
print special characters.
'__'
(oo)
+========\/
/||%%%||
*||||
""""
boolean Literals
There are only two boolean literals, i.e., true and false. For example,
booleandone=true;
booleangameOver=false;
Example on Literals
/*
*Testliteralsforvariousprimitivetypes
*/
publicclassLiteralTest{
publicstaticvoidmain(String[]args){
Stringname="TanAhTeck";//Stringisdoublequoted
chargender='m';//charissinglequoted
booleanisMarried=true;//trueorfalse
bytenumChildren=8;//Rangeofbyteis[127,128]
shortyearOfBirth=1945;//Rangeofshortis[32767,32768].Beyondbyte
intsalary=88000;//Beyondtherangesofbyteandshort
longnetAsset=8234567890L;//Needsuffix'L'forlong.Beyondint
doubleweight=88.88;//Withfractionalpart
floatgpa=3.88f;//Needsuffix'f'forfloat
//println()canbeusedtoprintvalueofanytype
System.out.println("Nameis"+name);
System.out.println("Genderis"+gender);
System.out.println("Ismarriedis"+isMarried);
System.out.println("Numberofchildrenis"+numChildren);
System.out.println("Yearofbirthis"+yearOfBirth);
System.out.println("Salaryis"+salary);
System.out.println("NetAssetis"+netAsset);
System.out.println("Weightis"+weight);
System.out.println("GPAis"+gpa);
}
}
3.Operations
3.1Arithmetic Operators
Java supports the following arithmetic operators:
All these operators are binary operators, i.e., they take two operands. However, '+' and '' can also be interpreted as unary "positive" and "negative" operators. For
example,
intnumber=88;//negate
intx=+5;//'+'optional
3.2Arithmetic Expressions
In programming, the following arithmetic expression:
must be written as (1+2*a)/3+(4*(b+c)*(5de))/f6*(7/g+h). You cannot omit the multiplication symbol *, as in Mathematics.
Rules on Precedence
Like Mathematics:
1. The multiplication *, division / and remainder % take precedence over addition + and subtraction . For example, 1+2*34/2 is interpreted as 1+
(2*3)(4/2).
3. Parentheses () have the highest precedence and can be used to change the order of evaluation.
4. Within the same precedence level e.g., addition and subtraction, the expression is evaluated from left to right called leftassociative. For example, 1+23+4
is evaluated as ((1+2)3)+4 and 1*2%3/4 is ((1*2)%3)/4.
3.3MixedType Operations
The arithmetic operators are only applicable to primitive numeric types: byte, short, int, long, float, double, and char. These operators do not apply to
boolean.
If both operands are int, long, float or double, the arithmetic operations are carried in that type, and evaluated to a value of that type, i.e., int5+int6
int11; double2.1+double1.2double3.3.
It is important to take note int division produces an int, i.e., int/intint, with the result truncated, e.g., 1/20, instead of 0.5?!
If both operand are byte, short or char, the operations are carried out in int, and evaluated to a value of int. A char is treated as a 16bit unsigned integer in
the range of [0,65535]. For example, byte127+byte1int127+int1int128.
If the two operands belong to different types, the value of the smaller type is promoted automatically to the larger type known as implicit typecasting. The
operation is then carried out in the larger type, and evaluated to a value in the larger type.
byte, short or char is first promoted to int before comparing with the type of the other operand.
For examples,
1. int/doubledouble/doubledouble. Hence, 1/20,1.0/2.00.5,1.0/20.5,1/2.00.5.
2. char+floatint+floatfloat+floatfloat.
byteb1=1,b2=2;
byteb3=b1+b2;//CompilationError:possiblelossofprecision
//b1+b2returnsanint,cannotbeassignedtobyte
The typepromotion rules for unary operations e.g., negate '' can be summarized as follows:
1. If the operand is double, float, long or int, there is no promotion.
2. Else the operand is byte, short, char, the operand is promoted to int.
For example,
byteb1=1;
byteb2=b1;//CompilationError:possiblelossofprecision
//b1returnsanint,cannotbeassignedtobyte
For example,
5%23%21
5.5%2.23.3%2.21.1
Exponent?
Java does not have an exponent operator. The '^' operator is for exclusiveor, NOT exponent. You need to use method Math.exp(x,y) to evaluate x raises to
power y.
3.4Overflow/Underflow
Study the output of the following program:
/*
*Illustrate"int"overflow
*/
publicclassOverflowTest{
publicstaticvoidmain(String[]args){
//Rangeofintis[2147483648,2147483647]
inti1=2147483647;//maximumint
System.out.println(i1+1);//2147483648(overflow!)
System.out.println(i1+2);//2147483647
System.out.println(i1*i1);//1
inti2=2147483648;//minimumint
System.out.println(i21);//2147483647(overflow!)
System.out.println(i22);//2147483646
System.out.println(i2*i2);//0
}
}
In arithmetic operations, the resultant value wraps around if it exceeds its range i.e., overflow. Java runtime does NOT issue an error/warning message but
produces an incorrect result.
On the other hand, integer division produces an truncated integer and results in socalled underflow. For example, 1/2 gives 0, instead of 0.5. Again, Java runtime
does NOT issue an error/warning message, but produces an imprecise result.
It is important to take note that checking of overflow/underflow is the programmer's responsibility. i.e., your job!!!
Why computer does not flag overflow/underflow as an error? This is due to the legacy design when the processors were very slow. Checking for
overflow/underflow consumes computation power. Today, processors are fast. It is better to ask the computer to check for overflow/underflow if you design a new
language, because few humans expect such results.
To check for arithmetic overflow known as secure coding is tedious. Google for "INT32C. Ensure that operations on signed integers do not result in overflow" @
www.securecoding.cert.org.
3.5TypeCasting
In Java, you will get a compilation error if you try to assign a double or float value of to an int variable. This is because the fractional part would be lost. The
compiler issues an error "possible loss in precision". For example,
doubled=3.5;
inti;
i=d;//CompilationError:possiblelossofprecision(assigningadoublevaluetoanintvariable)
intsum=55.66f;//CompilationError:possiblelossofprecision(assigningafloatvaluetoanintvariable)
doubled=3.5;
inti;
i=(int)d;//Castdoublevalueof3.5toint3.Assigntheresultantvalue3toi
//Castingfromdoubletointtruncates.
Typecasting is an operation which takes one operand. It operates on its operand, and returns an equivalent value in the specified type.
inti=3;
doubled;
d=i;//OK,noexplicittypecastingrequired
//d=3.0
d=(double)i;//Explicittypecastingoperatorusedhere
doubleaDouble=55;//Compilerautocastsint55todouble55.0
doublenought=0;//Compilerautocastsint0todouble0.0
//int0anddouble0.0aredifferent.
The following diagram shows the order of implicit typecasting performed by compiler. The rule is to promote the smaller type to a bigger type to prevent loss of
precision, known as widening conversion. Narrowing conversion requires explicit typecast to inform the compiler that you are aware of the possible loss of
precision. Take note that char is treated as an 16bit unsigned integer in the range of [0,65535]. boolean value cannot be typecasted i.e., converted to non
boolean.
Example : Suppose that you want to find the average in double of the integers between 1 and 100. Study the following codes:
1 publicclassSum1To100{
2 publicstaticvoidmain(String[]args){
3 intsum=0;
4 doubleaverage;
5 intnumber=1;
6 while(number<=100){
7 sum+=number;//Finalsumisint5050
8 ++number;
9 }
10 average=sum/100;//Won'twork(average=50.0insteadof50.5)
11 System.out.println("Averageis"+average);//Averageis50.0
12 }
13 }
This is because both the sum and 100 are int. The result of division is an int, which is then implicitly casted to double and assign to the double variable average.
To get the correct answer, you can do either:
average=(double)sum/100;//Castsumfrominttodoublebeforedivision
average=sum/(double)100;//Cast100frominttodoublebeforedivision
average=sum/100.0;
average=(double)(sum/100);//Won'twork.why?
3.7Increment/Decrement
Java supports these unary arithmetic operators: increment ++ and decrement for all numeric primitive types byte, short, char, int, long, float and
double, except boolean.
The increment ++ and decrement operate on its operand and store the result back to its operand. For example, x++ retrieves x, increment and stores the
result back to x. Writing x=x++ is a logical error!!!
Unlike other unary operator such as negate which promotes byte, short and char to int, the increment and decrement do not promote its operand
because there is no such need.
The increment/decrement unary operator can be placed before the operand prefix, or after the operands postfix, which affects its resultant value.
If these operators are used by themselves e.g., x++ or ++x, the outcomes are the same for pre and postoperators, because the resultant values are
discarded.
If '++' or '' involves another operation e.g., y=x++ or y=++x, then pre or postorder is important to specify the order of the two operations:
For examples,
x=5;
System.out.println(x++);//Printx(5),thenincrementx(=6).Outputis5.(x++returnstheoldX.)
x=5;
System.out.println(++x);//Incrementx(=6),thenprintx(6).Outputis6.(++xreturnsx+1.)
Prefix operator e.g, ++i could be more efficient than postfix operator e.g., i++?!
In Java, these comparison operations returns a boolean value of either true or false.
Each comparison operation involves two operands, e.g., x<=100. It is invalid to write 1<x<100 in programming. Instead, you need to break out the two
comparison operations x>1, x<100, and join with with a logical AND operator, i.e., (x>1)&&(x<100), where && denotes AND operator.
Java provides four logical operators, which operate on boolean operands only, in descending order of precedences, as follows:
Example:
//Returntrueifxisbetween0and100(inclusive)
(x>=0)&&(x<=100)
//wrongtouse0<=x<=100
//Returntrueifxisoutside0and100(inclusive)
(x<0)||(x>100)//or
!((x>=0)&&(x<=100))
//Returntrueifyearisaleapyear
//Ayearisaleapyearifitisdivisibleby4butnotby100,oritisdivisibleby400.
((year%4==0)&&(year%100!=0))||(year%400==0)
/*
*Testrelationalandlogicaloperators
*/
publicclassRelationalLogicalOpTest{
publicstaticvoidmain(String[]args){
intage=18;
doubleweight=71.23;
intheight=191;
booleanmarried=false;
booleanattached=false;
chargender='m';
System.out.println(!married&&!attached&&(gender=='m'));
System.out.println(married&&(gender=='f'));
System.out.println((height>=180)&&(weight>=65)&&(weight<=80));
System.out.println((height>=180)||(weight>=90));
}
}
Write an expression for all unmarried male, age between 21 and 35, with height above 180, and weight between 70 and 80.
Exercise: Given the year, month 112, and day 131, write a boolean expression which returns true for dates before October 15, 1582 Gregorian calendar cut
over date.
Ans: (year<1582)||(year==1582&&month<10)||(year==1582&&month==10&&day<15)
Operator Precedence
The precedence from highest to lowest is: '!' unary, '^', '&&', '||'. But when in doubt, use parentheses!
System.out.println(true||true&&false);//true(sameasbelow)
System.out.println(true||(true&&false));//true
System.out.println((true||true)&&false);//false
System.out.println(false&&true^true);//false(sameasbelow)
System.out.println(false&&(true^true));//false
System.out.println((false&&true)^true);//true
ShortCircuit Operation
The logical AND && and OR || operators are known as shortcircuit operators, meaning that the right operand will not be evaluated if the result can be
determined by the left operand. For example, false&&... gives false; true||... give true without evaluating the right operand. This may have adverse
consequences if you rely on the right operand to perform certain operations, e.g. false&&(++i<5) but ++i will not be evaluated.
4.Strings
A String is a sequence of characters. A string literal is surrounded by a pair of double quotes, e.g.,
Strings1="Hi,Thisisastring!"//Stringliteralsareenclosedindoublequotes
Strings2=""//Anemptystring
You need to use an escape sequence for special control characters such as newline \n and tab \t, doublequote \" and backslash \\ due to conflict and
Unicode character \uhhhh if your editor does not support Unicode input, e.g.,
Strings3="A\"string\"nested\\inside\\astring"
Strings4="Hello,\u60a8\u597d!"//"Hello,!"
Strings5="Hi,I'mastring!"//SinglequoteOK
1+23
1.2+2.23.4
1+2.21.0+2.23.2
If both operands are Strings, '+' concatenates the two Strings and returns the concatenated String. E.g.,
"Hello"+"world""Helloworld"
"Hi"+","+"world"+"!""Hi,world!"
If one of the operand is a String and the other is numeric, the numeric operand will be converted to String and the two Strings concatenated, e.g.,
"Thenumberis"+5"Thenumberis"+"5""Thenumberis5"
"Theaverageis"+average+"!"(supposeaverage=5.5)"Theaverageis"+"5.5"+"!""Theaverageis5.5!"
"Howabout"+a+b(supposea=1,b=1)"Howabout11"
4.2String Operations
The most commonlyused String methods are:
length(): return the length of the string.
charAt(intindex): return the char at the index position index begins at 0 to length()1.
equals(): for comparing the contents of two strings. Take note that you cannot use "==" to compare two strings.
For examples,
Stringstr="Javaiscool!";
System.out.println(str.length());//returnint13
System.out.println(str.charAt(2));//returnchar'v'
System.out.println(str.charAt(5));//returnchar'i'
//ComparingtwoStrings
StringanotherStr="JavaisCOOL!";
System.out.println(str.equals(anotherStr));//returnbooleanfalse
System.out.println(str.equalsIgnoreCase(anotherStr));//returnbooleantrue
System.out.println(anotherStr.equals(str));//returnbooleanfalse
System.out.println(anotherStr.equalsIgnoreCase(str));//returnbooleantrue
//(str==anotherStr)tocomparetwoStringsisWRONG!!!
To check all the available methods for String, open JDK API documentation select package "java.lang" select class "String" choose method. For
examples,
Stringstr="Javaiscool!";
System.out.println(str.length());//returnint13
System.out.println(str.charAt(2));//returnchar'v'
System.out.println(str.substring(0,3));//returnString"Jav"
System.out.println(str.indexOf('a'));//returnint1
System.out.println(str.lastIndexOf('a'));//returnint3
System.out.println(str.endsWith("cool!"));//returnbooleantrue
System.out.println(str.toUpperCase());//returnanewString"JAVAISCOOL!"
System.out.println(str.toLowerCase());//returnanewString"javaiscool!"
4.3String/Primitive Conversion
"String" to "int/byte/short/long" : You could use the JDK builtin methods Integer.parseInt(anIntStr) to convert a String containing a valid
integer literal e.g., "1234" into an int e.g., 1234. The runtime triggers a NumberFormatException if the input string does not contain a valid integer literal e.g.,
"abc". For example,
StringinStr="5566";
intnumber=Integer.parseInt(inStr);//number<5566
//InputtoInteger.parseInt()mustbeavalidintegerliteral
number=Integer.parseInt("abc");//RuntimeError:NumberFormatException
Similarly, you could use methods Byte.parseByte(aByteStr), Short.parseShort(aShortStr), Long.parseLong(aLongStr) to convert a string containing a
valid byte, short or long literal to the primitive type.
"String" to "double/float" : You could use Double.parseDouble(aDoubleStr) or Float.parseFloat(aFloatStr) to convert a String containing a
floatingpoint literal into a double or float, e.g.
StringinStr="55.66";
floataFloat=Float.parseFloat(inStr);//aFloat<55.66f
doubleaDouble=Double.parseDouble("1.2345");//aDouble<1.2345
aDouble=Double.parseDouble("abc");//RuntimeError:NumberFormatException
"String" to "char" : You can use aStr.charAt(index) to extract individual character from a String, e.g.,
//Convertingfrombinarytodecimal
Stringmsg="101100111001!";
intpos=0;
while(pos<msg.length()){
charbinChar=msg.charAt(pos);//Extractcharacteratpos
//Dosomethingaboutthecharacter
.......
++pos;
}
"String" to "boolean" : You can use method Boolean.parseBoolean(aBooleanStr) to convert string of "true" or "false" to boolean true or false,
e.g.,
StringboolStr="true";
booleandone=Boolean.parseBoolean(boolStr);//done<true
booleanvalid=Boolean.parseBoolean("false");//valid<false
Primitive int/double/float/byte/short/long/char/boolean to "String" : To convert a primitive to a String, you can use the '+'
operator to concatenate the primitive with an empty String(""), or use the JDK builtin methods String.valueOf(aPrimitve), Integer.toString(anInt),
Double.toString(aDouble), Character.toString(aChar), Boolean.toString(aBoolean), etc. For example,
//Stringconcatenationoperator'+'(applicabletoALLprimitivetypes)
Strings1=123+"";//int123>"123"
Strings2=12.34+"";//double12.34>"12.34"
Strings3='c'+"";//char'c'>"c"
Strings4=true+"";//booleantrue>"true"
//String.valueOf(aPrimitive)isapplicabletoALLprimitivetypes
Strings1=String.valueOf(12345);//int12345>"12345"
Strings2=String.valueof(true);//booleantrue>"true"
doubled=55.66;
Strings3=String.valueOf(d);//double55.66>"55.66"
//toString()foreachprimitivetype
Strings4=Integer.toString(1234);//int1234>"1234"
Strings5=Double.toString(1.23);//double1.23>"1.23"
charc1=Character.toString('z');//char'z'>"z"
//chartoString
charc='a';
Strings5=c;//CompilationError:incompatibletypes
Strings6=c+"";//ConvertthechartoString
//booleantoString
booleandone=false;
Strings7=done+"";//booleanfalse>"false"
Strings8=Boolean.toString(done);
Strings9=String.valueOf(done);
"char" to "int" : You can convert char '0' to '9' to int 0 to 9 by subtracting the char with '0' e.g., '8''0'8.
5.Flow Control
There are three basic flow control constructs sequential, conditional or decision, and loop or iteration, as illustrated below.
5.1Sequential Flow Control
A program is a sequence of instructions. Sequential flow is the most common and straightforward, where programming statements are executed in the order that
they are written from top to bottom in a sequential manner.
//ifthen if(mark>=50){
if(booleanExpression){ System.out.println("Congratulation!");
trueblock; System.out.println("Keepitup!");
} }
//ifthenelse if(mark>=50){
if(booleanExpression){ System.out.println("Congratulation!");
trueblock; System.out.println("Keepitup!");
}else{ }else{
falseblock; System.out.println("TryHarder!");
} }
//nestedif if(mark>=80){
if(booleanExpr1){ System.out.println("A");
block1; }elseif(mark>=70){
}elseif(booleanExpr2){ System.out.println("B");
block2; }elseif(mark>=60){
}elseif(booleanExpr3){ System.out.println("C");
block3; }elseif(mark>=50){
}elseif(booleanExpr4){ System.out.println("D");
...... }else{
}else{ System.out.println("F");
elseBlock; }
}
//switchcasedefault charoper;intnum1,num2,result;
switch(selector){ ......
casevalue1: switch(oper){
block1;break; case'+':
casevalue2: result=num1+num2;break;
block2;break; case'':
casevalue3: result=num1num2;break;
block3;break; case'*':
...... result=num1*num2;break;
casevaluen: case'/':
blockn;break; result=num1/num2;break;
default: default:
defaultblock; System.err.println("Unknownoperator);
} }
Braces: You could omit the braces { }, if there is only one statement inside the block. However, I recommend that you keep the braces to improve the
readability of your program. For example,
if(mark>=50)
System.out.println("PASS");//Onlyonestatement,canomit{}butNOTrecommended
else{//Morethanonestatements,need{}
System.out.println("FAIL");
System.out.println("TryHarder!");
}
"switchcasedefault"
"switchcase" is an alternative to the "nestedif". In a switchcase statement, a break statement is needed for each of the cases. If break is missing, execution will
flow through the following case. You can use an int, byte, short, or char variable as the caseselector, but NOT long, float, double and boolean. JDK 1.7
supports String as the caseselector.
5.3Conditional Operator ?:
A conditional operator is a ternary 3operand operator, in the form of booleanExpr?trueExpr:falseExpr. Depending on the booleanExpr, it evaluates
and returns the value of trueExpr or falseExpr.
Syntax Example
booleanExpr?trueExpr:falseExpr System.out.println((mark>=50)?"PASS":"FAIL");
max=(a>b)?a:b;//RHSreturnsaorb
abs=(a>0)?a:a;//RHSreturnsaora
5.4Exercises on Conditional
LINK TO EXERCISES ON CONDITIONAL FLOW CONTROL
//forloop //Sumfrom1to1000
for(initialization;test;postprocessing){ intsum=0;
body; for(intnumber=1;number<=1000;++number){
} sum+=number;
}
//whiledoloop intsum=0,number=1;
while(test){ while(number<=1000){
body; sum+=number;
} ++number;
}
//dowhileloop intsum=0,number=1;
do{ do{
body; sum+=number;
} ++number;
while(test); }while(number<=1000);
The difference between whiledo and dowhile lies in the order of the body and condition. In whiledo, the condition is tested first. The body will be executed if the
condition is true and the process repeats. In dowhile, the body is executed and then the condition is tested. Take note that the body of dowhile will be executed at
least once vs. possibly zero for whiledo. Similarly, the forloop's body could possibly not executed.
Example: Suppose that your program prompts user for a number between 1 to 10, and checks for valid input. A dowhile loop with a boolean flag could be
more appropriate as it prompts for input at least once, and repeat again and again if the input is invalid.
//Inputwithvaliditycheck
booleanvalid=false;
intnumber;
do{
//promptusertoenteranintbetween1and10
......
//ifthenumberenteredisvalid,setdonetoexittheloop
if(number>=1&&number<=10){
valid=true;
}
}while(!valid);//Needasemicolontoterminatedowhile
Example: Below is an example of using whiledo with a boolean flag. The boolean flag is initialized to false to ensure that the loop is entered.
//Gameloop
booleangameOver=false;
while(!gameOver){
//playthegame
......
//Updatethegamestate
//SetgameOvertotrueifappropriatetoexitthegameloop
......
}
Empty forloop
for(;;){body} is known as an empty forloop, with empty statement for initialization, test and postprocessing. The body of the empty forloop will
execute continuously infinite loop. You need to use a break statement to break out the loop.
for(introw=0,col=0;row<SIZE;++row,++col){
//Processdiagonalelements
......
}
5.6Exercises on Loops
LINK TO EXERCISES ON LOOP FLOW CONTROL
The continue statement aborts the current iteration and continue to the next iteration of the current innermost loop.
break and continue are poor structures as they are hard to read and hard to follow. Use them only if absolutely necessary.
Example break: The following program lists the nonprime numbers between 2 and an upperbound.
/*
*Listallnonprimenumbersbetween2andanupperbound
*/
publicclassNonPrimeList{
publicstaticvoidmain(String[]args){
intupperbound=100;
for(intnumber=2;number<=upperbound;++number){
//Notaprime,ifthereisafactorbetween2andsqrt(number)
intmaxFactor=(int)Math.sqrt(number);
for(intfactor=2;factor<=maxFactor;++factor){
if(number%factor==0){//Factor?
System.out.println(number+"isNOTaprime");
break;//Afactorfound,noneedtosearchformorefactors
}
}
}
}
}
Let's rewrite the above program to list all the primes instead. A boolean flag called isPrime is used to indicate whether the current number is a prime. It is then
used to control the printing.
/*
*Listallprimenumbersbetween2andanupperbound
*/
publicclassPrimeListWithBreak{
publicstaticvoidmain(String[]args){
intupperbound=100;
for(intnumber=2;number<=upperbound;++number){
//Notaprime,ifthereisafactorbetween2andsqrt(number)
intmaxFactor=(int)Math.sqrt(number);
booleanisPrime=true;//booleanflagtoindicatewhethernumberisaprime
for(intfactor=2;factor<=maxFactor;++factor){
if(number%factor==0){//Factor?
isPrime=false;//numberisnotaprime
break;//Afactorfound,noneedtosearchformorefactors
}
}
if(isPrime)System.out.println(number+"isaprime");
}
}
}
Let's rewrite the above program without using break statement. A while loop is used which is controlled by the boolean flag instead of for loop with break.
/*
*Listallprimenumbersbetween2andanupperbound
*/
publicclassPrimeList{
publicstaticvoidmain(String[]args){
intupperbound=100;
for(intnumber=2;number<=upperbound;++number){
//Notprime,ifthereisafactorbetween2andsqrtofnumber
intmaxFactor=(int)Math.sqrt(number);
booleanisPrime=true;
intfactor=2;
while(isPrime&&factor<=maxFactor){
if(number%factor==0){//Factorofnumber?
isPrime=false;
}
++factor;
}
if(isPrime)System.out.println(number+"isaprime");
}
}
}
Example continue:
/*
*Sum1toupperbound,exclude11,22,33,...
*/
intupperbound=100;
intsum=0;
for(intnumber=1;number<=upperbound;++number){
if(number%11==0)continue;//Skiptherestoftheloopbody,continuetothenextiteration
sum+=number;
}
//Itisbettertorewritetheloopas:
for(intnumber=1;number<=upperbound;++number){
if(number%11!=0)sum+=number;
}
/*
*Amysteryseriescreatedusingbreakandcontinue
*/
publicclassMysterySeries{
publicstaticvoidmain(String[]args){
intnumber=1;
while(true){
++number;
if((number%3)==0)continue;
if(number==133)break;
if((number%2)==0){
number+=3;
}else{
number=3;
}
System.out.print(number+"");
}
}
}
Labeled break
In a nested loop, the break statement breaks out the innermost loop and continue into the outer loop. At times, there is a need to break out all the loops or
multiple loops. This is clumsy to achieve with boolean flag, but can be done easily via the socalled labeled break. You can add a label to a loop in the form of
labelName:loop. For example,
level1://definealabelforthelevel1loop
for(.....){
level2://definealabelforthelevel2loop
for(.....){
for(......){//level3loop
if(...)breaklevel1;//breakallloops,continueaftertheloop
if(...)breaklevel2://continueintothenextstatementoflevel1loop
......
}
}
}
Labeled continue
In a nested loop, similar to labeled break, you can use labeled continue to continue into a specified loop. For example,
level1://definealabel(with:suffix)forthelevel1loop
for(.....){
level2://definealabel(with:suffix)forthelevel2loop
for(.....){
for(......){//level3loop
if(...)continuelevel1;//continuethenextiterationoflevel1loop
if(...)continuelevel2://continuethenextiterationoflevel2loop
......
}
}
}
Again, labeled break and continue are not structured and hard to read. Use them only if absolutely necessary.
Example Labeled break: Suppose that you are searching for a particular number in a 2D array.
1 publicclassTestLabeledBreak{
2 publicstaticvoidmain(String[]args){
3 int[][]testArray={
4 {1,2,3,4},
5 {4,3,1,4},
6 {9,2,3,4}
7 };
8
9 intmagicNumber=8;
10 booleanfound=false;
11 mainLoop:
12 for(inti=0;i<testArray.length;++i){
13 for(intj=0;j<testArray[i].length;++j){
14 if(testArray[i][j]==magicNumber){
15 found=true;
16 breakmainLoop;
17 }
18 }
19 }
20 System.out.println("Magicnumber"+(found?"found":"NOTfound"));
21 }
22 }
5.8Terminating Program
System.exit(intexitCode) : You could invoke the method to terminate the program and return the control to the Java
System.exit(intexitCode) : You could invoke the method System.exit(intexitCode) to terminate the program and return the control to the Java
runtime. By convention, return code of zero indicates normal termination; while a nonzero exitCode indicates abnormal termination. For example,
if(errorCount>10){
System.out.println("toomanyerrors");
System.exit(1);//Terminatetheprogram
}
The return statement : You could also use a "returnreturnValue" statement in the main() method to terminate the program and return control back to
the Java Runtime. For example,
publicstaticvoidmain(String[]args){
...
if(errorCount>10){
System.out.println("toomanyerrors");
return;//TerminateandreturncontroltoJavaRuntimefrommain()
}
...
}
5.9Nested Loops
Try out the following program, which prints a 8by8 checker box pattern using nested loops, as follows:
########
########
########
########
########
########
########
########
1 /*
2 *Printasquarepattern
3 */
4 publicclassPrintSquarePattern{//Saveas"PrintSaurePattern.java"
5 publicstaticvoidmain(String[]args){
6 intsize=8;
7 for(introw=1;row<=size;++row){//Outerlooptoprintalltherows
8 for(intcol=1;col<=size;++col){//Innerlooptoprintallthecolumnsofeachrow
9 System.out.print("#");
10 }
11 System.out.println();//Arowended,bringthecursortothenextline
12 }
13 }
14 }
This program contains two nested forloops. The inner loop is used to print a row of eight "#", which is followed by printing a newline. The outer loop repeats the
inner loop to print all the rows.
Suppose that you want to print this pattern instead in program called PrintCheckerPattern:
########
########
########
########
########
########
########
########
You need to print an additional space for evennumber rows. You could do so by adding the following statement before Line 8.
if((row%2)==0){//printaleadingspaceforevennumberedrows
System.out.print("");
}
TRY:
1. Print these patterns using nested loop in a program called PrintPattern1x. Use a variable called size for the size of the pattern and try out various sizes.
You should use as few print() or println() statements as possible.
#*#*#*#*################11
#*#*#*#*##############2112
#*#*#*#*############321123
#*#*#*#*##########43211234
#*#*#*#*########5432112345
#*#*#*#*######654321123456
#*#*#*#*####76543211234567
#*#*#*#*##8765432112345678
(a)(b)(c)(d)(e)
Hints:
The equations for major and opposite diagonals are row = col and row + col = size + 1. Decide on what to print above and below the diagonal.
2. Print the timetable of 1 to 9, as follows, using nested loop. Hints: you need to use an ifelse statement to check whether the product is singledigit or
doubledigit, and print an additional space if needed.
123456789
24681012141618
......
###################################
##########
##########
########
##########
##########
###################################
(a)(b)(c)(d)(e)
if(i==0)
if(j==0)
System.out.println("iandjarezero");
elseSystem.out.println("iisnotzero");//intendfortheouterif
The else clause in the above codes is syntactically applicable to both the outerif and the innerif. Java compiler always associate the else clause with the
innermost if i.e., the nearest if. Dangling else can be resolved by applying explicit parentheses. The above codes are logically incorrect and require explicit
parentheses as shown below.
if(i==0){
if(j==0)System.out.println("iandjarezero");
}else{
System.out.println("iisnotzero");//nonambiguousforouterif
}
while(true){......}
is commonly used. It seems to be an endless loop or infinite loop, but it is usually terminated via a break or return statement inside the loop body. This kind of
code is hard to read avoid if possible by rewriting the condition.
Provide comments to explain the important as well as salient concepts. Comment your codes liberally.
Write your program documentation while writing your programs.
Avoid unstructured constructs, such as break and continue, which are hard to follow.
Use "monospace" fonts such as Consolas, Courier New, Courier for writing/displaying your program.
It is estimated that over the lifetime of a program, 20 percent of the effort will go into the original creation and testing of the code, and 80 percent of the effort will
go into the subsequent maintenance and enhancement. Writing good programs which follow standard conventions is critical in the subsequent maintenance and
enhancement!!!
6.1Programming Errors
There are generally three classes of programming errors:
1. Compilation Error or Syntax Error: can be fixed easily.
2. Runtime Error: program halts prematurely without producing the results can also be fixed easily.
3. Logical Error: program completes but produces incorrect results. It is easy to detect if the program always produces wrong result. It is extremely hard to fix if
the program produces the correct result most of the times, but incorrect result sometimes. For example,
//Cancompileandexecute,butgivewrongresultsometimes!
if(mark>50){
System.out.println("PASS");
}else{
System.out.println("FAIL");
}
This kind of errors is very serious if it is not caught before production. Writing good programs helps in minimizing and detecting these errors. A good testing
strategy is needed to ascertain the correctness of the program. Software testing is an advanced topics which is beyond our current scope.
6.2Debugging Programs
Here are the common debugging techniques:
1. Stare at the screen! Unfortunately, errors usually won't popup even if you stare at it extremely hard.
2. Study the error messages! Do not close the console when error occurs and pretending that everything is fine. This helps most of the times.
3. Insert print statements at appropriate locations to display the intermediate results. It works for simple toy program, but it is neither effective nor efficient for
complex program.
4. Use a graphic debugger. This is the most effective means. Trace program execution stepbystep and watch the value of variables and outputs.
5. Advanced tools such as profiler needed for checking memory leak and method usage.
6. Proper program testing to wipe out the logical errors.
7.Input/Output
Java SE 5 introduced a new method called printf() for formatted output which is modeled after C Language's printf(). printf() takes the following form:
printf(formattingstring,arg1,arg2,arg3,...);
Formattingstring contains both normal texts and the socalled Format Specifiers. Normal texts including white spaces will be printed as they are. Format
specifiers, in the form of "%[flags][width]conversioncode", will be substituted by the arguments following the formattingstring, usually in a onetoone and
sequential manner. A format specifier begins with a '%' and ends with the conversion code, e.g., %d for integer, %f for floatingpoint number, %c for character and
%s for string. Optional [width] can be inserted in between to specify the fieldwidth. Similarly, optional [flags] can be used to control the alignment, padding
and others. For examples,
%d: integer printed in spaces is optional.
%s: String printed in spaces is optional. If is omitted, the number of spaces is the length of the string to fit the string.
%.f: Floating point number float and double printed in spaces with decimal digits and are optional.
%n: a systemspecific new line Windows uses "\r\n", Unix and Mac "\n".
Examples:
System.out.printf("Hello%2dand%6s",8,"HI!!!%n");
Hello*8and****HI!!!//*denoteswhitespacesinsertedbyformatspecifier
System.out.printf("Hi,%s%4d%n","Hello",88);
Hi,Hello**88
System.out.printf("Hi,%d%4.2f%n",8,5.556);
Hi,85.56
System.out.printf("Hi,%4s&%6.2f%n","Hi",5.5);//'%ns'forleftalignString
Hi,Hi**&**5.50
System.out.printf("Hi,Hi,%.4f%n",5.56);
Hi,Hi,5.5600
Take note that printf() does not advance the cursor to the next line after printing. You need to explicitly print a newline character at the end of the formatting
string to advance the cursor to the next line, if desires. [In C program, we often use '\n' to print a newline, which results in nonportable program. You should use
format specifier "%n" instead.]
There are many more format specifiers in Java. Refer to JDK Documentation for the detailed descriptions.
Also take note that printf() take a variable number of arguments or varargs, which is a new feature introduced in JDK 1.5 in order to support printf()
You can read input from keyboard via System.in standard input device.
Java SE 5 introduced a new class called Scanner in package java.util to simplify formatted input and a new method printf() for formatted output described
earlier. You can construct a Scanner to scan input from System.in keyboard, and use methods such as nextInt(), nextDouble(), next() to parse the next
int, double and String token delimited by white space of blank, tab and newline.
/*
*Testinginputscanner
*/
importjava.util.Scanner;//NeededtousetheScanner
publicclassScannerTest{
publicstaticvoidmain(String[]args){
//Declarevariables
intnum1;
doublenum2;
Stringstr;
//ConstructaScannernamed"in"forscanningSystem.in(keyboard)
Scannerin=newScanner(System.in);
//Readinputsfromkeyboard
System.out.print("Enteraninteger:");//Showpromptingmessage
num1=in.nextInt();//UsenextInt()toreadanint
System.out.print("Enterafloatingpoint:");//Showpromptingmessage
num2=in.nextDouble();//UsenextDouble()toreadadouble
System.out.print("Enterastring:");//Showpromptingmessage
str=in.next();//Usenext()toreadaStringtoken,uptowhitespace
//Formattedoutputviaprintf()
System.out.printf("%s,Sumof%d&%.2fis%.2f%n",str,num1,num2,num1+num2);
//closetheinput
in.close();
}
}
You can also use method nextLine() to read in the entire line, including white spaces, but excluding the terminating newline.
/*
*TestingScanner'snextLine()
*/
importjava.util.Scanner;//NeededtousetheScanner
publicclassScannerNextLineTest{
publicstaticvoidmain(String[]args){
Scannerin=newScanner(System.in);
System.out.print("Enterastring(withspace):");
//UsenextLine()toreadentirelineincludingwhitespaces,
//butexcludingtheterminatingnewline.
Stringstr=in.nextLine();
System.out.printf("%s%n",str);
in.close();
}
}
Try not to mix nextLine() and nextInt()|nextDouble()|next() in a program as you may need to flush the newline from the input buffer.
The Scanner supports many other input formats. Check the JDK documentation page, under package java.util class Scanner Method.
Scannerin=newScanner(newFile("in.txt"));//ConstructaScannertoscanatextfile
//Usethesamesetofmethods
intanInt=in.nextInt();//nextString
doubleaDouble=in.nextDouble();//nextdouble
Stringstr=in.next();//nextint
Stringline=in.nextLine();//entireline
To open a file via newFile(filename), you need to handle the socalled FileNotFoundException, i.e., the file that you are trying to open cannot be found.
Otherwise, you cannot compile your program. There are two ways to handle this exception: throws or trycatch.
/*
*InputfromFile.
*Technique1:Declare"throwsFileNotFoundException"intheenclosingmain()method
*/
importjava.util.Scanner;//NeededforusingScanner
importjava.io.File;//Neededforfileoperation
importjava.io.FileNotFoundException;//Neededforfileoperation
publicclassTextFileScannerWithThrows{
publicstaticvoidmain(String[]args)
throwsFileNotFoundException{//Declare"throws"here
intnum1;
doublenum2;
Stringname;
Scannerin=newScanner(newFile("in.txt"));//Scaninputfromtextfile
num1=in.nextInt();//Readint
num2=in.nextDouble();//Readdouble
name=in.next();//ReadString
System.out.printf("Hi%s,thesumof%dand%.2fis%.2f%n",name,num1,num2,num1+num2);
in.close();
}
}
To run the above program, create a text file called in.txt containing:
1234
55.66
Paul
/*
*InputfromFile.
*Technique2:Usetrycatchtohandleexception
*/
importjava.util.Scanner;//NeededforusingScanner
importjava.io.File;//Neededforfileoperation
importjava.io.FileNotFoundException;//Neededforfileoperation
publicclassTextFileScannerWithCatch{
publicstaticvoidmain(String[]args){
intnum1;
doublenum2;
Stringname;
try{//trythesestatements
Scannerin=newScanner(newFile("in.txt"));
num1=in.nextInt();//Readint
num2=in.nextDouble();//Readdouble
name=in.next();//ReadString
System.out.printf("Hi%s,thesumof%dand%.2fis%.2f%n",name,num1,num2,num1+num2);
in.close();
}catch(FileNotFoundExceptionex){//catchandhandletheexceptionhere
ex.printStackTrace();//printthestacktrace
}
}
}
/*
*OutputtoFile.
*Technique1:Declare"throwsFileNotFoundException"intheenclosingmain()method
*/
importjava.io.File;
importjava.util.Formatter;//<==note
importjava.io.FileNotFoundException;//<==note
publicclassTextFileFormatterWithThrows{
publicstaticvoidmain(String[]args)
throwsFileNotFoundException{//<==note
//ConstructaFormattertowriteformattedoutputtoatextfile
Formatterout=newFormatter(newFile("out.txt"));
//Writetofilewithformat()method(similartoprintf())
intnum1=1234;
doublenum2=55.66;
Stringname="Paul";
out.format("Hi%s,%n",name);
out.format("Thesumof%dand%.2fis%.2f%n",num1,num2,num1+num2);
out.close();//Closethefile
System.out.println("Done");//Printtoconsole
}
}
Run the above program, and check the outputs in text file "out.txt".
/*
*OutputtoFile.
*Technique2:Usetrycatchtohandleexception
*/
importjava.io.File;
importjava.util.Formatter;//<==note
importjava.io.FileNotFoundException;//<==note
publicclassTextFileFormatterWithCatch{
publicstaticvoidmain(String[]args){
try{//trythefollowingstatements
//ConstructaFormattertowriteformattedoutputtoatextfile
Formatterout=newFormatter(newFile("out.txt"));
//Writetofilewithformat()method(similartoprintf())
intnum1=1234;
doublenum2=55.66;
Stringname="Pauline";
out.format("Hi%s,%n",name);
out.format("Thesumof%dand%.2fis%.2f%n",num1,num2,num1+num2);
out.close();//Closethefile
System.out.println("Done");//Printtoconsole
}catch(FileNotFoundExceptionex){//catchtheexceptionhere
ex.printStackTrace();//Printthestacktrace
}
}
}
1 /*
2 *InputviaaDialogbox
3 */
4 importjavax.swing.JOptionPane;//NeededtouseJOptionPane
5 publicclassJOptionPaneTest{
6 publicstaticvoidmain(String[]args){
7 StringradiusStr;
8 doubleradius,area;
9 //ReadinputStringfromdialogbox
10 radiusStr=JOptionPane.showInputDialog("Entertheradiusofthecircle");
11 radius=Double.parseDouble(radiusStr);//ConvertStringtodouble
12 area=radius*radius*Math.PI;
13 System.out.println("Theareais"+area);
14 }
15 }
To use the new Console class, you first use System.console() to retrieve the Console object corresponding to the current system console.
Consolecon=System.console();
You can then use methods such as readLine() to read a line. You can optionally include a prompting message with format specifiers e.g., %d, %s in the
prompting message.
StringinLine=con.readLine();
Stringmsg=con.readLine("Enteryourmessage:");//readLine()withpromptingmessage
Stringmsg=con.readLine("%s,entermessage:",name);//Promptingmessagewithformatspecifier
You can use con.printf() for formatted output with format specifiers such as %d, %s. You can also connect the Console to a Scanner for formatted input, i.e.,
parsing primitives such as int, double, for example,
Scannerin=newScanner(con.reader());//UseScannertoscantheConsole
//UsetheScanner'smethodssuchasnextInt(),nextDouble()toparseprimitives
intanInt=in.nextInt();
doubleaDouble=in.nextDouble();
Stringstr=in.next();
Stringline=in.nextLine();
Example:
/*
*Testingjava.io.Consoleclass
*/
importjava.io.Console;
importjava.util.Scanner;
publicclassConsoleTest{
publicstaticvoidmain(String[]args){
Consolecon=System.console();//RetrievetheConsoleobject
//ConsoleclassdoesnotworkinEclipse/NetBeans
if(con==null){
System.err.println("ConsoleObjectisnotavailable.");
System.exit(1);
}
//Readalinewithapromptingmessage
Stringname=con.readLine("EnteryourName:");
con.printf("Hello%s%n",name);
//UsetheconsolewithScannerforparsingprimitives
Scannerin=newScanner(con.reader());
con.printf("Enteraninteger:");
intanInt=in.nextInt();
con.printf("Theintegerenteredis%d%n",anInt);
con.printf("Enterafloatingpointnumber:");
doubleaDouble=in.nextDouble();
con.printf("Thefloatingpointnumberenteredis%f%n",aDouble);
in.close();
}
}
The Console class also provides a secure mean for password entry via method readPassword(). This method disables input echoing and keep the password in a
char[] instead of a String. The char[] containing the password can be and should be overwritten, removing it from memory as soon as it is no longer needed.
Recall that Strings are immutable and cannot be overwritten. When they are longer needed, they will be garbagecollected at an unknown instance.
/*
*InputtingpasswordviaConsole
*/
importjava.io.Console;
importjava.util.Arrays;
publicclassConsolePasswordTest{
staticStringlogin;
staticchar[]password;
publicstaticvoidmain(String[]args){
Consolecon=System.console();
if(con==null){
System.err.println("ConsoleObjectisnotavailable.");
System.exit(1);
}
login=con.readLine("EnteryourloginName:");
password=con.readPassword("Enteryourpassword:");
if(checkPassword(login,password)){
Arrays.fill(password,'');//Removepasswordfrommemory
//Continue...
}
}
staticbooleancheckPassword(Stringlogin,char[]password){
returntrue;
}
}
7.7Exercises on Input/Output
LINK TO EXERCISE ON INPUT
8.Arrays
Suppose that you want to find the average of the marks for a class of 30 students, you certainly do not want to create 30 variables: mark1, mark2, ..., mark30.
Instead, You could use a single variable, called an array, with 30 elements.
An array is an ordered collection of elements of the same type, identified by a pair of square brackets []. To use an array, you need to:
1. Declare the array with a name and a type. Use a plural name for array, e.g., marks, rows, numbers. All elements of the array belong to the same type.
int[]marks;//Declareanintarraynamedmarks
//markscontainsaspecialvaluecallednull.
intmarks[];//Sameasabove,buttheabovesyntaxrecommended
marks=newint[5];//Allocate5elementsviathe"new"operator
//Declareandallocatea20elementarrayinonestatementvia"new"operator
int[]factors=newint[20];
//Declare,allocatea6elementarraythruinitialization
int[]numbers={11,22,33,44,55,66};//sizeofarraydeducedfromthenumberofitems
When an array is constructed via the new operator, all the elements are initialized to their default value, e.g., 0 for int, 0.0 for double, false for boolean, and
null for objects. [Unlike C/C++, which does NOT initialize the array contents.]
When an array is declared but not allocated, it contains a special value called null.
You can refer to an element of an array via an index or subscript enclosed within the square bracket []. Java's array index begins with zero 0. For example,
suppose that marks is an int array of 5 elements, then the 5 elements are: marks[0], marks[1], marks[2], marks[3], and marks[4].
int[]marks=newint[5];//Declare&allocatea5elementintarray
//Assignvaluestotheelements
marks[0]=95;
marks[1]=85;
marks[2]=77;
marks[3]=69;
marks[4]=66;
System.out.println(marks[0]);
System.out.println(marks[3]+marks[4]);
To create an array, you need to known the length or size of the array in advance, and allocate accordingly. Once an array is created, its length is fixed and cannot
be changed. At times, it is hard to ascertain the length of an array e.g., how many students?. Nonetheless, you need to estimate the length and allocate an upper
bound. This is probably the major drawback of using an array.
In Java, the length of array is kept in an associated variable called length and can be retrieved using "arrayName.length", e.g.,
int[]factors=newint[5];//Declareandallocatea5elementintarray
intnumFactors=factors.length;//numFactoris5
Unlike languages like C/C++, Java performs array indexbound check at the
runtime. In other words, for each reference to an array element, the index is
checked against the array's length. If the index is outside the range of [0,
arrayName.legnth1], the Java Runtime will signal an exception called
ArrayIndexOutOfBoundException. It is important to note that checking
array indexbound consumes computation power, which inevitably slows
down the processing. However, the benefits gained in terms of good
software engineering outweight the slow down in speed.
1 /*
2 *Findthemeanandstandarddeviationofnumberskeptinanarray
3 */
4 publicclassMeanStdArray{
5 publicstaticvoidmain(String[]args){
6 int[]marks={74,43,58,60,90,64,70};
7 intsum=0;
8 intsumSq=0;
9 intcount=marks.length;
10 doublemean,stdDev;
11 for(inti=0;i<count;++i){
12 sum+=marks[i];
13 sumSq+=marks[i]*marks[i];
14 }
15 mean=(double)sum/count;
16 System.out.printf("Meanis%.2f%n",mean);
17 stdDev=Math.sqrt((double)sumSq/countmean*mean);
18 System.out.printf("Stddevis%.2f%n",stdDev);
19 }
20 }
Syntax Example
for(typeitem:anArray){ int[]numbers={8,2,6,4,3};
body; intsum=0;
} for(intnumber:numbers){//foreachintnumberinint[]numbers
//typemustbethesameasthe sum+=number;
//anArray'stype }
System.out.println("Thesumis"+sum);
It shall be read as "for each element in the array...". The loop executes once for each element in the array, with the element's value copied into the declared
variable. The foreach loop is handy to transverse all the elements of an array or a collection. It requires fewer lines of codes, eliminates the loop counter and the
array index, and is easier to read. However, for array of primitive types e.g., array of ints, it can read the elements only, and cannot modify the array's contents.
This is because each element's value is copied into the loop's variable passbyvalue, instead of working on its original copy.
In many situations, you merely want to transverse thru the array and read each of the elements. For these cases, enhanced forloop is preferred and recommended
over other loop constructs.
8.3Exercises on Arrays
LINK TO EXERCISES ON ARRAY
8.4MultiDimensional Array
In Java, you can declare an array of arrays. For examples:
intgrid[][]=newint[12][8];//a128gridofint
grid[0][0]=8;
grid[1][1]=5;
System.out.println(grid.length);//12
System.out.println(grid[0].length);//8
System.out.println(grid[11].length);//8
In the above example, grid is an array of 12 elements. Each of the elements grid[0] to grid[11] is an 8element int array. In other words, grid is a "12
element array" of "8element int arrays". Hence, grid.length gives 12 and grid[0].length gives 8.
publicclassArray2DTest{
publicstaticvoidmain(String[]args){
int[][]grid=newint[12][8];//A12x8grid,in[row][col]or[y][x]
intnumRows=grid.length;//12
intnumCols=grid[0].length;//8
//Fillingrid
for(introw=0;row<numRows;++row){
for(intcol=0;col<numCols;++col){
grid[row][col]=row*numCols+col+1;
}
}
//Printgrid
for(introw=0;row<numRows;++row){
for(intcol=0;col<numCols;++col){
System.out.printf("%3d",grid[row][col]);
}
System.out.println();
}
}
}
To be precise, Java does not support multidimensional array directly. That is, it does not
support syntax like grid[3,2] like some languages. Furthermore, it is possible that the
arrays in an arrayofarrays have different length.
Take note that the right way to view the "array of arrays" is as shown, instead of treating it
as a 2D table, even if all the arrays have the same length.
For example,
1 publicclassArray2DWithDifferentLength{
2 publicstaticvoidmain(String[]args){
3 int[][]grid={
4 {1,2},
5 {3,4,5},
6 {6,7,8,9}
7 };
8
9 //Printgrid
10 for(inty=0;y<grid.length;++y){
11 for(intx=0;x<grid[y].length;++x){
12 System.out.printf("%2d",grid[y][x]);
13 }
14 System.out.println();
15 }
16
17 int[][]grid1=newint[3][];
18 grid1[0]=newint[2];
19 grid1[1]=newint[3];
20 grid1[2]=newint[4];
21
22 //Printgridallelementsinitto0
23 for(inty=0;y<grid1.length;++y){
24 for(intx=0;x<grid1[y].length;++x){
25 System.out.printf("%2d",grid1[y][x]);
26 }
27 System.out.println();
28 }
29 }
30 }
9.Methods (Functions)
9.1Why Methods?
At times, a certain portion of codes has to be used many times. Instead of rewriting the codes many times, it is better to put them into a "subroutine", and "call"
this "subroutine" many time for ease of maintenance and understanding. Subroutine is called method in Java or function in C/C++.
9.2Using Methods
Two parties are involved in using a method: a caller, who calls or invokes the method, and the method called.
The process is:
1. The caller invokes a method and passes arguments to the method.
2. The method:
a. receives the arguments passed by the caller,
b. performs the programmed operations defined in the method's body, and
c. returns a result back to the caller.
3. The caller receives the result, and continue its operations.
Example: Suppose that we need to evaluate the area of a circle many times, it is better to write a method called getArea(), and reuse it when needed.
1 publicclassEgMethodGetArea{
2 //Theentrymainmethod
3 publicstaticvoidmain(String[]args){
4 doubler=1.1,area,area2;
5 //Call(Invoke)methodgetArea()
6 area=getArea(r);
7 System.out.println("areais"+area);
8 //CallmethodgetArea()again
9 area2=getArea(2.2);
10 System.out.println("area2is"+area2);
11 //CallmethodgetArea()onemoretime
12 System.out.println("area3is"+getArea(3.3));
13 }
14
15 //MethodgetArea()Eefinition.
16 //Computeandreturnthearea(indouble)ofcirclegivenitsradius(indouble).
17 publicstaticdoublegetArea(doubleradius){
18 returnradius*radius*Math.PI;
19 }
20 }
areais3.8013271108436504
area2is15.205308443374602
area3is34.21194399759284
In the above example, a reusable method called getArea() is defined, which receives an argument in double from the caller, performs the calculation, and return
a double result to the caller. In the main(), we invoke getArea() methods thrice, each time with a different parameter.
Take note that there is a transfer of control from the caller to the method called, and from the method back to the caller, as illustrated.
Another Example:
/**ExampleofJavaMethoddefinitionandinvocation*/
publicclassEgMinMaxMethod{
//Theentrymain()method
publicstaticvoidmain(String[]args){
inta=6,b=9,max,min;
max=max(a,b);//invokemethodmax()witharguments
min=min(a,b);//invokemethodmin()witharguments
System.out.println(max+","+min);
System.out.println(max(5,8));//invokemethodmax()
System.out.println(min(5,8));//invokemethodmin()
}
//Themax()methodreturnsthemaximumoftwogivennumbers
publicstaticintmax(intnumber1,intnumber2){
return(number1>number2)?number1:number2;
}
//Themin()methodreturnstheminimumoftwogivennumbers
publicstaticintmin(intnumber1,intnumber2){
return(number1<number2)?number1:number2;
}
}
returnaReturnValue;//ofreturnValueTypedeclaredinmethod'ssignature
return;//returnnothing(orvoid)
Notice that main() is a method with a returnvalue type of void. main() is called by the Java runtime, perform the actions defined in the body, and return
nothing back to the Java runtime.
In the above example, the variable (doubleradius) declared in the signature of getArea(doubleradius) is known as formal parameter. Its scope is within the
method's body. When the method is invoked by a caller, the caller must supply socalled actual parameters or arguments, whose value is then used for the actual
computation. For example, when the method is invoked via "area1=getArea(radius1)", radius1 is the actual parameter, with a value of 1.1.
For example,
1 publicclassPassingParameterTest{
2 publicstaticvoidmain(String[]args){
3 intnumber=8;//primitivetype
4 System.out.println("Incaller,beforecallingthemethod,numberis:"+number);//8
5 intresult=increment(number);//invokemethod
6 System.out.println("Incaller,aftercallingthemethod,numberis:"+number);//8
7 System.out.println("Theresultis"+result);//9
8 }
9
10 publicstaticintincrement(intnumber){
11 System.out.println("Insidemethod,beforeoperation,numberis"+number);//8
12 ++number;//changetheparameter
13 System.out.println("Insidemethod,afteroperation,numberis"+number);//9
14 returnnumber;
15 }
16 }
9.7Varargs Method with Variable Number of Formal Arguments JDK 1.5
Before JDK 1.5, a method has to be declared with a fixed number of formal arguments. Clike printf(), which take a variable number of argument, cannot not be
implemented. Although you can use an array for passing a variable number of arguments, it is not neat and requires some programming efforts.
JDK 1.5 introduces variable arguments or varargs and a new syntax "Type...". For example,
publicPrintWriterprintf(Stringformat,Object...args)
publicPrintWriterprintf(Locall,Stringformat,Object...args)
Varargs can be used only for the last argument. The three dots ... indicate that the last argument may be passed as an array or as a sequence of comma
separated arguments. The compiler automatically packs the varargs into an array. You could then retrieve and process each of these arguments inside the
method's body as an array. It is possible to pass varargs as an array, because Java maintains the length of the array in an associated variable length.
1 publicclassVarargsTest{
2 //Amethodwhichtakesavariablenumberofarguments(varargs)
3 publicstaticvoiddoSomething(String...strs){
4 System.out.print("Argumentsare:");
5 for(Stringstr:strs){
6 System.out.print(str+",");
7 }
8 System.out.println();
9 }
10
11 //Amethodwhichtakesexactlytwoarguments
12 publicstaticvoiddoSomething(Strings1,Strings2){
13 System.out.println("Overloadedversionwith2args:"+s1+","+s2);
14 }
15
16 //Cannotoverloadwiththismethodcrashwithvarargsversion
17 //publicstaticvoiddoSomething(String[]strs)
18
19 //Testmain()method
20 //CanalsouseString...insteadofString[]
21 publicstaticvoidmain(String...args){
22 doSomething("Hello","world","again","and","again");
23 doSomething("Hello","world");
24
25 String[]strs={"apple","orange"};
26 doSomething(strs);//invokevarargsversion
27 }
28 }
Notes:
If you define a method that takes a varargs String..., you cannot define an overloaded method that takes a String[].
"varargs" will be matched last among the overloaded methods. The varargsMethod(String, String), which is more specific, is matched before the
varargsMethod(String...).
From JDK 1.5, you can also declare your main() method as:
publicstaticvoidmain(String...args){....}//JDK1.5varargs
9.8Method Overloading
In Java, a method of a particular method name can have more than one versions, each version operates on different set of parameters known as method
overloading. The versions shall be differentiated by the numbers, types, or orders of the parameters.
For example,
/**TestingMethodOverloading*/
publicclassEgMethodOverloading{
publicstaticvoidmain(String[]args){
System.out.println(average(8,6));//invokeversion1
System.out.println(average(8,6,9));//invokeversion2
System.out.println(average(8.1,6.1));//invokeversion3
System.out.println(average(8,6.1));
//int8autocasttodouble8.0,invokeversion3
//average(1,2,3,4)//CompilationErrornosuchmethod
}
//Version1takes2int's
publicstaticintaverage(intn1,intn2){
System.out.println("version1");
return(n1+n2)/2;//int
}
//Version2takes3int's
publicstaticintaverage(intn1,intn2,intn3){
System.out.println("version2");
return(n1+n2+n3)/3;//int
}
//Version3takes2doubles
publicstaticdoubleaverage(doublen1,doublen2){
System.out.println("version3");
return(n1+n2)/2.0;//double
}
}
The expected outputs are:
version1
7
version2
7
version3
7.1
version3
7.05
9.9"boolean" Methods
A boolean method returns a boolean value to the caller.
Suppose that we wish to write a method called isOdd() to check if a given number is odd.
1 /**
2 *Testingbooleanmethod(methodthatreturnsabooleanvalue)
3 */
4 publicclassBooleanMethodTest{
5 //Thismethodreturnsabooleanvalue
6 publicstaticbooleanisOdd(intnumber){
7 if(number%2==1){
8 returntrue;
9 }else{
10 returnfalse;
11 }
12 }
13
14 publicstaticvoidmain(String[]args){
15 System.out.println(isOdd(5));//true
16 System.out.println(isOdd(6));//false
17 System.out.println(isOdd(5));//false
18 }
19 }
This seemingly correct codes produces false for 5, because 5%2 is 1 instead of 1. You may rewrite the condition:
publicstaticbooleanisOdd(intnumber){
if(number%2==0){
returnfalse;
}else{
returntrue;
}
}
The above produces the correct answer, but is poor. For boolean method, you can simply return the resultant boolean value of the comparison, instead of using a
conditional statement, as follow:
publicstaticbooleanisEven(intnumber){
return(number%2==0);
}
publicstaticbooleanisOdd(intnumber){
return!(number%2==0);
}
9.10Mathematical Methods
JDK provides many commonused Mathematical methods in a class called Math. The signatures of some of these methods are:
doubleMath.pow(doublex,doubley)//returnsxraisestopowerofy
doubleMath.sqrt(doublex)//returnsthesquarerootofx
doubleMath.random()//returnsarandomnumberin[0.0,1.0)
doubleMath.sin()
doubleMath.cos()
Math.PI//3.141592653589793
Math.E//2.718281828459045
To check all the available methods, open JDK API documentation select package "java.lang" select class "Math" choose method.
For examples,
intsecretNumber=(int)Math.random()*100;//Generatearandomintbetween0and99
doubleradius=5.5;
doublearea=radius*radius*Math.PI;
area=Math.pow(radius,2)*Math.PI;//Notasefficientasabove
intx1=1,y1=1,x2=2,y2=2;
doubledistance=Math.sqrt((x2x1)*(x2x1)+(y2y1)*(y2y1));
intdx=x2x1;
intdy=y2y1;
distance=Math.sqrt(dx*dx+dy*dy);//Slightlymoreefficient
9.11Implicit TypeCasting for Method's Parameters
A method that takes a double parameter can accept any numeric primitive type, such as int or float. This is because implicit typecasting is carried out.
However, a method that take a int parameter cannot accept a double value. This is because the implicit typecasting is always a widening conversion which
prevents loss of precision. An explicit typecast is required for narrowing conversion. Read "TypeCasting" on the conversion rules.
9.12Exercises on Methods
LINK TO EXERCISES ON METHOD
10.CommandLine Arguments
Java's main(String[]args) method takes an argument: String[]args, i.e., a String array named args. This is known as "commandline arguments", which
corresponds to the augments provided by the user when the java program is invoked. For example, a Java program called Arithmetic could be invoked with
additional commandline arguments as follows in a "cmd" shell:
javaArithmetic123456+
Each argument, i.e., "12", "3456" and "+", is a String. Java runtime packs all the arguments into a String array and passes into the main() method as args. For
this example, args has the following properties:
args={"12","3456","+"}//"args"isaStringarray
args.length=3//lengthofthearrayargs
args[0]="12"//EachelementofthearrayisaString
args[1]="3456"
args[2]="+"
args[0].length()=2//lengthoftheString
args[1].length()=4
args[2].length()=1
Example: The program Arithmetic reads three parameters form the commandline, two integers and an arithmetic operator '+', '', '*', or '/', and
performs the arithmetic operation accordingly. For example,
javaArithmetic32+
3+2=5
javaArithmetic32
32=1
javaArithmetic32/
3/2=1
1 publicclassArithmetic{
2 publicstaticvoidmain(String[]args){
3 intoperand1,operand2;
4 chartheOperator;
5 operand1=Integer.parseInt(args[0]);//ConvertStringtoint
6 operand2=Integer.parseInt(args[1]);
7 theOperator=args[2].charAt(0);//Consideronly1stcharacter
8 System.out.print(args[0]+args[2]+args[1]+"=");
9 switch(theOperator){
10 case('+'):
11 System.out.println(operand1+operand2);break;
12 case(''):
13 System.out.println(operand1operand2);break;
14 case('*'):
15 System.out.println(operand1*operand2);break;
16 case('/'):
17 System.out.println(operand1/operand2);break;
18 default:
19 System.out.printf("%nError:Invalidoperator!");
20 }
21 }
22 }
11.Code Examples
11.1EG 1: Bin2Dec
Convert a binary string into its equivalent decimal number.
Version 1:
/*
*Promptuserforabinarystring,andconvertintoitsequivalentdecimalnumber.
*/
importjava.util.Scanner;
publicclassBin2Dec{
publicstaticvoidmain(String[]args){
StringbinStr;//Theinputbinarystring
intbinStrLen;//ThelengthofbinStr
intdec=0;//Thedecimalequivalent,accumulatefrom0
//Readinput
Scannerin=newScanner(System.in);
System.out.print("Enterabinarystring:");
binStr=in.next();
binStrLen=binStr.length();
//Processcharbycharfromtheright(i.e.Leastsignificantbit)
for(intexp=0;exp<binStrLen;++exp){
intcharPos=binStrLen1exp;//charAt(pos)
charbinChar=binStr.charAt(charPos);
//3cases:'1'(addtodec),'0'(donothing),other(error)
if(binChar=='1'){
dec+=(int)Math.pow(2,exp);//castthedoubleresultbacktoint
}elseif(binChar!='0'){
System.out.println("Error:Invalidbinarystring\""+binStr+"\"");
System.exit(1);//quit
}
}
//Printresult
System.out.println("Theequivalentdecimalfor\""+binStr+"\"is"+dec);
in.close();
}
}
binStr:10111001
charAt(pos):01234567(poscountsfromtheleft)
Math.pow(2,exp):76543210(expcountsfromtheright)
binStr.length()=8
pos+exp=binStr.length()1
Version 2:
/*
*Promptuserforabinarystring,andconvertintoitsequivalentdecimalnumber.
*Validatetheinputstring.
*Repeattheprogram,untiluserchoosestoquit.
*Allowblankinthebinarystring,e.g.,"01001000".
*/
importjava.util.Scanner;
publicclassBin2DecIteractive{
publicstaticvoidmain(String[]args){
StringinStr;//Theinputbinarystring
Scannerin=newScanner(System.in);
booleandone=false;//booleanflagforcontrollingtheloop
while(!done){
//Promptfortheinputstring
System.out.print("Enterabinarystringor'q'toquit:");
inStr=in.nextLine();//readentirelineincludingblanks
if(inStr.equals("q")){
System.out.println("Bye!");
done=true;
}elseif(!isValidBinStr(inStr)){
System.out.println("Error:Invalidbinarystring:\""+inStr+"\",tryagain.");
}else{
System.out.println("Theequivalentdecimalnumberfor\""+inStr+"\"is"+bin2Dec(inStr));
}
}
in.close();
}
//Returntrueifthegivenstringcontainsonlybinarynumbersandblanks.
publicstaticbooleanisValidBinStr(StringbinStr){
for(inti=0;i<binStr.length();++i){
charbinChar=binStr.charAt(i);
if(binChar!='0'&&binChar!='1'&&binChar!=''){
returnfalse;//breakonfirstinvalidchar
}
}
returntrue;
}
//Returntheequivalentdecimalnumberofthegivenbinarystring.
//BlanksareallowedinthebinStr,e.g.,"00101000".
//Assumethattheinputcontains'0','1'or''.
publicstaticintbin2Dec(StringbinStr){
intbinStrLen=binStr.length();//ThelengthofbinStr
intdec=0;//Equivalentdecimalnumber,accumulatingfrom0
//Weneedtoprocessfromtheright(i.e.Leastsignificantbit)
for(intcharPos=binStrLen1,exp=0;charPos>=0;charPos){
charbinChar=binStr.charAt(charPos);
//3cases:'1'(addtodec,++exp),'0'(++exp),''(donothing)
if(binChar=='1'){
dec+=(int)Math.pow(2,exp);
++exp;
}elseif(binChar=='0'){
++exp;
}//elsefor''(donothing)
}
returndec;
}
}
11.2EG 2: Hex2Dec
Convert a hexadecimal string to its decimal equivalence.
/*
*Promptuserforthehexadecimalstring,andconverttoitsequivalentdecimalnumber
*/
importjava.util.Scanner;
publicclassHex2Dec{
publicstaticvoidmain(String[]args){
StringhexStr;//TheinputhexadecimalString
inthexStrLen;//ThelengthofhexStr
intdec=0;//Thedecimalequivalent,accumulatingfrom0
//Readinput
Scannerin=newScanner(System.in);
System.out.print("EnteraHexadecimalstring:");
hexStr=in.next();
hexStrLen=hexStr.length();
//Processcharbycharfromtheright(leastsignificantdigit)
for(intexp=0;exp<hexStrLen;++exp){
intcharPos=hexStrLen1exp;
charhexChar=hexStr.charAt(charPos);
intfactor=(int)Math.pow(16,exp);
//23cases:'0''9','a''f','A''F',other(error)
if(hexChar>='1'&&hexChar<='9'){
dec+=(hexChar'0')*factor;
}elseif(hexChar>='a'&&hexChar<='f'){
dec+=(hexChar'a'+10)*factor;
}elseif(hexChar>='A'&&hexChar<='F'){
dec+=(hexChar'A'+10)*factor;
}else{
System.out.println("Error:Invalidhexstring\""+hexStr+"\"");
System.exit(1);
}
}
System.out.println("Theequivalentdecimalfor\""+hexStr+"\"is"+dec);
in.close();
}
}
You may use in.next().toLowercase() to reduce the number of cases. But that modifies the input string.
11.3EG 3: Dec2Hex
Convert a decimal number to its hexadecimal equivalence.
/*
*Promptuserforanint,andconverttoitsequivalenthexadecimalnumber.
*/
importjava.util.Scanner;
publicclassDec2Hex{
publicstaticvoidmain(String[]args){
intdec;//Theinputdecimalnumber
StringhexStr="";//TheequivalenthexString,accumulatingfromemptyString
intradix=16;//Hexradix
char[]hexChar={'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F'};//Usethisarrayaslookuptable
//Readinput
Scannerin=newScanner(System.in);
System.out.print("Enteradecimalnumber:");
dec=in.nextInt();
//Repeateddivisionandgettheremainder
while(dec>0){
inthexDigit=dec%radix;
hexStr=hexChar[hexDigit]+hexStr;//appendinfrontofthehexstring
dec=dec/radix;
}
System.out.println("Theequivalenthexadecimalnumberis"+hexStr);
in.close();
}
}
11.4EG 4: Hex2Bin
Convert a hexadecimal number to its binary equivalence.
/*
*Promptuserforahexadecimalstring,andconverttoitsbinaryequivalence.
*/
importjava.util.Scanner;
publicclassHex2Bin{
publicstaticvoidmain(String[]args){
StringhexStr;//TheinputhexadecimalString
inthexStrLen;//ThelengthofhexStr
StringbinStr="";//TheequivalentbinaryString,accumulatingfromemptyString
//LookuptableforthebinarystringcorrespondingtoHexdigit'0'(index0)to'F'(index15)
String[]binStrs
={"0000","0001","0010","0011","0100","0101","0110","0111",
"1000","1001","1010","1011","1100","1101","1110","1111"};
//Readinput
Scannerin=newScanner(System.in);
System.out.print("EnteraHexadecimalstring:");
hexStr=in.next();
hexStrLen=hexStr.length();
//Processthestringfromtheleft
for(intpos=0;pos<hexStrLen;++pos){
charhexChar=hexStr.charAt(pos);
if(hexChar>='0'&&hexChar<='9'){
binStr+=binStrs[hexChar'0'];//indexintothebinStrsarray
}elseif(hexChar>='a'&&hexChar<='f'){
binStr+=binStrs[hexChar'a'+10];
}elseif(hexChar>='A'&&hexChar<='F'){
binStr+=binStrs[hexChar'A'+10];
}else{
System.err.println("Error:InvalidHexstring\""+hexStr+"\"");
System.exit(1);//quit
}
}
System.out.println("Theequivalentbinaryfor\""+hexStr+"\"is\""+binStr+"\"");
in.close();
}
}
importjava.util.Scanner;
publicclassNumberGuess{
publicstaticvoidmain(String[]args){
intsecretNumber;//Secretnumbertobeguessed
intnumberIn;//Theguessednumberentered
inttrialNumber=0;//Numberoftrialssofar
booleandone=false;//booleanflagforloopcontrol
//Setupthesecretnumber
//Math.random()generatesadoublein[0.0,1.0)
secretNumber=(int)(Math.random()*100);
Scannerin=newScanner(System.in);
while(!done){
++trialNumber;
System.out.print("Enteryourguess(between0and99):");
numberIn=in.nextInt();
if(numberIn==secretNumber){
System.out.println("Congratulation");
done=true;
}elseif(numberIn<secretNumber){
System.out.println("Tryhigher");
}else{
System.out.println("Trylower");
}
}
System.out.println("Yougotin"+trialNumber+"trials");
in.close();
}
}
Example
1 publicclassTestBitwiseOp{
2 publicstaticvoidmain(String[]args){
3 intx=0xAAAA_5555;//anegativenumber(signbit(msb)=1)
4 inty=0x5555_1111;//apositivenumber(signbit(msb)=0)
5 System.out.printf("%d%n",x);//1431677611
6 System.out.printf("%d%n",y);//1431638289
7 System.out.printf("%08X%n",~x);//5555AAAAH
8 System.out.printf("%08X%n",x&y);//00001111H
9 System.out.printf("%08X%n",x|y);//FFFF5555H
10 System.out.printf("%08X%n",x^y);//FFFF4444H
11 }
12 }
Compound operator &=, |= and ^= are also available, e.g., x&=y is the same as x=x&y.
System.out.println(true&true);//logical>true
System.out.println(0x1&0xffff);//bitwise>1
System.out.println(true&&true);//logical>true
2. The bitwise NOT or bit inversion operator is represented as '~', which is different from logical NOT !.
3. The bitwise XOR is represented as '^', which is the same as logical XOR ^.
4. The operators' precedence is in this order: '~', '&', '^', '|', '&&', '||'. For example,
System.out.println(true|true&false);//true|(true&false)>true
System.out.println(true^true&false);//true^(true&false)>true
Bitwise operations are powerful and yet extremely efficient. [Example on advanced usage.]
12.2BitShift Operations
Bitshift operators perform left or right shift on an operand by a specified number of bits. Rightshift can be either signedextended >> padded with signed bit
or unsignedextended >>> padded with zeros. Leftshift is always padded with zeros for both signed and unsigned.
Since all the Java's integers byte, short, int and long are signed integers, leftshift << and rightshift >> operators perform signedextended bit shift. Signed
extended right shift >> pads the most significant bits with the sign bit to maintain its sign i.e., padded with zeros for positive numbers and ones for negative
numbers. Operator >>> introduced in Java, not in C/C++ is needed to perform unsignedextended right shift, which always pads the most significant bits with
zeros. There is no difference between the signedextended and unsignedextended left shift, as both operations pad the least significant bits with zeros.
Example
1 publicclassBitShiftTest{
2 publicstaticvoidmain(String[]args){
3 intx=0xAAAA5555;//anegativenumber(signbit(msb)=1)
4 inty=0x55551111;//apositivenumber(signbit(msb)=0)
5 System.out.printf("%d%n",x);//1431677611
6 System.out.printf("%d%n",y);//1431638289
7 System.out.printf("%08X%n",x<<1);//5554AAAAH
8 System.out.printf("%08X%n",x>>1);//D5552AAAH
9 System.out.printf("%d%n",x>>1);//negative
10 System.out.printf("%08X%n",y>>1);//2AAA8888H
11 System.out.printf("%08d%n",y>>1);//positive
12 System.out.printf("%08X%n",x>>>1);//55552AAAH
13 System.out.printf("%d%n",x>>>1);//positive
14 System.out.printf("%08X%n",y>>>1);//2AAA8888
15 System.out.printf("%d%n",y>>>1);//positive
16
17 //Moreefficienttousesignedrightrighttoperformdivisionby2,4,8,...
18 inti1=12345;
19 System.out.println("i1dividesby2is"+(i1>>1));
20 System.out.println("i1dividesby4is"+(i1>>2));
21 System.out.println("i1dividesby8is"+(i1>>3));
22 inti2=12345;
23 System.out.println("i2dividesby2is"+(i2>>1));
24 System.out.println("i2dividesby4is"+(i2>>2));
25 System.out.println("i2dividesby8is"+(i2>>3));
26 }
27 }
As seen from the example, it is more efficient to use signrightshift to perform division by 2, 4, 8... power of 2, as integers are stored in binary.
13.Algorithms
Before writing a program to solve a problem, you have to first develop the steps involved, called algorithm, and then translate the algorithm into programming
statements. This is the hardest part in programming, which is also hard to teach because the it involves intuition, knowledge and experience.
An algorithm is a stepbystep instruction to accomplice a task, which may involve decision and iteration. It is often expressed in Englishlike pseudocode, before
translating into programming statement of a particular programming language. There is no standard on how to write pseudocode simply write something that
you, as well as other people, can understand the steps involved, and able to translate into a working program.
To test whether a number x is a prime number, we could apply the definition by dividing x by 2, 3, 4, ..., up to x1. If no divisor is found, then x is a prime number.
Since divisors come in pair, there is no need to try all the factors until x1, but up to x.
//Totestwhetheranintxisaprime
intmaxFactor=(int)Math.sqrt(x);//findthenearestintegralsquarerootofx
assumexisaprime;
for(intfactor=2;factor<=maxFactor;++factor){
if(xisdivisiblebyfactor){
xisnotaprime;
break;//afactorfound,noneedtofindmorefactors
}
}
TRY : translate the above pseudocode into a Java program called PrimeTest.
//Totestwhetherintxisaperfectnumber
intsum=0;
for(inti=1;i<x;++i){
if(xisdivisiblebyi){
iisaproperdivisor;
addiintothesum;
}
}
if(sum==x)
xisaperfectnumber
else
xisnotaperfectnumber
TRY : translate the above pseudocode into a Java program called PerfectNumberTest.
Assume that a and b are positive integers and a>=b, the Euclidean algorithm is based on these two properties:
1.GCD(a,0)=a
2.GCD(a,b)=GCD(b,amodb),where"amodb"denotestheremainderofadividesbyb.
For example,
GCD(15,5)=GCD(5,0)=5
GCD(99,88)=GCD(88,11)=GCD(11,0)=11
GCD(3456,1233)=GCD(1233,990)=GCD(990,243)=GCD(243,18)=GCD(18,9)=GCD(9,0)=9
GCD(a,b)//assumethata>=b
while(b!=0){
//Changethevalueofaandb:ab,bamodb,andrepeatuntilbis0
tempb
bamodb
atemp
}
//aftertheloopcompletes,i.e.,bis0,wehaveGCD(a,0)
GCDisa
Before explaining the algorithm, suppose we want to exchange or swap the values of two variables x and y. Explain why the following code does not work.
intx=55,y=66;
//swapthevaluesofxandy
x=y;
y=x;
To swap the values of two variables, we need to define a temporary variable as follows:
intx=55,y=66;
inttemp;
//swapthevaluesofxandy
temp=y;
y=x;
x=temp;
Let us look into the Euclidean algorithm, GCD(a,b)=a, if b is 0. Otherwise, we replace a by b; b by (amodb), and compute GCD(b,amodb). Repeat the
process until the second term is 0. Try this out on pencilandpaper to convince yourself that it works.
13.4Exercises on Algorithm
LINK TO EXERCISES ON ALGORITHMS
14.Summary
This chapter covers the Java programming basics:
Variables, literals, expressions and statements.
The concept of type and Java's eight primitive types: byte, short, int, long, float, double, char, and boolean.
Three flow control constructs: sequential, condition if, ifelse, switchcase and nestedif and loops while, dowhile, for and nested loops.
Input via Scanner & Output print(), println() and printf() operations.
Arrays and the enhanced forloop.
Methods and passing parameters into methods.
The advanced bitwise logical operators &, |, ~, ^ and bitshift operators <<, >>, >>>.
Developing algorithm for solving problems.
Feedback, comments, corrections, and errata can be sent to Chua HockChuan (ehchua@ntu.edu.sg) | HOME