Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
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