Download Object Oriented Programming in Java Dr. E.C. Kulasekere

Document related concepts
no text concepts found
Transcript
Object Oriented Programming in Java
Dr. E.C. Kulasekere
[email protected]
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.1
Java?
Web enabled and network savvy.
Enforces safety in transfers.
Delivers a software front end.
Network library is easy to use.
Java is cross platform
Compiles to machine independent byte code (JVM runtime can execute it).
Offers a portable graphics library; AWT (abstract windowing toolkit); Java2
offers Swing components.
Java is simple
Automated memory management. eg. inaccessible array locations cannot
be referenced, automated garbage collection.
Java simplifies pointer handling. Only reference are passed to objects.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.2
Cont ..
Java is object oriented
All functions are associated with objects. In many other OO languages we
have normal functions and then methods. In Java the only allowable
function is a method.
All data types are objects. Primitive data types such as int and double have
external wrappers such as Integer and Double.
Java has a rich and powerful standard libraries in its APIs.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.3
Introduction to Java Applications
Java programs consists of pieces called classes.
Classes consists of pieces called methods. These methods perform tasks and
return information when they complete their tasks.
Additional Java APIs (Applications Programming Interfaces) are provided by
compiler vendors. These are known as Java class libraries
Hence learning Java consists of:
Learning to use Java APIs.
Learning to write your own classes.
The Java 2 Software Development Kit (J2SDK) Version 1.2.4 can be
downloaded for Unix/Linux and Win32 platforms from java.sun.com.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.4
A Survey of Programming Techniques
Unstructured programming.
Procedural programming.
Modular programming.
Object-oriented programming.
This is also known as the stages in the learning curve of programming.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.5
Unstructured Programming
program
main program
data
Simple sequence of
command statements.
Operates directly on global
data.
Not good for large programs.
Repetitive statement segments are copied over.
The repetitive sequences extracted and named so that
they can be called and values returned leads to the idea of
procedures.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.6
Procedural Programming
Combines returning
sequences of statements
into one function.
program
main program
data
procedure1
procedure2
Procedure calls are used to
invoke procedures.
procedure3
Programs are now more
structured.
Errors are easier to detect.
Combining procedures into modules is the next logical
extension.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.7
Modular Programming
Procedures with common
functionality are grouped
into modules.
program
main program
data
module 1
module 2
data +data1
data +data2
procedure1
procedure2
procedure3
Main program coordinates
calls to procedures within
modules.
Each module has its own
data and isolated for other
modules.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.8
Object-Oriented Programming
Data and the functions that
operate on that data are
combined into an object.
program
object1
data
object4
data
object3
data
object2
data
Programming is not function
based but object based.
Objects are base on three
basic ideas:
Encapsulation, Inheritance and Polymorphism.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.9
Basics of a Typical Java Environment
Java system: an environment, the language, the Java API, various
class libraries.
Development:
edit (JBuilder, Netbeans [www.netbeans.com], Visual Cafe)
compile (using javac into Byte code)
load (class loader)
verify (the byte codes in .class file)
execute (using java).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.10
Program Structure
1. public class Prog1 {
2. public static void main(String args[]) {
3.
System.out.println("prog1");
4.
}
6. }
The class consists of a class header (1); First letter capital for classes (Java is case
sensitive); public access modifier requires that the name of the file is identical to the
class name. Hence it is illegal for one file to have two classes with public modifier.
System is a class in java.lang.* API, however import java.lang.* is omitted
since it is always a part of the program.
Execution entry point is main. It should be seen by all (ensured by public) and it
should exist before any instance of the class has been created (ensured by static).
With static only one instance will exist everywhere. No ambiguity.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.11
Adding Graphics
1. import javax.swing.JOptionPane;
2.
3. public class Welcome {
4.
public static void main(String [] args) {
5.
JOptionPane.showMessageDialog(
6.
null, "Welcome");
7.
System.exit(0);
8.
}
9. }
Note that Java is case sensitive, hence be careful.
Line 1 loads the JOptionPane class of the swing package.
showMessageDialog is a static method of the class JOptionPane. That is it
has global scope (only one instance exists) hence can only be accessed using
the dot notation with class scope attached.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.12
Explanation ...
Each object of a class has its own copy of all the instance variables of the
class. i.e. Different memory locations.
data variables share one memory location for all the class objects of the
same type.
static
methods are similar. All class instances access the same method without
modification. i.e. the scope resolution is necessary when you access it.
static
A static class variable and a static class method exist and can be used even if
no objects of that class have been created. Static methods cannot call
non-static methods or non-static class variables.
Forgetting to call System.exit in an application that displays a GUI prevents
the program from exiting properly. This will freeze the command window.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.13
Instance Variables
import javax.swing.JOptionPane;
public class Addition {
public static void main( String args[] )
{
String num1, num2;
int number1, number2, sum;
num1 = JOptionPane.showInputDialog( "Enter first integer" );
num2 = JOptionPane.showInputDialog( "Enter second integer" );
number1 = Integer.parseInt(num1);
number2 = Integer.parseInt(num2);
sum = number1 + number2;
JOptionPane.showMessageDialog(
null, "The sum is " + sum, "Results",
JOptionPane.PLAIN_MESSAGE );
System.exit( 0 );
}
}
Both integers and strings will be instance variables where each will have a memory
space allocated as place holder. That is data members of a class is usually called
instance variables.
Integer is a class from the java.lang package. This will be automatically loaded at
compile time.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.14
Cont ...
parseInt is a static method within Integer.
The + operator can be used for string concatenation. (preview of
polymorphism, explain)
For double basic data type, a type conversion occurs for the output. (eg:
Addition.java) This is a preview to polymorphism.
The usage of APIs can be found in the javadoc, documentation files.
Downloadable from java.sun.com.
The PLAIN_MESSAGE option removes the window icon.
Do not confuse the assignment operator (=) with the comparison operator
(==).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.15
Control Structures
Control structures are used to deviate from the sequential operation of
programs.
If/Else structure and if/else if structures.
while repetition structure. do/while structure. Different from while
When x=2; post increment x++ prints 2; pre increment ++x displays 4 useful in
control structures.
for control structure.
switch structure. Selection among multiple directions.
break and continue control statements. Break exits from a loop or switch
statement. continue moves to the end and loops back (skips remaining).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.16
Methods
Operations on the data within a class is carried out using methods
For example the Math class methods enable the user to do math operations
such as finding square root (Math.sqrt(4)).
Variables within methods are called local variables (encapsulated).
A method definition has the following syntax
return-value-type method-name(parameter-list)
{
declarations and statements;
}
Method definition should appear inside a class definition.
The return statement should have a compatible type.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.17
Duration and Scope of Identifiers
Identifiers are used for variable and reference names.
The duration of an identifier is the period during which that identifier exists in memory.
An identifiers scope is where the identifier can be referenced in a program.
Local variables declared in a method body are also called automatic variables. These
are created while a block or method is active and destroyed when the block or method
exits.
Instance variables of a class are automatically initialized by the compiler if the
programmer does not provide initial values. All primitive data types are initialized to zero
and boolean variables to false.
However Automatic variables need to be initialized before they can be used.
Variables of static duration remain in memory after creation till the program
terminates.
Their storage is allocated and initialized when their classes are loaded into memory.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.18
Cont ...
Duration of a static variable has nothing to do with the scope. Even though it exists in
memory it may not be accessible in some cases.
Methods and instance variables have class scope. That is methods and instance
variables are global within the class.
Identifiers within a block have block scope. That is within the braces of a block. The
variable scope remains the same for nested blocks too.
If a local variable in a method has the same name as an instance variable, the instance
variable is hidden until the block terminates execution.
For labels used with break and continue, we have a special scope called method scope.
That is the label is visible to only the method in which it is used.
A variable name in an inner block having the same name as a variable in an outer block
will cause a syntax error.
As a general practice you should avoid defining local variables that hide instance
variable.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.19
Example
import java.awt.Container;
import javax.swing.*;
public class Scoping extends JApplet {
JTextArea outputArea;
int x = 1;
// instance variable
public void init()
{
outputArea = new JTextArea();
Container c = getContentPane();
c.add( outputArea );
}
public void start()
{
int x = 5;
// variable local to method start
outputArea.append( "local x in start is " + x );
methodA();
methodB();
methodA();
methodB();
//
//
//
//
methodA has automatic local x
methodB uses instance variable x
methodA reinitializes automatic local x
instance variable x retains its value
outputArea.append( "\n\nlocal x in start is " + x );
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.20
Cont ...
public void methodA()
{
int x = 25; // initialized each time a is called
outputArea.append( "\n\nlocal x in methodA is
" after entering methodA"
++x;
outputArea.append( "\nlocal x in methodA is "
" before exiting methodA"
" + x +
);
+ x +
);
}
public void methodB()
{
outputArea.append( "\n\ninstance variable x is " + x +
" on entering methodB" );
x *= 10;
outputArea.append( "\ninstance variable x is " + x +
" on exiting methodB" );
}
}
To run the above applet the following HTML code can be used.
<html>
<applet code="Scoping.class" width=280 height=260>
</applet>
</html>
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.21
Cont .. Results
local x in stat is 5
local x in methodA is 25 after entering method A
local x in methodA is 26 before exising method A
instance variable x is 1 on entering method B
instance variable is 10 on exiting method B
local x in methodA is 25 after entering method A
local x in methodA is 26 before exising method A
instance variable x is 10 on entering method B
instance variable is 100 on exiting method B
local x in start is 5
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.22
Method Overloading
public class MOverload extends JApplet {
......
......
}
public int square (int x) {
return x*x;
}
public double square (double x) {
return x*x;
}
The appropriate square function will be chosen according to the input
parameters.
This is a preview to Polymorphism (parametric).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.23
Arrays
Arrays, in general are static entities.
First element is C[0]. It is important to know the difference between the nth element of
an array and element n, there is an off-by-one error if not used properly.
Declaring an array: int c[]; Allocating an array: c = new int[12]
Both of the above can be done using int c[]=new int [12].
Allocations are considered instance variables and initialized appropriately.
Indirect Allocation: int c[] = {1,2,3}
Passing arrays using call by value and call by reference. What is the difference?
In Java the arrays are passed always call by reference. If only a single value is passed
then call by value is used.
To pass array c[] into a method use just the name c.
The length of the array is given by c.length if the array is c.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.24
Cont ...
When arrays are allocated, the elements are automatically initialized to zero for numeric
primitive data type variables, tofalse for boolean variables or null for references (any
non primitive data types).
The C++ declaration of an array, int c[12] produces a syntax error.
Several arrays can be declared using primitive type [] arrayName1,
arrayName2.
Similarly allocation is primitive type [] arrayName1 = new
primitive type[numeric1], arrayName2 = new
primitive type[numeric2].
For primitive data types every element of the array is one value of the declared data
type. (eg int double)
For nonprimitive data types, every element of the array is a reference to an object of the
data type of the array. eg. an element in a String array is a reference to a String
which has a value of null by default initialization.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.25
Example
import javax.swing.*;
public class InitArray {
public static void main( String args[] )
{
final int ARRAY_SIZE = 10;
int n[];
// reference to int array
String output = "";
n = new int[ ARRAY_SIZE ];
// allocate array
// Set the values in the array
for ( int i = 0; i < n.length; i++ )
n[ i ] = 2 + 2 * i;
output += "Subscript\tValue\n";
for ( int i = 0; i < n.length; i++ )
output += i + "\t" + n[ i ] + "\n";
JTextArea outputArea = new JTextArea( 11, 10 );
outputArea.setText( output );
JOptionPane.showMessageDialog( null, outputArea,
"Initializing to Even Numbers from 2 to 20",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.26
Cont ...
The final quantifier declares a constant variable. Such variables must be initialized
before they are used and cannot be modified thereafter.
Any attempt to modify a constant variable (kind of contradictory isn’t it?) produces a
syntax error.
On the other hand if any attempt is made to use a final instance variable before it is
initialized, the compiler issues an error message.
When Java program executes, the interpreter checks array element subscripts to see if
they are valid (greater than equal to zero and less than array.length). For invalid
subscripts it generates an exception.
These exceptions can be used to recover from an error rather than the entire program
crashing.
Referring to an array element outside the array bounds is a logical error.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:10
at Test.main(Test.java:5)
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.27
References and Reference Parameters
Two methods, call-by-value and call-by-reference.
With call-by-value, changes to the called method’s copy do not effect the original
variable’s value in the calling method.
Call-by-reference, the caller gives the called method the ability to directly access the
caller’s data and to modify the data if the called method so chooses.
Call-by-reference improves performance by eliminating overhead created by copying
large amounts of data.
However, call-by-reference weakens security because the called method can now
access the callers data (partial encapsulation).
Java does not allow the user to choose how data and objects are passed. Primitive data
type variables are always passed call-by-value. Objects are not passed into methods;
rather references to objects are passed. References themselves are passed
call-by-value.
An array is passed call-by=reference while its elements are passed call-by-value.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.28
Example Applet: Sorting
import java.awt.*;
import javax.swing.*;
public class BubbleSort extends JApplet {
public void init()
{
JTextArea outputArea = new JTextArea();
Container c = getContentPane();
c.add( outputArea );
int a[] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };
String output = "Data items in original order\n";
for ( int i = 0; i < a.length; i++ )
output += "
" + a[ i ];
bubbleSort( a );
output += "\n\nData items in ascending order\n";
for ( int i = 0; i < a.length; i++ )
output += "
" + a[ i ];
outputArea.setText( output );
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.29
Cont ...
// sort the elements of an array with bubble sort
public void bubbleSort( int b[] )
{
for ( int pass = 1; pass < b.length; pass++ ) // passes
for ( int i = 0; i < b.length - 1; i++ ) // one pass
if ( b[ i ] > b[ i + 1 ] )
// one comparison
swap( b, i, i + 1 );
// one swap
}
// swap two elements of an array
public void swap( int c[], int first, int second )
{
int hold; // temporary holding area for swap
hold = c[ first ];
c[ first ] = c[ second ];
c[ second ] = hold;
}
}
The above program shows a bubble short algorithm in applet form.
Larger values are made to sink to the bottom of the array while the smaller values are
floated up. The method init initializes the applet.
The method swap is used to exchange elements of an array.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.30
Example Applet: Searching
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class LinearSearch extends JApplet
implements ActionListener {
JLabel enterLabel, resultLabel;
JTextField enter, result;
int a[];
public void init()
{
Container c = getContentPane();
c.setLayout( new FlowLayout() );
enterLabel = new JLabel( "Enter integer search key" );
c.add( enterLabel );
enter = new JTextField( 10 );
enter.addActionListener( this );
c.add( enter );
resultLabel = new JLabel( "Result" );
c.add( resultLabel );
result = new JTextField( 20 );
result.setEditable( false );
c.add( result );
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.31
Cont ...
// create array and populate with even integers 0 to 198
a = new int[ 100 ];
for ( int i = 0; i < a.length; i++ )
a[ i ] = 2 * i;
}
// Search "array" for the specified "key" value
public int linearSearch( int array[], int key )
{
for ( int n = 0; n < a.length; n++ )
if ( array[ n ] == key )
return n;
return -1;
}
public void actionPerformed( ActionEvent e )
{
String searchKey = e.getActionCommand();
// Array a is passed to linearSearch even though it
// is an instance variable. Normally an array will
// be passed to a method for searching.
int element =
linearSearch( a, Integer.parseInt( searchKey ) );
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.32
Cont ...
if ( element != -1 )
result.setText( "Found value in element " +
element );
else
result.setText( "Value not found" );
}
}
To respond to an action event, the class ActionListener is defined.
The content pane is an object of class Container from the java.awt
package.
If the search key is not found a value of -1 is returned.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.33
Multiple-Subscripted Arrays
These are used to represent tables of values consisting of information arranged in rows
and columns.
Row0 Column0 of array a is indicated as a[0][0].
Columns are indicated by the RHS subscript while the rows are represented by LHS
subscripts.
Initialization: int b[][] = {{1,2},{3,4}};
Dynamic: int b[][] = new int [3][3] allocates and initializes a 3 × 3 array.
Multiple-subscripted arrays with different lengths are maintained as arrays of arrays. int
b[][] = {{1,2},{3,4,5}}. Creates integer array b with Row0 containing two
elements and Row1 containing three elements.
Allocation can be dynamic for the above case using the following
int b[][];
b = new int[2][]; // allocated rows
b[0] = new int [5]; //allocated columns for Row0
b[1] = new int [3]; // allocated columns for Row1
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.34
Example: Double Subscripted Arrays
import java.awt.*;
import javax.swing.*;
public class DoubleArray extends JApplet {
int grades[][] = { { 77, 68, 86, 73 },
{ 96, 87, 89, 81 },
{ 70, 90, 86, 81 } };
int students, exams;
String output;
JTextArea outputArea;
// initialize instance variables
public void init()
{
students = grades.length;
exams = grades[ 0 ].length;
outputArea = new JTextArea();
Container c = getContentPane();
c.add( outputArea );
// build the output string
output = "The array is:\n";
buildString();
output += "\n\nLowest grade: " + minimum() +
"\nHighest grade: " + maximum() + "\n";
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.35
Cont ...
for ( int i = 0; i < students; i++ )
output += "\nAverage for student " + i + " is " +
average( grades[ i ] );
outputArea.setFont(
new Font( "Courier", Font.PLAIN, 12 ) );
outputArea.setText( output );
}
// find the minimum grade
public int minimum()
{
int lowGrade = 100;
for ( int i = 0; i < students; i++ )
for ( int j = 0; j < exams; j++ )
if ( grades[ i ][ j ] < lowGrade )
lowGrade = grades[ i ][ j ];
return lowGrade;
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.36
Cont ...
// find the maximum grade
public int maximum()
{
int highGrade = 0;
for ( int i = 0; i < students; i++ )
for ( int j = 0; j < exams; j++ )
if ( grades[ i ][ j ] > highGrade )
highGrade = grades[ i ][ j ];
return highGrade;
}
// determine the average grade for a particular
// student (or set of grades)
public double average( int setOfGrades[] )
{
int total = 0;
for ( int i = 0; i < setOfGrades.length; i++ )
total += setOfGrades[ i ];
return ( double ) total / setOfGrades.length;
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.37
Cont ...
// build output string
public void buildString()
{
output += "
";
// used to align column heads
for ( int i = 0; i < exams; i++ )
output += "[" + i + "] ";
for ( int i = 0; i < students; i++ ) {
output += "\ngrades[" + i + "]
";
for ( int j = 0; j < exams; j++ )
output += grades[ i ][ j ] + "
";
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.38
Object-Based Programming
A solid foundation in structured-programming is essential since object-based
programming will be composed in part of structured programming pieces.
OOP encapsulates data (attributes) and methods (behaviors) into objects; the data and
methods of an object is tightly coupled.
The communication between objects is carried out using well defined interfaces; in
general one object is not allowed to know how another object is implemented (idea of
encapsulation).
Eg. Driving a car without really knowing the internals of its engine.
Java always uses a piece of an existing class definition to create a new class. You can
never really create a class definition from scratch.
Java uses a process called inheritance to create new classes from existing class
definitions.
In the following program extends Object is used to inherit the class Object from the
java.lang package.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.39
Cont ...
The new class created by inheriting will have all the attributes (data) and behaviors
(methods) of the class that is inherited as well s the new methods and data that you add.
Every class is a subclass of the class Object.
For programs with more than one class, the additional classes should be defined in
separate files and called in the main class file.
If a class does not explicitly use the keyword extends in its definition, the class implicitly
extends Object.
Within a class, the instance variables or methods declared with member access modifier
public are accessible wherever the program has reference to the object. On the other
hand if they are declared with member access modifier private they are only
accessible to the methods within the object and not when it is referenced.
In general instance variables are declared as private and the methods are declared as
public. Hence the private data can be used with the public interface but will not be able
to modify it. This is good and safe programming practice.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.40
Example: Implementing an Abstract Data Type
Time1.java class
import java.text.DecimalFormat;
// used for number formatting
// This class maintains the time in 24-hour format
public class Time1 extends Object {
private int hour;
// 0 - 23
private int minute;
// 0 - 59
private int second;
// 0 - 59
// Time1 constructor initializes each instance variable
// to zero. Ensures that each Time1 object starts in a
// consistent state.
public Time1()
{
setTime( 0, 0, 0 );
}
// Set a new time value using universal time. Perform
// validity checks on the data. Set invalid values to zero.
public void setTime( int h, int m, int s )
{
hour = ( ( h >= 0 && h < 24 ) ? h : 0 );
minute = ( ( m >= 0 && m < 60 ) ? m : 0 );
second = ( ( s >= 0 && s < 60 ) ? s : 0 );
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.41
Cont ...
// Convert to String in universal-time format
public String toUniversalString()
{
DecimalFormat twoDigits = new DecimalFormat( "00" );
return twoDigits.format( hour ) + ":" +
twoDigits.format( minute ) + ":" +
twoDigits.format( second );
}
// Convert to String in standard-time format
public String toString()
{
DecimalFormat twoDigits = new DecimalFormat( "00" );
return ( (hour == 12 || hour == 0) ? 12 : hour % 12 ) +
":" + twoDigits.format( minute ) +
":" + twoDigits.format( second ) +
( hour < 12 ? " AM" : " PM" );
}
}
Next we write the utility program to use the Time1.class
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.42
Cont ...
TimeTest.java class
import javax.swing.JOptionPane;
public class TimeTest {
public static void main( String args[] )
{
Time1 t = new Time1(); // calls Time1 constructor
String output;
output = "The initial universal time is: " +
t.toUniversalString() +
"\nThe initial standard time is: " +
t.toString() +
"\nImplicit toString() call: " + t;
t.setTime( 13, 27, 6 );
output += "\n\nUniversal time after setTime is: " +
t.toUniversalString() +
"\nStandard time after setTime is: " +
t.toString();
t.setTime( 99, 99, 99 ); // all invalid values
output += "\n\nAfter attempting invalid settings: " +
"\nUniversal time: " + t.toUniversalString() +
"\nStandard time: " + t.toString();
}
}
JOptionPane.showMessageDialog( null, output,
"Testing Class Time1",
JOptionPane.INFORMATION_MESSAGE );
System.exit( 0 );
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.43
The Execution Sequence
Every class in Java is part of a package. Similar to classes from the Java API.
If the programmer does not specify the package for a class, the class is
automatically placed in the default package which includes the compiled
classes in the current directory. This is the manner in which Time1 is found.
That is, if a class is in the same package as the class that uses it, an import
command is not required. The classes from the Java API are not in the current
package and would require an import command.
Note that the objects and variables are created in a consistent state using
what is known as the constructor associated with the class.
Note that the instance variables are all initialized in Time1() so that no illegal
values are created. Any subsequent attempt to instantiate the class object will
also be scrutinized by Time1().
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.44
Time Out: Applets, How and Why
Java applets are byte code that can be executable in web browsers.
An applet is created by inheriting the class JApplet. Here JApplet is called the base
class while the newly created applet is called the subclass or derived class.
The predefined start up sequence of an applet involves the methods init, start and
paint (optional) as it executes.
Once the class file is created using javac, the applet can be viewed using a web
browser and the <applet> tag.
The same can be achieved using appletviewer as well.
In both the above cases, the version used should be compatible, otherwise a class
loading error can occur. Note that SDK versions 1.2 and above are compatible.
In general web browsers save a copy of the applet in temporary memory when it loads it.
Hence and subsequent changes to the applet may not be reflected till all the instances of
the web browser are closed and reopened. Reload button does not achieve this.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.45
Objects: What are they?
In Java the unit of programming is the class from which objects are created
(instantiated).
The objects that are created will work together to implement the system.
As noted previously all Java objects are passed by reference (only a memory
address is passed and not a copy of, possibly a large object).
Object creation may require some initialization; to facilitate this a special
method called the constructor is placed in a class.
When objects are instantiated the first method that it calls is the constructor.
Once instantiated, public methods associated with the object can be
accessed using the dot notation.
Note that the private methods are only accessible within the class and are
not accessible using the dot notation.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.46
Constructors
Each class will have a constructor, implicitly or explicitly.
The constructor will have the same name as the class.
The constructor will not have a return type.
The declaration line of a constructor is
public ClassName()
Attempting to specify a return type such as void to a constructor will give no
error at compilation time, however, the constructor will not be called at the time
of object instantiation.
The reason for the above is because the constructor becomes a common
method with the declaration of a return type.
A default constructor with zero arguments is added to the class by the
compiler implicitly if its not defined. If any other constructor is defined this
does not happen automatically.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.47
Cont ...
Any number of constructors with different arguments can be chosen.
When defining constructor variables, care must be taken not to hide or
shadow the instance variables.
double x,y;
public Ship(double x, double y){}
presents a problem because of this. A better method is to define
double x,y;
public ship(double x, double y){
x = x;
y = y;
}
This is legal but not to useful, hence reassign as
double x,y;
public ship(double inputX, double inputY){
x = inputX;
y = inputY;
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.48
Scope and Controlling Access to Members
Inheritance creates a hierarchy in the objects using superclass and subclass.
A direct superclass of a subclass is when the subclass explicitly inherits using
the extends keyword.
An indirect superclass is when the inheritance is from two or more levels up in
the class hierarchy.
Note that Java does not support multiple inheritances as in C++.
The notion of interfaces help Java achieve most of the uses of multiple
inheritance without the associated problems.
In a inheritance, the subclass adds instance variables and instance methods
of its own. This means the subclass can replace or add to the features that are
in the superclass.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.49
Cont ...
Al of these are for variable or method modifiers in the superclass.
public: These can be accessed by anyone who can access an instance of the class.
This includes subclasses and classes in the same package.
protected: subclass methods and methods of other classes in the same package as
the superclass can access protected superclass members. Variables and methods
that are protected can cross package boundaries through inheritance. However unlike
public modifier, the protected modifier variables and methods cannot be accessed
by instantiating if they are not in the same package.
private: superclass members that are private cannot be accessed in a subclass
derived through inheritance.
No modifier (default): These variables and methods can be accessed by methods within
the class and within classes in the same package but is not inherited by subclasses.
Variables and methods with default visibility cannot cross package boundaries through
inheritance.
If a subclass could access its superclass’s private members, it would be possible for
the classes derived from the subclass to access that data as well and so on (destroys
encapsulation).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.50
Access Within Same Class
/* AccessTest1.java */
import java.lang.*;
public class AccessTest1 {
public static void main (String [] args) {
SameClass t = new SameClass (1,2,3,4);
System.out.println("Access SameClass from within main");
t.accessPrivate();
t.accessPublic();
t.accessProtected();
t.accessUnspecified();
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.51
Cont ...
/* SameClass.java */
public class SameClass{
private int var1;
public int var2;
protected int var3;
int var4;
public SameClass(int x, int y, int z, int w) {
var1 = x; var2 = y; var3 = z; var4 = w;
}
public void accessPrivate() {
System.out.println("var1 (private) accessed within class: " + var1);
}
public void accessPublic() {
System.out.println("var2 (public) accessed within class: " + var2);
}
public void accessProtected() {
System.out.println("var3 (protected) accessed within class: " + var3);
}
public void accessUnspecified() {
System.out.println("var4 (unspecified) accessed within class: " +
var4);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.52
Classes Within the Same Package
Since both AccessTest1 and SameClass are in the same package, we can simulate the
above condition by using the following modifications in AccessTest1.java.
// AccessTest2.java
import java.lang.*;
public class AccessTest2 {
public static void main (String [] args) {
SameClass t = new SameClass (1,2,3,4);
System.out.println("Access variables of SameClass from within main");
System.out.println("var1 in SameClass: "+ t.var1);
System.out.println("var2 in SameClass: "+ t.var2);
System.out.println("var3 in SameClass: "+ t.var3);
System.out.println("var4 in SameClass: "+ t.var4);
}
}
Access to var1 will generate an error.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.53
Access in Subclasses
// ParentClass.java
public class ParentClass {
private int var1=1;
public int var2=2;
protected int var3=3;
int var4=4;
}
// SubClass.java
public class SubClass extends ParentClass{
public void accessPrivate() {
// System.out.println("var1 (private) accessed from SubClass: " + var1);
System.out.println("var1 (private) Cannot be accessed from SubClass");
}
public void accessPublic() {
System.out.println("var2 (public) accessed from SubClass: " + var2);
}
public void accessProtected() {
System.out.println("var3 (protected) accessed from SubClass: " + var3);
}
public void accessUnspecified() {
System.out.println("var4 (unspecified) accessed from SubClass: " +
var4);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.54
Cont ...
// AccessTest3.java
import java.lang.*;
public class AccessTest3 {
public static void main (String [] args) {
SubClass t = new SubClass ();
System.out.println("Access SubClass from within main");
t.accessPrivate();
t.accessPublic();
t.accessProtected();
t.accessUnspecified();
}
}
The private variable in ParentClass is not inherited.
Any unspecified modifier defaults to private (protects encap). However this program will
not generate an error for t.accessUnspecified();. The reason is that even though
subclasses do not inherit unspecified access modifier variables the two classes are in
the same package (default package). Then it has access.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.55
Access in Subclasses: Different packages
// SubClass.java
import java.lang.*;
import myclass.ParentClass;
public class SubClass extends ParentClass{
public void accessPrivate() {
// System.out.println("var1 (private) accessed from SubClass: " + var1);
}
public void accessPublic() {
System.out.println("var2 (public) accessed from SubClass: " + var2);
}
public void accessProtected() {
System.out.println("var3 (protected) accessed from SubClass: " + var3);
}
public void accessUnspecified() {
//
System.out.println("var4 (unspecified) accessed from SubClass: " + va
}
}
unspecified defaults to private in this case.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.56
Classes in Different Packages
import java.lang.*;
import myclass.ParentClass;
public class AccessTest4 {
public static void main (String [] args) {
ParentClass t = new ParentClass ();
System.out.println("Access ParentClass from within main");
System.out.println("Private var1 from main: " + t.var1);
System.out.println("Public var2 from main: " + t.var2);
System.out.println("Protected var3 from main: " + t.var3);
System.out.println("Unspecified var4 from main: " + t.var4);
//
//
//
}
}
For classes in different packages, only the public variables and methods are seen.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.57
Visibility: Access Modifier Summary
Variable or Method Modifier
Variables or Methods with this
Modifier can be accessed by
Methods in:
No Modifier
(default)
public
private
protected
Same class
Y
Y
Y
Y
Classes in same package
Y
N
Y
Y
Subclasses
Y
N
Y
N
Classes in different packages
Y
N
N
N
Other Modifiers
static:
The variable or method is shared by all the instances of the class.
These can be accessed by class name instead of just by an instance. eg. If class
FOO had a static variable bar and there is an instance of FOO called FOO1, the
static variable can be accessed as FOO.bar or FOO1.bar which would mean the
same.
static methods can only refer to static variables or other static methods unless they
create an instance.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.58
Cont ...
public class Statics {
public static void main (String [] args) {
staticMethod();
Statics s1 = new Statics();
s1.regularMethod();
}
public static void staticMethod() {
System.out.println("This is a static method");
}
public void regularMethod() {
System.out.println("This is a regular method");
}
}
One can see that main can refer directly to staticMethod while it requires
an instance to access regularMethod. Reason: static variables and
methods exists prior to instantiation.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.59
Cont ...
final:
The final modifier indicates that it cannot be subclassed.
Essentially it cannot be changed at runtime or overridden in a
subclass.
abstract:
This can be applied to classes or methods to indicate that the
class cannot be directly instantiated. These are used when you want
to provide a common behavior in the class but yet not create objects
out of it.
public abstract class Shape {
protected int x,y;
public int getX() {
return(x);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.60
Cont ...
The method that is defined with only a return type and no body is considered an abstract
method. A class that contains such a method must be declared as abstract. An
example of it is:
public int getY(int Y);
A subclass of such a class must also be declared abstract unless they implement all of
the abstract methods in the superclass. The reasoning behind this is that if the subclass
implements all of the abstract methods, they will be overridden in the subclass.
The above technique is used when you want to require all members of a class to have a
certain general categories of behavior but where each member of the class will
implement the behavior slightly differently.
The Shape class that is defined does not have any abstract methods. Hence the
subclass can be defined as abstract or concrete.
The subclass is generated as follows
public abstract class Curve extends Shape {}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.61
Creating Packages
Each class and interface in a Java API belongs to a specific package that
contains a group of related classes and interfaces.
Packages are in fact actually directory structures used to organize classes and
interfaces.
Packages also become useful to provide a convention for unique class names.
However once encapsulated in a package, similar names can be resolved.
Define a public class. Note that if the class is not public, it can be used only
by other classes in the same package. i.e. it has package scope.
Choose a package name and add a package statement to the source code.
Eg. package iics.example.pac. Such a statement will place the class at
compile time in a package with the given directory structure.
The root where the directory structure is created is jdk1.2.4/jre/class.
However this can be changed with the -d option of javac
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.62
Cont ...
When no member access modifier is provided for method variable in a class, it
is assumed to have package access.
Package access enables objects of different classes to interact without the
need for interface methods that can set and get variables, thus eliminating
some of the method call overhead.
In some sense, the package access method destroys the encapsulation
concept of OOP.
If it is not specified, Java will look for packages only in the current directory
(default package) and the directories specified by the CLASSPATH variable.
Entries in the CLASSPATH can be simple .class files or .jar (compressed)
files.
The class path can be specified in two ways, one to give the -classpath
option to javac or set the environment variable CLASSPATH.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.63
Example: package usage
Here is an example to show how the same name can be used for a class and still be able to
separate them out within the executable program.
// classes/package1/Class1.java
package package1;
public class Class1 {
public static void printInfo() {
System.out.println("Class1 in package1");
}
}
// classes/package4/Class1.java
package package4;
public class Class1 {
public static void printInfo() {
System.out.println("Class1 in package4");
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.64
Cont ...
// classes/PackageExample.java
import package1.*;
public class PackageExample {
public static void main(String [] args) {
Class1.printInfo();
package4.Class1.printInfo();
}
}
Compile and Run
javac PackageExample.java
java PackageExample
Output
Class1 in package1
Class1 in package4
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.65
Using JAR Files
Java ARchive (JAR) files are a convenient method to move large package
hierarchies around.
This is the only manner in which class paths can be specified if your
environment variable CLASSPATH exceeds the number of characters allowed.
the JDK includes an executable tool called jar that can compress multiple
class files into a single JAR file.
An example use
jar cfv example.jar package1 package2
Once the JAR file is created its location can be added to the CLASSPATH
variable or be places in jdk1.4/jre/lib/ext where Java automatically
looks for class files.
The usage and importing is similar to a regular class file.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.66
Finalizers
Constructors initialize objects and Finalizers aids garbage collection and
returning resources back to the system.
Note that Java performs automatic garbage collection when an object is no
longer referenced in the program.
The class Object has a method called finalize which is automatically
called.
finalize takes no input and returns no values.
Each class should have only one finalizer.
If a finalizer is not defined in a class the one in Object is called. If a finalizer
is defined in a class it is called before calling finalize in the Object class.
The definition of a finalizer is protected void finalize()
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.67
Constructors and Finalizers in a Subclass
The subclass constructor does not explicitly call a constructor in the super
class other than the default constructor which does not take any arguments.
If the superclass does not have a zero argument constructor, then a compile
error is generated when the subclass is compiled.
If a zero-argument constructor exists in the super class, it is called before any
code is executed in the subclass constructor.
Note that the compiler will add the default constructor into any class if its not
defined, however if an overloaded constructor is defined the compiler will not
any constructor.
If an overloaded constructor in the super class is to be called use the keyword
super to call it.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.68
Cont ...
public class ChildClass extends ParentClass {
public Childclass(duble z) {
super(z); // Call ParentClass’s constructor
....
}
}
Note that super should be the first statement in the subclass constructor, else it
will generate an error.
Through inheritance the methods that existed in the superclass can be
overridden. However in order for this to happen the subclass should have a
method that has the same method name and the same parameter list and the
return type.
However if the method of the superclass needs to be accessed it can be done
via super.OverriddenMethod(...).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.69
Cont ...
If you are down in the inheritance hierarchy, you cannot use super.super to
access overridden methods higher up in the inheritance hierarchy.
All other non-overridden methods are available for use in the subclass without
any hinderance.
The visibility of an overridden method can be changed of needed. Eg. A
method declared protected in the parent class can be redeclared as
public in the child class.
You can also override variables inherited from the parent class too. However
this is NEVER done in practice.
The reason for the above is; an instance of the child class will have two
variables with the same name– one variable is exposed when a method is
executed in the child class and the other variable is exposed when an
inherited method is executed in the parent class. Debugging becomes difficult
to say the least.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.70
Implementation of Interfaces
Interfaces look like abstract classes where all the methods are abstract.
Unlike in an abstract class being used as a superclass, a subclass can directly
implement multiple interfaces. Note that Java can directly extend only a single class.
A class that implements an interface must either provide definitions for all the methods or
declare itself abstract as in the case of abstract classes.
public interface Interface1 {
int Shape1(int x);
int Shape2(int y);
}
All methods in an interface are abstract.
The public declaration for methods is optional since all methods in an interface are
implicitly public.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.71
Using Interfaces
public class Class1 extends SomeClass implements Interface1 {
public int Shape1(int x) {
Some code here;
}
public int Shape2(int y) {
Some code here;
}
Other code;
}
Note that since Class1 is not declared as abstract, all the methods that are
inherited from Interface1 should be implemented.
Interfaces can be used to selectively inherit behaviors.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.72
Multiple Interface Inheritance
public interface Interface2 {
int Shape3(int z);
}
The program segment given below outlines a class with two interfaces.
It is declared as abstract hence one does not have to implement all
interface methods.
public abstrace class Class2 extends SomeClass implements
Interface1, Interface2 {
Some code unrelated to the methods in the interface;
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.73
Building Concrete Classes
An abstract class as one given above can be used to instantiate a concrete
class if all the methods are implemented
public class Class3 extends Class2 {
public int Shape1(int x) {
some code;
}
public int Shape2(int y) {
some code;
}
public int Shape3(int z) {
some code;
}
Other code in Class3;
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.74
Extending Interfaces
Interfaces cannot be instantiated since they have abstract methods.
However they can extend (not implemented) one or more other interfaces. Hence the
hierarchy can be built as in classes.
Note that such extended interfaces cannot have instance variables such as in classes.
However constants can exist. Such constants will implicitly have thepublic, static
and final modifiers implicitly associated with it. Hence they are usually left out of the
declaration.
public Interface Interface3 extends Interface1, Interface2 {
int MIN_VAL = 0;
int MAX_VAL = 100;
}
The naming convention of an interface is similar to a class.
It is widely accepted that the interface class names end in “able”. For example
Measurable
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.75
Benefits of Inheritance
Software Reusability:
When behaviors are inherited, the code that provides the
behavior need not be rewritten.
Increased Reliability:
Smaller objects can be debugged easily to form reliable
pieces of code.
Code Sharing:
Unlike procedural programming many of the code segments are
written only once and reused within the program repeatedly.
Consistency of Interface:
When two or more classes inherit from the same super
class, the behavior they inherit will be identical.
Software Components:
Eg. Java libraries provide extensive application support
Rapid Prototyping:
Software systems can be generated more quickly because
behaviors are inherited rather than created.
Information Hiding:
Connection between software components is reduced since
one need not know what the internals of an object when it is used.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.76
The Costs of Inheritance
Execution Speed:
The inherited code is slower than specialized code
due to additional overhead. However the decrease in speed is amply
made up by the efficiency of the code so that the detrimental effects is
small.
Program Size:
The use of general software libraries increase the
program size as opposed to specific program code.
Message-Passing Overhead:
The message passing is by nature more
costly than a simple procedure call. However the increase cost should
be look upon in the light of all the befits that it brings.
Program Complexity:
Over use of inheritance hierarchies can increase
the complexity of the program and prove counter productive.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.77
Is-a Rule and Has-a Rule in Inheritance
is-a relationship
This relationship holds between concepts when the first is a specialized instance of the
second. Eg. Dog is-a Mammal, Rectangle is-a Polygon.
The behavior and data associated with the more specific data from a subset of the
behavior and data associated with the more abstract data.
The is-a relationship takes two forms; Inheritance of code and Inheritance of behavior.
If the two concepts share structure and code inheritance is carried out with extends. If
the two concepts share the specification of behavior (methods), but no actual code, then
use implements to formulate inheritance.
has-a relationship
This relationship holds when the second concept is a component of the first but the two
are not in any sense the same thing, no matter how abstract the generality. eg. Car
has-a Engine.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.78
Composition and Inheritance
Composition
Composition is formed out of instantiation of objects that already exists. This
implies no substitutability implicitly or explicitly.
Though one class inherits the functionality of the inherited class using
instantiation, the two classes are completely distinct.
Composition is a manifestation of has-a relationship
Inheritance
In this method, the data and behavior are inherited using a mechanism of
subclasses and super classes. Here some of the methods can be redefined.
Hence there is an explicit implication of substitutability (i.e. Overriding)
Inheritance is a manifestation of is-a relationship.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.79
Example
Vector Class
class Vector {
public int size () {....}
//other methods and code
}
Using Vector with a class Stack using composition:
class Stack {
private Vector theData;
public Stack () {
theData = new Vector();
}
// other methods and code
}
Using Vector with a class Stack using inheritance:
class Stack extends Vector {
// other code in the class.
// does not require construction
// does not require dot notation to access methods.
}
In the composition one does not need the constructor to initialize the instance we could have
. - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.80
used private Vector thedata = new Vector()
PR 2015
Composition and Inheritance Contrasted
Inheritance carries with it an implicit if not explicit assumption of substitutability.
Composition is the simpler of the two techniques. Its advantage is that it more
clearly indicates exactly what operations can be performed on a particular
data structure. This is so because no substitution of behavior occurs.
In inheritance one has to know how the super class behaves to know what
operations are legal.
Using inheritance one does not need to write additional code to access the
information within the inherited class. In composition the class has to be
constructed and a dot notation used to address the information within the
inherited class.
In inheritance one can add to the behavior the class and also manipulate the
behavior of the parent class using new methods.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.81
Cont ...
With inheritance the subclass has access to the protected part of the parent
class. In composition it has access only to the public part of the parent class.
Inheritance allows the notion of polymorphism while composition does not.
The reason being the absence of substitutability in composition.
The composition code can be understood even if the parent class code is not
known. However with inheritance the behavior of the methods are hard to
understand because of overriding etc. Hence in inheritance for proper
utilization one has to understand both classes.
Execution time with inheritance is slightly shorter than with composition. That
is overhead is smaller in inheritance.
With composition the binding of new classes is dynamic while with inheritance
it has to be bound at creation. Sometimes this is called dynamic composition.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.82
Example
Here is an example of dynamic composition.
FrogBehavior
public abstract class FrogBehavior {
public boolean growUp() {return false;}
public void grow();
}
TadpoleBehavior
public class TadpoleBehavior extends FrogBehavior {
private int age = 0;
public boolean growUp() {
if (++age >> 24)
return true; }
public grow () { ... }
}
AdultFrogBehavior
public class AdultFrogBehavior extends FrogBehaior {
public void grow () { ... }
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.83
Note that both the above classes are not abstract, and why they are not.
Cont ...
Frog:
Driver program.
public class Frog {
private FrogBehavior behavior;
public Frog() {
behavior = = new TadpoleBehavior();
}
public grow () {
if (behavior.growUp())
behavior = new AdultFrogBehavior();
behavior.grow();
}
}
With inheritance the link between the child class and the parent class is
established at compile time. However with composition it can be created at
run time.
Here we see that polymorphically the behavior instance can be attached to
the appropriate behavior as the Frog grows up to be an adult.
Note how the different functions are from different classes as the program
progresses down.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.84
Combining Inheritance and Composition
Using Instances
public class ChildClass extends ParentClass {
protected ParentClass pc;
....
}
In the above program the functionality of the ParentClass is explicitly in
ChildClass using inheritance. However a nother special instance of the
ParentClass is included using composition to handle, maybe, some specific
instance of the ParentClass functionality.
Another advantage of such a mix is the ability to use dynamic binding using
composition at a later stage of the execution.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.85
Cont ...
Using Inner Class Definitions
Inner classes can be complete class definitions or anonymous inner class
definitions.
An inner class object is allowed to access directly all the instance variables
and methods of the outer class that defined it.
An inner class defined in a method is allowed to access all the instance
variables and methods of the outer class object that defined it and any final
local variables in the method.
Compiling a class that contains inner classes result in separate class files for
every class. Inner classes with names will have a file name
OuterClass$Innerclass.class and anonymous inner classes will have
names OuterClass$#.class where the hash will start from 1 and
increment for each new anonymous class fond during compilation.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.86
Cont ...
The outer class is responsible for creating objects of its inner classes. To
create an object of another class’s inner class, first create the object of the
outer class and assign it to a reference OCref. Then use the follows
OuterClass.InnerClass innerInstance = OCref.new InnerClass ();
A static inner class does not have access to the outer class’s non-static
members. Furthermore, to instantiate a static inner class, one does not need
to instantiate an object of its outer class
For anonymous classes, only one instance of this class is created.
The only advantage of anonymous classes is that we can avoid writing a new
definition of a class and creating an instance. However the downside is that
the code becomes unreadable and complicated.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.87
Inner Class Examples
Inner class
public class OuterClass extends SomeClass1 {
....
private class InnerClass extends SomeClass2 {
....
}
....
}
Anonymous class
public class OuterClass extends SomeClass1 {
...
private someMethod (
new AnonymousClass () {
...
...
}
);
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.88
Form of Inheritance
Inheritance for Specialization
The child class satisfies the specification of the parent class.
public class ChildClass extends ParentClass {
....
}
The methods in the child class do not know they are manipulating
methods of the parent class.
The above is true if the child class does not override any parent class
method.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.89
Cont ...
Inheritance for Specification
The child class maintains a certain common interface by
implementing the same methods given in the parent class.
The implementation of the parent class methods are deferred to the
child class.
public class ChildClass implements ParentClass {
...
An abstract parent class used to create a concrete child class also
falls into this type of inheritance.
In short, the child class implements the deferred methods to a
specification.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.90
Cont ...
Inheritance for Construction
This occurs when you inherit methods from a class with which one
does not have a is-a relationship but conceptually the methods may be
used except perhaps change the names of the methods.
An example is when one builds the Stack class using the Vector
class. (Explain).
Another example is constructing a class call Hole extending a class
called Ball. The parameter used in the latter may have the same
functional behavior for some of the methods required for the previous.
This is frowned upon since it breaks the principle of substitutability.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.91
Cont ...
Inheritance for Extension
The child class does not override any of the methods inherited from
the parent class.
However new methods will get added in the child class, hence
extends the parent class functionality.
Here the principle of substitutability is not used.
public class ChildClass extends ParentClass {
// methods that so not appear in ParentClass
// instance variables that do not appear in
// the parent class
}
Inheritance from abstract ParentClasses are not included here.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.92
Cont ...
Inheritance for Combination
The child class simulated multiple inheritance.
One method of achieving this is to extend one class and implement
several others.
public class ChildClass extends Cat1 implements Cat2
// implements all of Cat2 at least
}
This simulates combining several categories of methods.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.93
The Polymorphic Variable
class Shape {
protected int x;
protected int y;
public Shape (int ix, int iy) {
x = ix; y = iy;
}
public String describe () {
return "Unknown Shape";
}
}
class Square extends Shape {
protected int side;
public Square (int ix, int iy, int is) {
super(ix,iy);
side = is;
}
public String describe () {
return "Square with sides " + side;
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.94
Cont ...
class ShapeTest {
static public void main (String [] args) {
Shape form = new Shape (1,2);
System.out.println("form in " + form.describe());
form = new Square (3,4,5);
System.out.println("form is " + form.describe());
}
}
A polymorphic variables is one which is defined as one type but at times holds
different types.
With the existence of this type of variable, one cannot determine the memory
requirement at the compile time. Hence all allocations reside in a heap in
memory.
The other method it to assign the memory in a stack of the allocation is known
at run time. By doing this, you will create copies of the object at runtime for
use.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.95
Cont ...
With heap allocation one has to just assign the reference to the location in the
heap rather than making a new copy. Hence references are built in for Java.
This method is similar to the dynamic combination technique discussed earlier.
The output of the first statement comes from the Shape class while the output
from the second statement comes from the Square class.
In summary, the polymorphic variable is used in the following manner: We use
a super class reference to refer to a subclass object and invoke the
polymorphic variable (which is a method), then the program will choose the
appropriate implementation from the subclass dynamically (at execution time)
as each subclass is chosen as the object.
Note that when a subclass chooses not to redefine a method, the subclass
simply inherits its immediate super class’s method definition.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.96
A more Simpler Implementation
For this example we assume that classes called Circle, Triangle, Rectangle
and Square are all created by extending Shape class which has a method area,
and that each class redefines this method appropriately.
Shape currentShape = new Shape ();
switch(type) {
case 1:
currentShape = new Circle(..,..);
break;
case 2:
currentShape = new Triangle(..,..,..);
break;
case 3:
currentShape = new Rectangle(..,..);
break;
case 4:
currentShape = new Square(..);
break;
default:
Syste.out.println("....");
}
However this may not be the optimum method of implementing polymorphism.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.97
Final Methods and Classes
Previously we have seem that variables that are declared final have to be
initialized when they are declared and cannot be modified thereafter.
A method that is declared as final cannot be overridden in a subclass.
Methods that are declared static and private are implicitly final.
All methods in a final class are final.
A class that is declared final cannot be super classed. That is one cannot
inherit from a final class.
At compile time, the compiler replaces calls to final methods with the explicit
code, this is called in-lining code. This improves performance because the
overhead of a method call is no longer there.
Such classes or methods cannot be used polymorphically.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.98
Polymorphic Variable and Memory Layout
Two main categories of memory values; stack-based and heap-based.
Stack based memory locations are tied to the method try and exit: at entry the
space is allocated on a run-time stack for local variables and the memory is
recovered at exit.
Since the memory for stack-based is allocated as a block for a method, it is
easier to deallocate in a block as well.
Once the allocation block is known the individual variables are addressed
using an offset.
For stack-based memory the actual space for each variable has to be known
at compile time. This is because the offsets to the variables ae determined at
compile time and not at run time.
However for a polymorphic variable this information is not know at compile
time but determined at run time. Hence this type of memory allocation is not
suitable for it.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.99
Cont ...
The solution is to use heap-based memory allocation. These are not tied to
method entry and exit.
A heap is created and memory allocated at run time when the demand is
explicitly known. Allocation on the heap is carried out using the new operator.
The memory is recycled and given back to the heap when the object is no
longer in use or in scope.
At compile time the memory allocation is carried out in a stack using pointers.
For pointers the compiler known exactly how much memory is required. This
is required since in the executable the addressing should be compiled in.
Now the compiler can code the executable so that the variables a addressed
still using a offset.
At run time the pointer field is filled when the object is created.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.100
Memory Allocation Examples
In Java, values are naturally maintained in a heap rather than a record in a
stack.
Consider the following example: In Java x and y refer to the same location. In
any other programming language they have two distinct locations. y is not a
copy of x.
Box x = new Box();
Box y = x;
pointer allocated on a stack
x
allocated on heap
a Box instance
y
pointer allocated on a stack
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.101
Cont ...
If the desired effect is a copy process, then the programmer has to write code
explicitly to copy the contents of one class variables into the other.
For example if there is a method called copy which achieves this the following
declaration will copy the contents on x into y
Box y = x.copy();
In Java comparison of objects in a equality operation will convert one type to
the other before checking for equality.
The reasoning behind this is that an object pointer can hold in its field several
different instances polymorphically. Hence == should be used only when
comparing numeric qualities and when testing an object against null. For all
other cases write a method that checks for equality.
Since heap allocation is not tied on to method entry and exit, Java will
intermittently see when objects are no longer used and release them into the
heap for reuse.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.102
Types of Polymorphism
Polymorphism is a natural result of is-a relationship and of substitutability.
In pure polymorphism, there is one function and a number of different
interpretations of it. An example of the program we saw in the previous
section.
Ad hoc polymorphism on the other hand has number of different functions all
denoted by the same name. An example of this is overloading.
Between these two extremes are the overriding and the deferred method
leading to polymorphic behavior.
Another form is coercion polymorphism where the values are coerced into
changing its type depending on the function. For example if there is only one
function to compute real + real, then any values into this function will be
coerced into changing its type to real.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.103
Overloading
A method name is overloaded if two or more function bodies are
associated with it. Note that overloading can occur without overriding.
In overloading it is the method name that is polymorphic.
There are two methods of overloading
The method name overloading occurs in two or more classes that
are not linked by inheritance.
The method name overloading occurs with two or more methods
within one class or if one is inherited from another class.
The second kind mentioned above leads to what is known as
parametric overloading.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.104
Overriding
Overriding comes in two forms: Replacement and Refinement.
In replacement, a method in the parent class is completely replaced by a
method in the child class, in which case the code in the parent class is not
executed at all.
In a refinement, the parent class code is combined with the child classes code
to construct the method.
An example of a refinement is:
class Child extends Parent {
public void childMethod (...) {
super.parentMethod(...);
...
}
}
Constructors always use the refinement technique.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.105
Pure Polymorphism
This name is reserved for a method that can be used with a variety of
arguments. The appropriate method is chosen depending on the argument.
In its implementation it will finally call a method that is overridden.
PolyClass1.java
public class PolyClass1 {
void identify () {
System.out.println("This is in PolyClass1\n");
}
}
PolyClass2.java
public class PolyClass2 extends PolyClass1 {
void identify () {
System.out.println("This is in PolyClass2\n");
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.106
Cont ...
PrintClass.java
public class PrintClass {
void printNow(PolyClass1 pc1) {
pc1.identify();
}
}
PolyTest.java
class PolyTest {
public static void main(String [] args) {
PrintClass pc = new PrintClass();
PolyClass1 pc1 = new PolyClass1();
PolyClass2 pc2 = new PolyClass2();
pc.printNow(pc1);
pc.printNow(pc2);
}
}
We see that each time we add another PolyClass class, the rest of the
program can remain the same while the calling function will accept any type of
class. This can be done only if the classes are in an inheritance hierarchy.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.107
Exception Handling
An exception is an event that occurs during the execution of a program that
disrupts the flow of instructions and prevents the program from continuing
along its normal course.
In Java, the compiler can refuse to recognize any use of a method that does
not handle a possible exception. For example opening a file for read. A
possibility is that the file might not exist.
The exceptions are handled in a try/catch block in the program.
Note that when an exception does not occur, little or no overhead is imposed
by the presence of exception handling code. However when face with an
exception they do incur execution-time overhead.
If a method detects an error it will throw and exception. However it may or may
not be caught depending on whether you have anything out there to catch the
exception.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.108
Exception Handling (Cont ...)
A try block can be followed by zero or more catch blocks. Each catch block will
handle a different kind of exception.
At the end of a series of catch blocks a finally block appears. This block
provides code that will get executed regardless whether an exception occurs.
If there are no catch blocks after a try block, a finally block is required.
The finally block can be used to prevent resource leaks to release resources
since this gets executed anyway.
Once the execution leaves a try block, it will search in order for any
appropriate catch blocks.
One can also specify what type of exception a method throws by using the
throws keyword.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.109
Example
try {
.....
....
}
catch (ExceptionType1 ref1) {
....
....
}
catch (ExceptionType2 ref2) {
....
....
}
finally {
....
....
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.110
Exception Handling Example - Method 1
import java.lang.ArithmeticException;
import javax.swing.JOptionPane;
public class ExceptionHandler {
public static float findQuotient(float x, float y)
throws ArithmeticException {
if (y==0)
throw new ArithmeticException();
return x/y;
}
public static void main (String args []) {
String a,b;
float c,d,e;
a = JOptionPane.showInputDialog("Enter first number");
b = JOptionPane.showInputDialog("Enter second number");
c = Float.parseFloat(a);
d = Float.parseFloat(b);
try {
e = findQuotient(c,d);
JOptionPane.showMessageDialog(null, "The division is " + e);
} catch (ArithmeticException excep) {
JOptionPane.showMessageDialog(null,"Divide by zero!");
}
System.exit(0);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.111
Exception Handling Example - Method 2
NewExceptionHandler.java
import java.lang.ArithmeticException;
import javax.swing.JOptionPane;
public class NewExceptionHandler {
public static float findQuotient(float x, float y)
throws MyArithmeticException {
if (y==0)
throw new MyArithmeticException();
return x/y;
}
public static void main (String args []) {
String a,b;
float c,d,e;
a = JOptionPane.showInputDialog("Enter first number");
b = JOptionPane.showInputDialog("Enter second number");
c = Float.parseFloat(a);
d = Float.parseFloat(b);
try {
e = findQuotient(c,d);
JOptionPane.showMessageDialog(null, "The division is " + e);
} catch (MyArithmeticException excep) {
JOptionPane.showMessageDialog(null,excep.getMessage());
}
System.exit(0);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.112
Exception Handling Example - Method 2 (Cont ...)
MyArithmeticException.java
public class MyArithmeticException extends ArithmeticException{
public MyArithmeticException() {
super("Divide by zero error");
}
}
Here the exception handler is redefined using a user defined class.
In this case we have extended an inherited exception handler, however this is
not necessary.
In this program we have specified what kind of exception the method is going
to throw.
If there are several catch clauses after a try block, Java executes the first
catch clause that matches the type of exception thrown.
Note the difference between throws and throw.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.113
Exception Handling Example - Method 3
URLTest.java
import java.net.*;
import java.io.*;
public class URLTest {
public static void main (String args []) {
URLTest test = new URLTest();
test.getURL();
test.printURL();
}
private URL url = null;
public URL getURL() {
if (url != null) {
return(url);
}
System.out.print("Enter URL: ");
System.out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(System.in));
String urlString = null;
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.114
Exception Handling Example - Method 3 (Cont ...)
try {
urlString = in.readLine();
url = new URL(urlString);
} catch (MalformedURLException mue) {
System.out.println(urlString + " is not valid.\n" +
"Try again.");
getURL();
} catch (IOException ioe) {
System.out.println("IOError when reading input: " + ioe);
return(null);
}
return(url);
}
public void printURL() {
if (url == null) {
System.out.println("No URL!");
} else {
String protocol = url.getProtocol();
String host = url.getHost();
int port = url.getPort();
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.115
Exception Handling Example - Method 3 (Cont ...)
if (protocol.equals("http") && (port == -1) ) {
port = 80;
}
String file = url.getFile();
System.out.println("Protocol: " + protocol +
"\nHost: " + host +
"\nPort: " + port +
"\nFile: " + file);
}
}
}
Here the exceptions are not explicitly thrown. They are generated while
executing a statement that contains a default exception.
The exceptions that can be thrown by a process can be found in the APIs.
Each API has a certain number of exceptions it generates.
This program also illustrates the use of multiple catch statements.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.116
More on Exceptions
If you write a method that potentially generates one or more exceptions and you do not
handle them explicitly, you need to declare them with the throws construct as shown in
method 2
public someType someMethod(...) throws someException { ...
If multiple exceptions are thrown by the method it can be declared as
public someType someMethod(...)
throws ExceptionType1, ExceptionType2 { ...
This declaration lets yo do the following;
it permits you to write methods that have enforced safety checking, where users are
required to handle the exception when calling the method.
It permits you to defer the exception handling to a method higher in the method call
chain by declaring them in the method declaration but ignoring them in the method
body.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.117
More on Exceptions (Cont ...)
If you want to explicitly generate an exception, use the throw construct.
These are more common with user defined exceptions.
throw new IOException("Blocked by firewall");
When an exception is thrown, control transfers directly to the catch block that
handles the error. Unless the programmer explicitly invokes the same method,
control will not return to the point at which the error occurred. This is referred
to as the termination model of exception handling.
If there exists a programming language that permits control to be returned to
the point of error, such languages are said to use the resumptive model of
exception handling.
All errors and exceptions are subclasses if Throwable. The two major
subclasses are Error (representing hard failures such as error in the byte
code representation where processing will be immediately halted) and
Exception (errors that can be handled by various methods).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.118
More on Exceptions (Cont ...)
It is generally accepted that the user defined exception classes are derived
from Exception.
Exceptions are divided into two categories.
RuntimeException: conditions that arise within the JVM. Since the
source of this type of exception can be any Java statement, the compiler
does not insist that the programmer test for or catch the errors.
IOException: These are exceptions that can occur during input output
statements. These need to be handled by the programmer.
Note that the catch (Exception e) block should be placed last in the list
of catch blocks otherwise no other catch block will be executed. In particular if
its not placed last a syntax error occurs.
Using throw e; inside a catch block will rethrow the exception to the next try
block.
The JAVADOC contains the full list of built in exceptions.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.119
More on Exceptions (Cont ...)
It is a syntax error if a catch that catches a superclass object is placed before
a catch tha catches an object of the subclass of that superclass.
If a subclass method overrides a superclass method, it is an error for the
subclass method to list mode exceptions in its throw list that the overridden
superclass method does. A subclasses’ throws list can contain s subset of a
superclass’s throws list.
Exceptions thrown in constructors cause objects built as part of the object
being constructed to be marked for eventual garbage collection.
Although it is possible to use exception handling for other purposes, this
reduces the program performance and is strongly discouraged.
If an error can be processed locally instead of throwing an exception, do so.
This will improve the performance of the program.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.120
Exception Handling Examples
public class NewHandler1 {
public static void loopGen(int [] a, int p) {
for (int i = 0; i < p; i++)
a[i] = i;
}
public static void main(String[] args) {
int a[] = new int[10];
int b[] = new int[5];
try {
loopGen(a,12);
System.out.println(
"[A] This Code here gets executed if no exception occurs");
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println(
"First catch block: it will execute if an exception is caught");
} finally {
System.out.println(
"The finally block gets executed anyway");
}
System.out.println("This code gets excuted anyway");
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.121
Exception Handler Example (Cont ...)
try {
loopGen(b,12);
System.out.println(
"[B] This Code here gets executed if no exception occurs");
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("Second set of catch blocks");
} catch(Exception e) {
System.out.println("The second catch statement in the second
block");
}
System.out.println("Code here gets executed anyway");
}
}
loopGen will return an exception if the index exceeds the array size.
The moment the exception is generated the rest of the code does not get
executed.
However between try blocks the normal code gets executed. That is one try
lock is independent of the others.
Note multiple exception handlers and the generalization.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.122
Another Example
public class NewHandler {
public static void main(String[] args) {
int a[] = new int[10];
int b[] = new int[5];
try {
try {
for (int i=0; i < 11; i++)
a[i] = i;
System.out.println(
"[A] Code here gets executed if no exception occurs");
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println(
"First catch inside which will rethrow the exception");
throw ex;
} finally {
System.out.println(
"The finally after a rethrow gets executed anyway");
}
System.out.println(
"[B]Code here gets executed if no exception occurs");
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.123
Another Example (Cont ...)
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println(
"First outer catch block which will catch the rethrow");
} catch (Exception e) {
System.out.println(
"The next block which is a generalization");
} finally {
System.out.println(
"The outer finally block, gets executed anyway");
}
System.out.println(
"Code here gets executed at all times");
try {
for (int j=0; j < 3; j++)
b[j] = j;
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("Next catch block");
}
System.out.println("Code here gets executed anyway");
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.124
Yet Another Example
GenerateException.java
public class GenerateException {
public GenerateException () {
System.out.println(
"Calls the constructor of GenerateException");
}
public void GenerateExceptionFunction ()
throws ArrayIndexOutOfBoundsException {
int a[] = new int[10];
try {
for (int i = 0; i < 11; i++)
a[i] = i;
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println(
"The exception is rethrown in GenerateException");
throw ex;
} catch (Exception ex) {
System.out.println(
"Catch Exception in GenerateException");
} finally {
System.out.println(
"This gets executed anyway in GenerateException");
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.125
Yet Another Example (Cont ...)
testException.java
public class testException {
public static void main (String args []) {
float b[] = new float[5];
try {
GenerateException ge = new GenerateException();
System.out.println(
"Now we will generate an exception");
ge.GenerateExceptionFunction();
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("Caught outside in main");
} finally {
System.out.println(
"The finally block inside main that gets executed anyway");
}
try {
for (int j = 0; j < 6; j++) {
b[j] = (float)2.0;
}
} catch (ArrayIndexOutOfBoundsException f) {
System.out.println(
"In the second block of catch - out of bounds");
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.126
Count Up
import java.util.*;
public class test
{
public static void main(String args[]) {
String j="Helloworld";
char Search=’a’;
char stackArray[]=new char[150];
StringTokenizer ST=new StringTokenizer(j);
if (ST.countTokens()>1) {
System.out.println(
"Empty characters found in the input.Please check and re-en
} else {
for(int i=0;i<j.length();i++) {
stackArray[i]=j.charAt(i);
}
for(int k=0;k<=j.length();k++) {
System.out.println(stackArray[k]);
}
int count=0;
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.127
Count Up (Cont ...)
for (int l=0;l<=j.length();l++) {
if(stackArray[l]==Search) {
count++;
System.out.println("found "+ count +" matches");
} else {
System.out.println(
"No matches of"+Search+"were found from the array");
}
}
}
}
}
import java.util.*;
public class test{
public static void main(String args[]) {
String j="Helloworld";
char Search=’a’;
int count = 0;
int i = 0;
while (j.indexOf(Search,i) != -1) {
i = j.indexOf(Search,i)+1;
count++;
}
System.out.println("The count is " + count);
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.128
}
Input and Output Streams
It is relatively uncommon to read from standard input in the Java programming
language. It is basically for non-graphical programs tha typically use the
command line arguments for the data they need. The rest of the Java
programs can use basic Swing or AWT components to input and output data.
The basis for such inputs is to turn the System.in into a BufferReader.
There are two categories of input output facilities.
stream
classes: used to manipulate 8-bit quantities.
classes: used to manipulate string and 16-bit Unicode
(2-bytes) character values.
reader/writer
Most networking software and file systems are still based around the 8-bit unit,
and for the time being these will be the more commonly used.
The primary advantage of character streams is that they make it easy to write
programs that are not dependent upon a specific character encoding
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.129
Input and Output Streams (Cont ...)
Java generally stores strings in Unicode, an international standard character
encoding that is capable of representing most of the world’s written languages.
Hence character streams can be more advantageous.
A user-readable text files may use different encodings that are not necessarily
related to Unicode. Character streams hide the complexity of dealing with
these encodings by providing two classes that serve as bridges between byte
streams and character streams viz. InputStreamReader class that reads
bytes from a byte-input stream and converts then to characters according to a
specified encoding and a similar one for OutputStreamReader.
Another advantage of character streams is that they are potentially much more
efficient than byte streams.
The byte streams are oriented around byte-at-a-time read and write
operations. On the other hand character-stream classes are oriented around
buffer-at-a-time read and write operations.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.130
InputStream Hierarchy
The subclasses of InputStream are given below
InputStream
ByteArray
InputStream
File
InputStream
Data
InputStream
Filter
InputStream
Buffered
InputStream
Piped
InputStream
LineNumber
InputStream
Object
InputStream
Sequence
InputStream
Pushback
InputStream
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.131
InputStream Hierarchy (Cont ...)
The class InputStream is an abstract class, parent to 10 subclasses in the
Java library.
An IOException will be generated if the file associated with the input stream
cannot be opened.
The input hierarchy comes in two categories.
Physical input streams: These classes read from actual data areas such as
byte arrays, a file or a pipe. ByteArrayInputStream,
FileInputStream and PipedInputStream.
Virtual input streams: These depend upon another input stream for the
actual reading operations by extending the functionality of the input stream
in some fashion. SequenceInputStream, ObjectInputStream and
some subclasses of FilterInputStream
To use the above classes, the API java.io has to be imported. Read
javadoc for further information.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.132
InputStream Classes
System.in: Standard input stream object which allows input bytes from the
keyboard to the program. Similarly System.out.
FileInputStream: Files are opened by creating an object of these stream
class.
To perform input and output of data types, object of class
ObjectInputStream, DataInputStream will be used together with the file
stream classes.
File class is useful in obtaining information about files and directories.
To send data between two threads we use the piped classes.
PrintStream outputs formatted data to screen.
The Filter streaming classes will provide additional functionality such as
buffering, monitoring and byte aggregating.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.133
InputStream Classes (Cont ...)
The buffered classes will direct the input or the output to a region in memory.
The operations are performed when the buffer is filled. This will increase the
efficiency of the I/O.
The Push classes will be used to unread an un-access data.
DataInputStream enables a program to read binary data from an
InputStream
Stream Tokenizer
The class StreamTokenizer provides a useful mechanism for breaking a file
into a sequence of tokens.
The stream Tokenizer recognizes words (sequence of words separated by non
letter characters) and numbers.
Read javadoc for more information.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.134
Stream Tokenizer Example
import java.io.*;
public class testTokenizer {
public static void main(String[] args) {
StreamTokenizer tok = new StreamTokenizer(System.in);
try {
tok.nextToken();
if (tok.ttype==tok.TT_NUMBER)
System.out.println(tok.nval);
else if (tok.ttype==tok.TT_WORD)
System.out.println(tok.sval);
else
System.out.println("Unknown type");
} catch (IOException e) {
System.err.println(e);
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.135
Input Stream Example
import java.io.*;
public class FileTest {
public static void main (String args[]) {
String fileNameIn = "test.txt";
String fileNameOut = "new.txt";
FileInputStream fileIn;
DataInputStream dI;
DataOutputStream dO;
int offset=0;
int lengthOfStream=10;
byte b[] = new byte[lengthOfStream];
try {
fileIn = new FileInputStream(fileNameIn);
dI = new DataInputStream(fileIn);
dI.read(b,offset,lengthOfStream);
dO = new DataOutputStream(new FileOutputStream(fileNameOut));
dO.write(b,offset,lengthOfStream);
dI.close();
dO.close();
} catch (Exception e) {
System.err.println(e);
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.136
Input Stream Example (Cont ...)
The streams have the capability of being chained so that it provides input to
other streams.
The exception handling process is essential for the I/O to work.
if you use the statement testString = dI.readLine(); in the above
program it will take one line from the opened file object and make it available
through testString
If the standard input is to be used the following statements will achieve the
goal
DataInputStream dTest = new DataInputStream(System.in);
testString = dTest.readLine();
However the use of System.in is usually avoided.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.137
Output Streams
The output stream hierarchy is given below
OutputStream
ByteArray
OutputStream
File
OutputStream
Buffered
OutputStream
Filter
OutputStream
Data
OutputStream
Object
OutputStream
Piped
OutputStream
PrintStream
The output streams can also be divided into categories of physical and virtual
classes.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.138
The this Reference
Inside any class you can always use this reference to refer to the current
instance of the class.
Additionally, this is often used to pass to external routines a reference to
themselves.
You can legally use this reference to refer to internal fields or methods.
Sine the use of this complicates matters, you should save it for situations that
require it; namely passing references to the current object to external routines.
class Ship3 {
public double x,y;
public Ship3(double x, double y) {
this.x = x;
this.y = y;
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.139
Object Serialization
The ObjectOutputStream is a class designed to write object values to a
stream in a form that can be read easily by ObjectInputStream.
The objects that are saved in this manner can be retrieved using
ObjectInputStream.
The objects that are retrieved should be cast to the proper type using safe
casting.
Use the implementation Serializable if you need to create a class object
with a data structure that needs to be saved. In such a case the information is
formatted accordingly before the class object is saved in a file.
You can save primitive types by using os.writeInt(1); if os is of type
ObjectOutputStream.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.140
Object Serialization Example
RecordObject.java
import java.io.Serializable;
public class RecordObject implements Serializable {
private int number;
private String name;
public RecordObject() {
this(0,"");
}
public RecordObject(int nu, String na) {
number = nu;
name = na;
}
public void displayName() {
System.out.println("The name is " + name);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.141
Object Serialization Example (Cont ...)
ObjectTest.java
import java.io.*;
public class ObjectTest {
public static void main(String[] args) {
RecordObject record = new RecordObject(1,"Kulasekere");
ObjectOutputStream output;
ObjectInputStream input;
String file = "myrecord.txt";
try {
output = new ObjectOutputStream(new FileOutputStream(file));
output.writeObject(record);
output.flush();
output.close();
input = new ObjectInputStream(new FileInputStream(file));
RecordObject s1 = (RecordObject) input.readObject();
s1.displayName();
input.close();
} catch (IOException e) { System.err.println(e); }
catch (ClassNotFoundException f) { System.err.println(f); }
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.142
Readers and Writers
Reader
Buffered
Reader
CharArray
Reader
LineNumber
Reader
InputStream
Reader
Filter
Reader
File
Reader
PushBack
Reader
Piped
Reader
String
Reader
Writer
Buffered
Writer
CharArray
Writer
OutputStream
Writer
Filter
Writer
Piped
Writer
Print
Writer
String
Writer
File
Writer
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.143
Stream Comparison
The Character stream classes and the byte classes have a lot in common. The following
table provides a summary.
Character-stream class
Description
Corresponding byte class
Reader
Abstract
streams
BufferedReader
Buffers input, parses lines
BufferedInputStream
LineNumberReader
Keeps track of line numbers
LineNumberInputStream
CharArrayReader
Reads from a character array
ByteArrayInputStream
InputStreamReader
Translates a byte stream into a character
stream
(none)
FileReader
Translates bytes from a file into a character stream
FileInputStream
FilterReader
Abstract class for filtered character input
FilterInputStream
PushbackReader
Allows characters to be pushed back
PushbackInputStream
class
for
character-input
InputStream
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.144
Stream Comparison (Cont ...)
Character-stream class
Description
Corresponding byte class
PipedReader
Reads from a PipedWriter
PipedInputStream
StringReader
Reads from a String
StringBufferInputStream
Writer
Abstract
streams
BufferedWriter
Buffers output, uses platform’s line separator
BufferedOutputStream
CharArrayWriter
Writes to a character array
ByteArrayOutputStream
FilterWriter
Abstract class for filtered character output
FilterOutputStream
OutputStreamWriter
Translates a character stream into a byte
stream
(none)
FileWriter
Translates a character stream into a byte
file
FileOutputStream
PrintWriter
Prints values and objects to a Writer
PrintStream
PipedWriter
Writes to a PipedReader
PipedOutputStream
StringWriter
Writes to a String
class
for
character-output
OutputStream
(none)
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.145
Threads
The ability of a program to execute a number of tasks is embodied in threads.
The concepts are the same as those found in operating systems literature.
In threads, the data variables, methods are shared.
As with multi-tasking, the parallel behavior translates into task switching rather
than fully parallel execution.
Threads are also known as lightweight processes in OS language.
There are two methods of invoking threads in Java.
Method 1:
Making a separate subclass of the Thread class that contains
the code that will be run. That is putting the behavior in a separate Thread
object.
Method 2:
Using the Thread instance to call back to code in an ordinary
object. That is putting the behavior in a driver class, which must implement
Runnable.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.146
Method 1 of Implementing a Thread
Actions to be performed should be in the run method of the subclass.
Create an instance of the subclass and call the instances’ start method.
This method is inherited from the Thread class while run is overridden.
Each time the start method is called for an instance of the object, a new
thread will be created.
The author of the class is responsible for implementing run and the thread will
die when the run ends.
Never call a threads’ run method directly, Doing so will not start a separate
thread of execution, rather, it will be executed in the current thread just like a
normal method.
Data that is suppose to be local to the thread should be kept as local variables
of run or in private instance variables within the object. All other outside
data should be passed to the threads’ constructor or should be publicly
available as static variables or methods.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.147
Example of Method 1
ThreadClass.java
public class ThreadClass extends Thread {
int a,c;
public ThreadClass() {
System.out.println("The default Constructor");
}
public ThreadClass(int x, int y) {
a = x;
c = y;
}
public void run() {
while (a <10) {
System.out.println("Thread "+ c + " number "+a);
a++;
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.148
Example of Method 1 (Cont ...)
DriverClass.java
public class DriverClass {
public static void main(String[] args) {
ThreadClass t1 = new ThreadClass(1,1);
ThreadClass t2 = new ThreadClass(1,2);
t1.start();
t2.start();
}
}
The output will have a random selection of the loops. For example two loops
of the first call will get executed and then a couple of loops of the second call
will be executed and so on.
Note that the external variables are passed into the run method via the
constructor of the thread method.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.149
Method 2 of Implementing a Thread
Here the Runnable interface is implemented rather than extending the entire
Thread object.
Construct an instance of Thread passing the current class as an argument.
Then call the Thread’s start method. Again the run method will have the
actions that have to be performed.
Again the Threads run method will be ignored since the one you define will
override it.
Now run method has access to all variables and methods of the class
containing therun method.
Note however that the actual run method executed is determined by the object
passed to the thread constructor.
We use this reference to pass the current object to the Thread class.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.150
Example of Method 2
ThreadedClass.java
public class ThreadedClass implements Runnable {
public void run() {
System.out.println("This is a test");
}
public void startThread() {
Thread t = new Thread(this);
t.start();
}
.......;
.......;
}
Create an object of the class and call the startThread method to invoke a
thread.
Each thread so created will execute the same run method concurrently.
Each invocation of run owns a separate copy of the local variables.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.151
Example of Method 2 (Cont ...)
However the instance or class variables are shared among all thread instance
of the class. This can sometimes lead to a race condition. The multiple
threads can access the same variables concurrently. (eg 16.10 pp.706)
If you require the thread to be invoked when the class is instantiated then you
should have the start method invocation in the constructor of the class.
In which case the start method need not be called explicitly.
This method is sometimes useful since in Java you cannot have multiple
inheritance, that is if your class is already a subclass of some class it cannot
be a subclass of Thread too. In such a case if the instance variables and
variables of the main class need to be accessed one needs to do some extra
work. Here it is readily accessible. special
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.152
Method 2 Another Example
Count.java
public class Count implements Runnable {
private static int totalNum = 0;
private int currentNum,loopLimit;
public Count (int loopLimit) {
this.loopLimit = loopLimit;
currentNum = totalNum++;
Thread t = new Thread(this);
t.start();
}
private void pause(double seconds) {
try {
Thread.sleep(Math.round(1000.0*seconds));
} catch (InterruptedException e) {}
}
public void run() {
for (int i = 0; i<loopLimit; i++) {
System.out.println("Counter " + currentNum + ": " + i);
pause(Math.randon());
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.153
Method 2 Another Example (Cont ...)
Driver.java
public class Driver {
public static void main (String [] args) {
Count c1 = new Count(5);
Count c2 = new Count(5);
Count c3 = new Count(5);
}
}
Here for each new instance a set of variables will be copied.
The instantiation will start the thread and the start method need not be called
explicitly.
Use Thread.currentThread() to access the private information
associated with the current instance of the thread.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.154
Race Conditions
As mentioned previously, race conditions occur because multiple threads are
invoked within the same instance of the class.
This can only be done for a class implementing Runnable since the Thread
class is invoked within the class. In the method 1 this cannot be done since
the thread invocation is tied down to the class itself by extending it. Hence
only one thread per instance of a class can be invoked.
When multiple threads are invoked for an instance of a class, all instances of
the threads will be looking at the same instance of the class and each thread
will concurrently execute the same run method.
Local variables of methods will have a copy per thread. However the instance
variables will be shared among the thread instances and can be accessed
concurrently by the thread instances.
One has to be careful of static variables too.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.155
Example of a Race Condition
public class RaceCondition implements Runnable {
private int totalNum=0;
private int loopLimit = 3;
Thread threads[] = new Thread[loopLimit];
public RaceCondition() {
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(this);
threads[i].start();
}
}
public void run() {
int currentNum = totalNum;
System.out.println("Setting currentNum to " + currentNum);
totalNum++;
for (int i = 0; i < loopLimit; i++) {
System.out.println("Counter " + currentNum + ": "+i);
try {
Thread.sleep(Math.round(1000.0*Math.random()));
} catch (InterruptedException e) {
System.err.println(e);
}
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.156
Example of a Race Condition (Cont ...)
Instantiate RaceCondition within main and it will start automatically.
In a majority of the cases the three threads that are started will work
independently. The problem is we have no idea when the first thread is
preempted.
If a thread is preempted after setting the currentNum but before the
totalNum is incremented, the second thread will get incorrect values. The
reason for this is that the instance variable is shared.
Synchronization of the code is a way to get over this problem.
A shared resource can be synchronized, that is locked, using a monitor
(similar to semaphores).
The shared code segment is kept in a synchronized block. Once a thread
enters a synchronized block, no other thread can access this part till the
previous thread releases the lock.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.157
Example of a Race Condition (Cont ...)
However the above does not imply that the thread that is locked cannot be
preempted. If it is preempted while executing the critical section, no other
thread can access this part of the program but they can access another part of
the program other tan the critical section.
The Thread class has other methods such as sleep, interrupt and
isAlive. Also different forms of the constructor is available to name threads
etc. These can be looked up in the java documentation.
It should be noted that some operating systems do not preempt processes
depending on a time quantum. It can be done on a priority basis. For such
operating systems there are variables to set the priority of the thread.
When a part of the program is synchronized care must be taken to avoid
deadlocks if it gets preempted within a lock situation. We can use notify or
notifyAll methods to ensure that when one thread gets preempted it calls
another thread into the ready state before exiting. Every call to a wait()
should have a corresponding call to notify.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.158
Synchronization Example 1
public class RaceCondition implements Runnable {
private int totalNum=0;
private int loopLimit = 3;
Object someObject = new Object();
Thread threads[] = new Thread[loopLimit];
public RaceCondition() {
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(this);
threads[i].start();
}
}
public void run() {
int currentNum;
synchronized(someObject) {
currentNum = totalNum;
System.out.println("Setting currentNum to " + currentNum);
totalNum++;
}
for (int i = 0; i < loopLimit; i++) {
System.out.println("Counter " + currentNum + ": "+i);
try {
Thread.sleep(Math.round(1000.0*Math.random()));
} catch (InterruptedException e) {
System.err.println(e);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.159
}
}
Example Explanation
Even though someObject has been synchronized, in effect the code within
this object is what is synchronized. Objects are not synchronized. We could
have also passed this as the object name and it would have worked.
In this program if you had two segments synchronized with the same object
label someObject both parts cannot be accessed by any other thread if one
label is locked.
We see that now the sequence of events are all in order when compared to
the previous example of RaceCondition.
The sleep method issued to set an arbitrary time slice.
The above example shows how a segment of code can be synchronized.
However another method can also be synchronized in Java.
public synchronized void someMethod() {
body code;
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.160
More on Synchronization
When a method is synchronized the current object instance (i.e. this) is used
as the lock label (in the previous example the lock label was someObject).
Once a thread starts executing someMethod, no other thread can enter the
method or any other method that is synchronized on the current object (this)
untill the current thread exists or if it gives up the lock explicitly using a wait.
The above code segment is equivalent to
public void someMethod() {
synchronized(this) {
body code;
}
}
Overridden methods in subclasses do not inherit the synchronized
declaration.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.161
A Synchronization Bug
A common bug is when you use this as the object for synchronization across multiple
instances of a threaded class.
In the following example a shared static object is used to illustrate the bug.
public class SomeThreadedClass extends Thread {
private static AnotherClass someSharedObject;
.....
public synchronozed void doSomeOperation() {
accessSomeSharedObject();
}
.....
public void run() {
while(someCondition) {
doSomeOperation();
doSomeOtherOperation();
}
}
}
Since the method that is synchronized is equivalent the code segment being included in
synchronized(this), and since this for each instance of the class
SomeThreadedClass is unique, it cannot be used as a lock to protect the shared data.
However if you use synchronized(ObjectTag) then the problem is solved. i.e. each
instance of the class will now see the same object tag. Hence only one thread will be
able to access it at a time.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.162
Other Synchronization Methods
Synchronize on the shared data: this is the technique given above.
public void doSomeOpertion() {
synchronized(ObjectTag) {
accessSomeSharedObject();
}
}
The internal fields of the object are not locked and can be changed, how ever
the tag will tell other threads looking at the same label whether or not they can
enter the block of code.
Synchronize on the class object: Here the class name is used as an object.
public void doSomeOpertion() {
synchronized(SomeThreadedClass.class) {
accessSomeSharedObject();
}
}
Now with a static variable or method, the lock is the corresponding class
object and not this.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.163
Other Synchronization Methods (Cont ...)
Synchronize on an arbitrary object: Here we can create a static object and
use that as the object tag. This will act as a lock monitor since the same tag
name can be seen across all the class instances.
public class SomeThreadClass extends Thread {
private static Object objectTag = new Object();
.....
public void doSomeOperation () {
synchronozed(objecttag) {
The synchronization problems that occur with this is not an issue when the
class implements the Runnable interface. This is because now all threads will
implement the same run method within the class and this will correctly refer
to the same instance of the class and act as a proper lock on the method.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.164
Another Example
public class CalClass {
private int a;
private boolean available;
public int update() {
a++;
return a;
}
public int read() {
a--;
return a;
}
}
public class Inclass4 extends Thread {
private int threadNumber;
private CalClass c;
int i;
public Inclass4 (CalClass x, int tn) {
c = x;
threadNumber = tn;
}
public void run() {
while( i < 10) {
System.out.println("Thread " + threadNumber +
" Update " + i + " Number " + c.update());
i++;
try {sleep(Math.round(1000.0*Math.random()));
} catch (InterruptedException e){}
}
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.165
Another Example (Cont ...)
public class Inclass5 extends Thread {
private int threadNumber;
private CalClass c;
int i;
public Inclass5 (CalClass x, int tn) {
c = x;
threadNumber = tn;
}
public void run() {
while(i < 10) {
System.out.println("Thread " + threadNumber +
" Read " + i + " Number " + c.read());
i++;
try {sleep(Math.round(1000.0*Math.random()));}
catch (InterruptedException e) {}
}
}
}
public class Inclass6{
public static void main(String []args) {
CalClass c = new CalClass();
Inclass4 c4 = new Inclass4(c,1);
Inclass5 c5 = new Inclass5(c,2);
c4.start();
c5.start();
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.166
Another Example (Cont ...)
This problem can be eased by using synchronization on an object tag.
public class CalClass {
private int a;
private boolean available;
public int update() {
synchronized(CalClass.class) {
a++;
return a;}
}
public int read() {
synchronized(CalClass.class) {
a--;
return a;}
}
}
Would this solve the problem?
Even though both the update and the read functions not be accessed at the same time,
one cannot guarantee that they are accessed in an alternate fashion.
This is essential for a producer consumer problem where a shared variable is made
available by the producer and then the consumer makes use of it.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.167
Another Example (Cont ...)
The issue here is to make sure that one function waits for the value to be updated before
the other function starts operation.
public class CalClass {
private int a;
private boolean available;
public int update() {
synchronized(CalClass.class) {
while(available==false) {
try {
wait();
} catch (InterruptedException e) {}
}
a++;
available=false;
notify();
return a;}
}
public int read() {
synchronized(CalClass.class) {
while(available==true) {
try {
wait();
} catch (InterruptedException e) {}
}
a--;
available=true;
notify();
return a;
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.168
}
}
GUI Design Using AWT
The Abstract Window Toolkit (AWT) has many user interface elements. We
will discuss some of them such as Labels, Buttons, Text fieds, Text areas,
check boxes and Choice boxes. Further we will also discuss some of the
layout managers such as Flow, grid, Border, Card and Grid bag layouts. (AWT
Hierarchy)
In order to understand the operation of the graphics elements we define the
following:
Component: is something that can be displayed on a 2D screen and with
which the user can interact. Components have attributes such as size,
visibility, set of listeners etc. Besides Frames, buttons checkboxed etc are
also components.
Container : is a type of component that can nest other components within
it. Containers are useful for constructing complex graphical interfaces. For
example a Frame is a type of container since it can hold objects such as
buttons in it.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.169
More AWT Information
The Panel component is both a Component and a
Container. Such components can be inserted into a
Frame.
A concept of Layout managers are used to maintain the
proper appearance in each platform.
A container will inherit the FlowLayout manager by
default. Each different layout manager will place the
components within the container differently. For
example the FlowLayout manager will place them in
rows created from left to right.
The GUI components use polymorphism to update
paint or repaint the appropriate component.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.170
Components:
Label
import java.awt.*;
import java.awt.event.*;
public class CreateLabels extends Frame {
Label firstLabel = new Label("Right");
Label secondLabel = new Label("Left");
public CreateLabels() {
super("My labels");
setLayout(new FlowLayout());
add(firstLabel);
add(secondLabel);
setSize(300,60);
setVisible(true);
addWindowListener (
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
public static void main (String [] args) {
CreateLabels cl = new CreateLabels();
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.171
Explanation
Note that setVisible is a method in the Component class. However since
Label is derived from it you can call it from any class that extends Label.
The same goes for the method addWindowListner which is a method in the
Window class which is what is used to derive the Frame class.
The WindowAdapter class is simply a class that is derived from Object and
implements WindowListener.
The addWindowListener method declared in the Window class is given as
public void addWindowListener(WindowListener l)
The object that is passed into this methods should be window listener. A new
class that implements the WndowListner could have been created and
passed in to the above function. However, here a short cut to this has been
adopted.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.172
Implementing Other Components
Button Class
The Button class is derived directly from Component, so it can be added to
any class derived from Container such as the Frame class.
The following lines included in the previous program will add a button to the
GUI
Button firstButton = new Button("Left");
add(firstButton);
Most of the methods in the Button class are related to event handling, after
all you click the button for an event to occur.
The method add will add the components to the default container created for
the class when it is extended from Frame.
If you are adding components to any other container then the method issued
os of the form
container_name.add(object);
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.173
Implementing Other Components (Cont ...)
TextField Class
The text fields can be included in the previous program using
TextField firstText = new TextField("Initial",10);
add(firstText);
Some of the methods available in the TextField class are
setText(String) and getText(). A complete list can be found in the Java
Documentation.
For password fields you can use the statement
firstText.setEchoChar(’*’); so that what you type cannot be seen.
The text areas can also be defined in the same manner.
TextArea firstArea = new TextAre(15,80);
The constructor for TextArea is able to accept constants like
SCROLLBARS BOTH to set the style of the text area.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.174
Implementing Other Components (Cont ...)
CheckBox Class
import java.awt.*;
import java.awt.event.*;
public class CreateCheck extends Frame {
Label firstLabel = new Label("Right");
Checkbox firstCheck = new Checkbox("First");
CheckboxGroup cbg = new CheckboxGroup();
Checkbox cbg1 = new Checkbox("On",cbg,true);
Checkbox cbg2 = new Checkbox("Off",cbg,false);
public CreateCheck() {
super("My labels");
setLayout(new FlowLayout());
add(firstLabel);
add(firstCheck);
add(cbg1);
add(cbg2);
setSize(300,60);
setVisible(true);
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.175
Implementing Other Components (Cont ...)
addWindowListener (
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
public static void main (String [] args) {
CreateCheck cl = new CreateCheck();
}
}
Choice Class
The following will include a choice box
Choice firstChoice = new Choice();
firstChoice.addItem("First");
firstChoice.addItem("Second");
add(firstChoice);
The items should be added after the layout manager is defined. Otherwise the
program will not compile.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.176
Layout Managers
The layout manager will free the programmer from the burden of positioning
each component pixel-by-pixel when the components may be different in size
on different platforms, when the main window is interactively resized.
The built in layout managers are good for basic layouts but are not flexible
enough for complex arrangements. However by using nested containers, each
of which will have its own layout manager, you can achieve complex
positioning.
To use a layout manager, you first associate a manager with the container by
using setLayout, then inserting components into the window with add.
In an applet the layout manager is set in init and in an application it is set in
the constructor.
The AWT has 5 layout managers: FlowLayout, BorderLayout,
GridLayout, CardLayout, nd GridBagLayout.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.177
Example Layout
import java.awt.*;
import java.awt.event.*;
public class LayoutExample extends Frame {
Button firstButton = new Button("Left");
Button secondButton = new Button("Right");
Button thirdButton = new Button("Top");
Button fourthButton = new Button("Bottom");
public LayoutExample () {
super("Layouts");
setLayout(new FlowLayout());
Panel p1 = new Panel();
p1.setLayout(new FlowLayout(FlowLayout.LEFT));
p1.add(firstButton);
p1.add(secondButton);
Panel p2 = new Panel();
p2.setLayout(new FlowLayout(FlowLayout.RIGHT));
p2.add(thirdButton);
p2.add(fourthButton);
p1.setSize(300,60);
p1.setVisible(true);
p2.setSize(300,60);
p2.setVisible(true);
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.178
Example Layout
add(p1);
add(p2);
setSize(300,300);
setVisible(true);
addWindowListener (
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
public static void main (String [] args) {
LayoutExample cl = new LayoutExample();
}
}
Here we have added two panels to the main flow layout. Each panel holds two
buttons.
There are a lot of positioning methods available to set the panels to
appropriate locations. For example hgap. These can be looked up in the Java
documentation.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.179
Another Example
import java.awt.*;
import java.awt.event.*;
public class BorderLayoutExample extends Frame {
Button firstButton = new Button("Left");
Button secondButton = new Button("Right");
Button thirdButton = new Button("Top");
Button fourthButton = new Button("Bottom");
public BorderLayoutExample () {
super("Layouts");
setLayout(new BorderLayout());
add(firstButton,BorderLayout.WEST);
add(secondButton,BorderLayout.EAST);
add(thirdButton,BorderLayout.NORTH);
add(fourthButton,BorderLayout.SOUTH);
setSize(300,300);
setVisible(true);
addWindowListener (
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.180
Another Example (Cont ...)
public static void main (String [] args) {
BorderLayoutExample cl = new BorderLayoutExample();
}
}
In border layout the buttons have to be added to locations in the screen.
Otherwise they will get added to the center of the screen and what is visible
will be the last component to be added.
The components will stretch to the entire region unlike in the flow layout.
If you want to add more than one component to a region, group then in a
Panel and add the panel to the region.
GridLayout manager
This will divide the window into equal-sized rectangles based upon the
number of rows and columns specified in GridLayout(2,3).
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.181
CardLayout Manager Example
import java.awt.*;
import java.awt.event.*;
public class CardPanelExample extends Frame implements ActionListen
CardLayout layout = new CardLayout();
Button firstButton = new Button("Left");
Button secondButton = new Button("Right");
Button thirdButton = new Button("Top");
Button fourthButton = new Button("Bottom");
public CardPanelExample () {
super("Card Layouts");
setLayout(layout);
// The buttons will listen to their events
firstButton.addActionListener(this);
secondButton.addActionListener(this);
thirdButton.addActionListener(this);
fourthButton.addActionListener(this);
add("Card 1", firstButton);
add("Card 2", secondButton);
add("Card 3", thirdButton);
add("Card 4", fourthButton);
// display the first card
layout.first(this);
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.182
CardLayout Manager Example
setSize(300,300);
setVisible(true);
addWindowListener (
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
}
);
}
public void actionPerformed (ActionEvent e) {
Object objSource = e.getSource();
if ( objSource == firstButton ||
objSource == secondButton ||
objSource == thirdButton ||
objSource == fourthButton ) {
layout.next(this);
}
}
public static void main (String [] args) {
CardPanelExample cl = new CardPanelExample();
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.183
CardLayout Manager Example (Cont ...)
The CardLayout manager stacks components on top of each other.
It is sometimes useful to save a reference of the manager so that when you
add components to the container to which the manager was applied you can
so do with the reference. For example
Panel cardPanel;
CardLayout layout;
...
layout = new CardLayout();
cardPanel.setLayout(layout);
...
cardPanel.add("Card 1", component 1);
...
layout.show(cardPanel, "Card 1");
layout.first(cardPanel);
With such a system you will always have a handle to the proper container
even if many exists.
The GridBagLayout is a lot more flexible but a lot harder to use. it will chop
the window into cells so that you can specify the start and stop.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.184
Introduction to Swing
The Swing library is based on AWT but written in native Java. Swing is more
easier to use.
Like in AWT, Swing at its highest level contains a heavyweight container (eg.
JFrame similar to Frame in AWT) which is responsible for hosting the main
window of the application. The hierarchy of the panels is given in Fig1.
The naming convention for Swing is JXxxx. Most Swing components are
lightweight components. The exceptions are JFrame, JApplet, JWindow
and JDialog.
The content pane will act as the parent for all the components you add to the
container. It will maintain a layout manager that you can change. Then you
can add components to it directly using the add method.
To set the layout manager of the heavyweight container, you must obtain the
root pane’s content pane. It can be done with either of the two commands
Component contentPane = getRootPane().getContentPane();
Component contentPane = getContentPane();
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.185
Introduction to Swing (Cont ...)
The layout manager can be added using contentPane.setLayout(new
BorderLayout()); or since you have access to the content pane directly
you can also use getContentPane().setLayout(new
BorderLayout());.
Setting up a Swing application
Import the swing libraries.
Set up a heavyweight container.
Set up a lightweight container.
Build your components.
Add your components to the lightweight container.
Swing is preferred because: More components, look and feel support (change
window managers eg. Mortif), Accessibility APIs, Advanced support for 2D
drawing, drag and drop support to name a few.
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.186
Setting Up the Heavyweight Container
public class SwingPanel extends JPanel {
public SwingPanel() {
// setup panel
}
public static void main (String [] args) {
JFrame frame = new JFrame ("My frame");
SwingPanel panel = new SwingPanel();
// add the class instance to the JFrame’s content plane
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.setSize(640,480);
frame.setVisible(true);
frame.addWindowListener (
new WindowAdapter() {
public void windowClosing(WndowEvent e) {
System.exit(0);
}
}
);
}
}
This can also be done by deriving a heavy weight containers public class
SwingClass extends JFrame ...
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.187
Setting up the Lightweight Container
The heavyweight container created previously will hold a content pane that
holds the lightweight containers that hold the components.
The most common lightweight container is the JPanel class. Which doesnt
do much more than position the controls.
Other lightweight containers are JScrollPane, JToolbar etc.
You can create a lightweight container by either deriving your application class
from it or by creating an instance of it and use it that way.
The following example shows how it is done when you have derived your
application class from JFrame and want to use a JPanel lightweight
container.
In the previous example what we have done is deriving the application from
the lightweight container and use an instance of the heavyweight container
inside main
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.188
Lightweight Container Example
import
import
import
import
java.awt.*;// for container classes
java.awt.event.*;
javax.swing.*;
javax.swing.event.*;
public class SwingLightweight extends JFrame {
JPanel panel = new JPanel();
public SwingLightweight () {
getContentPane().add(panel,BorderLayout.CENTER);
setSize(640,480);
setVisible(true);
addWindowListener (
new WindowAdapter () {
public void windowClosing (WindowEvent e) {
System.exit(0);
}
}
);
}
public static void main (String [] args) {
SwingLightweight frame = new SwingLightweight();
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.189
Adding Components to the Lightweight Container
import
import
import
import
java.awt.*;// for container classes
java.awt.event.*;
javax.swing.*;
javax.swing.event.*;
public class SwingAddComponent extends JFrame {
JPanel panel = new JPanel();
JLabel label = new JLabel("this is a test");
public SwingAddComponent () {
getContentPane().add(panel,BorderLayout.CENTER);
setSize(640,480);
setVisible(true);
panel.add(label);
addWindowListener (
new WindowAdapter () {
public void windowClosing (WindowEvent e) {
System.exit(0);
}
}
);
}
public static void main (String [] args) {
SwingAddComponent frame = new SwingAddComponent();
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.190
Swing Layout Manager:
BoxLayout
This was introduced with Swing.
It supports arranging components either in a horizontal row
(BoxLayout.X AXIS) or in a vertical column (BoxLayout.Y AXIS).
This is the first attempt to arrange the components are their preferred widths
(vertical layout) or preferred height (horizontal layout)
import
import
import
import
java.awt.*;
java.awt.event.*;
java.util.*;
javax.swing.*;
public class BoxLayoutTest extends JPanel implements ActionListener
BoxLayout layout;
JButton topButton, middleButton, bottomButton;
public BoxLayoutTest () {
layout = new BoxLayout(this, BoxLayout.Y_AXIS);
setLayout(layout);
JLabel label = new JLabel("BoxLayout Demo");
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.191
Swing Layout Manager:
BoxLayout (Cont ...)
topButton = new JButton("Left Alignment");
middleButton = new JButton("Center Alignment");
bottomButton = new JButton("Right Alignment");
topButton.addActionListener(this);
middleButton.addActionListener(this);
bottomButton.addActionListener(this);
add(label);
add(topButton);
add(middleButton);
add(bottomButton);
setBackground(Color.white);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == topButton) {
refresh(Component.LEFT_ALIGNMENT);
} else if (e.getSource() == middleButton) {
refresh(Component.CENTER_ALIGNMENT);
} else if (e.getSource() == middleButton) {
refresh(Component.RIGHT_ALIGNMENT);
}
}
private void refresh(float alignment) {
topButton.setAlignmentX(alignment);
middleButton.setAlignmentX(alignment);
bottomButton.setAlignmentX(alignment);
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.192
Swing Layout Manager:
BoxLayout (Cont ...)
revalidate();
System.out.println("x: "+layout.getLayoutAlignmentX(this));
}
public static void main(String [] args) {
JFrame frame = new JFrame("My frame");
frame.setBackground(Color.white);
frame.setSize(640,480);
BoxLayoutTest blt = new BoxLayoutTest();
frame.setContentPane(blt);
// frame.addWindowListener(new ExitListener());
frame.setVisible(true);
}
}
PR 2015 - Advance Programming – Prepared by Dr. E.C. Kulasekere – p.193