Copyright Derek O'Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.
Java is an object oriented language. Java is very similar to C++. When in doubt about the functionality of Java, the odds are that the C++ equivalent will work.
All Java programs contain one or more class definitions. Each class definition contains various class methods (functions).
A Java program can be compiled to be either an:
In these notes, we shall concern ourselves primarily with applets.
Applets differ from stand-alone programs as follows:
There can only be one occurrence of init() in any applet. After the class's constructor, init() is the first code to be called when an applet is loaded into a browser. A class's constructor does not have access to the GUI. Therefore, init() is the first place where GUI methods can be called. The init() method is called exactly once for any applet. It is not called every time the browser returns to the HTML webpage in which the applet resides.
There can only be one occurrence of start() in any applet. The start() method is called after the init() method when an applet is loaded into a browser. In addition, start() is called every time a browser returns to the HTML webpage in which the applet resides.
An example where the start() method can be used is for starting an audio clip every time a user returns to a webpage.
To get access to the Applet class an applet must import (include) the applet package (library).
As every applet is a subclass of the Applet class, every applet must extend the Applet class:
For example:
import java.applet.*; public class Demo extends Applet { public void init() // most applets will use this method. { // body } public void start() // many applets will not use this method. { } }
The HTML wrapper code for an applet is:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Demo</title> </head> <body> <applet code = Demo.class name = Demo width = 640 height = 480> </applet> </body> </html>
Passing Parameters from HTML files
Using the HTML param tag and the Java getParameter() method we can read in applet parameters from a HTML file. The getParameter() method has the syntax:
String getParameter(String parameterName);
If the parameter does not exist in the HTML file, then NULL is returned.
For example:
import java.applet.*; public class Demo extends Applet { private String imageName; private int scaleX; private int scaleY; public void init() { this.imageName = getParameter("imageName"); this.scaleX = parseInt(getParameter("scaleX")); this.scaleY = parseInt(getParameter("scale Y")); } }
The HTML wrapper code for an applet with parameters is:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Demo</title> </head> <body> <applet code = Demo.class name = Demo width = 640 height = 480 param name = "imageName" value = "myBitmap.gif" param name = "scaleX" value = "2" param name = "scaleY" value = "1" </applet> </body> </html>
The paint(), destroy() and stop() Applet Methods
In addition to the init() and start() methods, all applets can override the paint() and destroy() methods.
The paint() method is used for all text and graphics output.
The destroy() method is used to destroy any resources (such as Graphics) that have been allocated by the applet.
Another useful method that all applets can use is the stop() method. The stop() method can be used to force an applet to terminate.
By convention:
A comment that only extends to the end of the current line is denoted:
A comment the can extend over more than one line is denoted:
/*Applets use the Java graphical user interface (GUI) for all text and graphics output. In order to facilitate simple text output in various examples in Section I we shall note that text output can be achieved using the drawString() method from inside the paint() method. To use these two methods we must import the Graphics class from the java.awt.Graphics package (awt is the abstract window toolkit).
Drawing Example: (Run Applet)
import javax.swing.*; import java.awt.*; public class DrawStringDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { @Override public void paintComponent(Graphics g) { g.drawString("Hello", 200, 50); } } }
The paint() method and the Graphics class will be described in more detail in Section II.
Java variables are declared as:
dataType variableName;
dataTypes can be either:
boolean types can have one of two values: true and false. In C++ TRUE and FALSE are just alternate names for 1 and 0. In Java true and false are distinct values. They are not 1 and 0.
We assign a character using the char keyword. For example: char day = '5';
The standard default value of a character is the null character, denoted by '\u000'
We shall talk about each of the three reference types in detail at a later stage.
When given an expression that contains both floating point and integer numbers, Java automatically casts each of the integer numbers into floating point.
Use the cast operator to force Java to convert from one type to another.
For example:
Given the declarations
int i; double d;
to cast, use
(double)i (int)d
Casting does not change the original type of either i or d in the above example.
Any class variable or class method can be declared to be public, private or protected.
Any class variable or class method that is declared to be public can be accessed from anywhere in a program.
Any class variable or class method that is declared to be private can only be accessed from within its own class.
Any class variable or class method that is declared to be protected can only be accessed from within its own class, from any of its own class's subclasses or from any other class that is in the package where the protected variable is defined.
We shall use the following class structure to demonstrate the various class features.
Use the following syntax to define a public class:
public class className { }
Each class can have at most ONE superclass.
To specify a class's superclass use the keyword extends and the name of the superclass in the subclass's definition. The syntax for specifying a superclass is:
public class subclassName extends superclassName { }
For example,
public class Rectangle extends Shape { }
The highest class is the Object class. Any class that does not extend from another class is assumed to extend from the Object class.
For example:
public class Shape { }
is the same as
public class Shape extends Object { }
Overriding occurs when two methods with the same name and the same parameter layout are defined in different classes, one of which is a superclass of the other. To decide which method to use, Java searches up through the subclass/superclass hierarchy until it finds an instance of the method. The first instance of the method that is encountered is the one that is used.
Superclasses are usually only ever used to hold common methods and variables for their various subclasses. It is often desirable that we only ever create instances of a superclass's subclasses and never of the superclass.
By making a superclass an abstract class, we ensure that we can never create an instance of the superclass.
Use the syntax shown below to make a class an abstract class.
public abstract class className { }
The Shape class should be abstract. We shall never actually create instances of a Shape class.
For example:
public abstract class Shape { } public class Rectangle extends Shape { }
An attempt to create an instance of an abstract class will give a Java compile error.
For example:
new Shape(); // will give a Java compile error
However, we can declare an abstract variable.
For example:
Shape myShape;
An abstract variable can be initiated to be any of the superclass's subclasses.
For example:
Shape myShape; myShape = new Rectangle(); // myShape is now an instance of Rectangle myShape = new Triangle(); // myShape changes, and is now an instance of Triangle
If we decide to create an abstract variable we can run into another compile problem. If there exists a public method in a subclass that does not exist in the superclass then the Java compiler can get confused. For example, we might decide to implement a getArea() method for the Rectangle, Triangle and Circle subclasses. The three versions of getArea() will need to be implemented differently.
This would give us the following classes.
public abstract class Shape { } public class Rectangle extends Shape { public int getArea() { } } public class Triangle extends Shape { public int getArea() { } } public class Circle extends Shape { public int getArea() { } }
As above, we can declare an abstract variable of class Shape and assign it to be an instance of the Rectangle, Triangle or Circle subclass.
Shape myShape; myShape = new Rectangle();
However, a call to the subclass getArea() method will give a Java compile error.
myShape.getArea(); // Java compile error
To overcome this Java compile error we can implement an abstract method. An abstract method will always be overrided by an equivalent method in a subclass. Abstract methods have a semicolon immediately after the method declaration. Abstract methods have no body as their only function is to stop the Java compile error mentioned above.
For example, we could include an abstract method in the Shape superclass.
public int getArea(); // note (1) the semicolon immediately after the method declaration // and (2) there is no { } (i.e. no body).
Abstract methods can only be defined in abstract classes.
Once we define an abstract method Java forces us to define a corresponding non-abstract method in each of the superclass's subclasses.
For example:
public int getArea() { }
must be declared in each of the Rectangle, Triangle and Circle subclasses.
A final class cannot have a subclass. Final classes always form leafs on the class hierarchy because they cannot have subclasses. A class cannot be both abstract and final.
Java does not support multiple inheritance, so any class can have at most one superclass. Sometimes it is desirable for a class to inherit methods from more than one class. Interfaces are used to achieve multiple inheritance. The methods in interfaces can be accessed by other classes, but interfaces are not superclasses.
An interface is defined in the same way as a class, except that the keyword implements is used instead of extends.
An interface is like an abstract class in that it holds abstract methods that force other classes to implement ordinary methods. All methods in an interface are abstract, whether they are marked as such or not. It is good programming practice to always mark them as abstract. An interface contains only shell methods. A class that implements an interface MUST override ALL methods that are contained in the interface. Failure to do this will result in a compile error.
Because interfaces only define abstract methods, there is no possibility that a method defined in an interface can conflict with a method inherited from a class.
A class can have more than one interface. If a class has more than one interface, then all of the interfaces are listed after the implements keyword.
To use an interface use the keyword implements.
For example, in a simple case where we have a college that contains staff and students:
public class Staff extends College implements Person { // five of the methods that could be in Staff public String getName(); // override from Person public void setName(String newAddress); // override from Person public String getAddress(); // override from Person public void setAddress(String newAddress); // override from Person public String[] getSubjectAreas(); ... } public class Student extends College implements Person { // five of the methods that could be in Student public String getName(); // override from Person public void setName(String newAddress); // override from Person public String getAddress(); // override from Person public void setAddress(String newAddress); // override from Person public String[] getResults (int forYear); ... } public class Room extends College // this is just to show that College is more than just people { // one of the methods that could be in Room public boolean isRoomFree(int day, int hour); } public abstract interface Person { // four of the methods that could be in Person public abstract String getName(); public abstract void setName(String newAddress); public abstract String getAddress(); public abstract void setAddress(String newAddress); ... } public Class College { // one of the methods that could be in College public String getName(); // get the name of the College ... }
In the above example, the way in which personal information is got or set for staff and students can be different. For example, the two sets of data would most probably be contained in different databases. Therefore the code to perform the getName(), setName(), getAddress() and setAddress() would be different for the Staff and Student classes.
Because the Person class is implemented, all of its methods are abstract. Because they are abstract, they must be overrided in every class that implements Person. In the above example, because they are overrided, there will never be any confusion when getName() is called. If getName() is called by Staff or Student, it will return the person's name. If getName() is called by College, it will return the name of the College.
An Inner class is a class that is defined within another class. Any methods that are defined within an inner class are visible to the class that contains the inner class.
Their primary usage is in providing an empty set of implementations for Interfaces. As stated above, any class that implements an Interface must override EVERY method that is contained within the Interface. If the user does not need to use all the methods that are available in the Interface then they must place dummy methods in their code so as not to get a compile error. Obviously, this is not a pleasant situation. Inner classes overcome the problem. We define a class that implements the required interface. Within that class, we implement the interface and declare a dummy override for every method that is contained within the interface. We can now make this class an inner class to any other class that needs to implement the interface. Within the class that contains the inner class we need only provide overrides to those methods that we wish to use, as the class inherits all of the dummy methods from the inner class. We do not need to implement an interface for any methods that we have embedded within an inner class.
Inner classes are used extensively within any classes that implement GUI event handling. More details on the use of inner classes for GUI purposes are contained in the section "Event Handling".
For the moment we shall concern ourselves with one example.The MouseListener interface implements five methods: mousePressed(), mouseReleased(), mouseEntered(), mouseExited() and mouseClicked(). In the two examples below, we only wish to make use of the mouseClicked() method. In the first example we do not use an inner class. In this case we must override all five methods that are in the MouseListener Interface. In the second example we make use an inner class to save us the bother of overriding those methods that we do not wish to use. Java provides a class called MouseAdapter that provides an override for the MouseListener interface.
Example Without inner class (Run Applet)
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class MouseListener_WITHOUT_InnerClassDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel implements MouseListener { public View() { super(); addMouseListener(this); } // In this example, we only wish to implement the mouseClicked method of the MouseListener Interface public void mouseClicked(MouseEvent e) { showStatus("Mouse x:" + e.getX() + " y:" + e.getY()); } // All of the classes below are not needed for this example. However, we still must override them @Override public void mousePressed(MouseEvent e) { } @Override public void mouseReleased(MouseEvent e) { } @Override public void mouseEntered(MouseEvent e) { } @Override public void mouseExited(MouseEvent e) { } } }
Example WITH inner class (Run Applet)
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class MouseListener_WITH_InnerClassDemo extends JApplet { @Override public void init() { this.setContentPane(new View()); } public class View extends JPanel { public View() { super(); addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { showStatus("Mouse x:" + e.getX() + " y:" + e.getY()); } }); } } }
A method can be any of the following method types:
A class's public methods can be called by any instance of the class or from any instance of any other class. Private methods can only be called from within the defining class's methods.
To call a method from another class then specify the className and methodName, joining them together using the field selection operator as shown below.
className.methodName();
Use the following syntax to define a method:
methodTvpe returnType methodName(parameterList) { }
For example
public int getMax(int num1, int num2) { return((num1 num2)?num1:num2); }
Several methods with the same name can be declared within a class, as long as each of the methods has a unique pattern of parameter data types.
The same method with the same pattern of parameter data types can be declared once in each of several different classes. Remember from earlier in these notes, that overridding occurs if the same method with the same pattern of parameter data types is declared in both a superclass and a subclass.
Each class can have at most one constructor method.
A class is allowed to have no constructor.
The constructor method is called automatically whenever a new class instance is created.
Constructor methods should always be made public.
Constructor methods are different to other methods in two ways:
For example
public class Demo { public Demo() // note the use of the uppercase D in Demo so as to exactly match the class nam { } }
As with other methods, a class can overload its constructor so that it contains constructors with different sets of parameters.
If a class has a superclass, then it is good programming practice that the first step within the subclass's constructor is to call the constructor of the superclass.
To call the constructor of a subclass's superclass use the method super(). The method super() must be the first statement in the subclass's constructor.
For example:
public class Rectangle extends Shape { public Rectangle() { super(); } }
The super() method must have the same number of parameters as the superclass's constructor.
If two, or more, expressions are joined using the && (logical AND) operator then the expressions are evaluated from left to right. Immediately after any evaluation is found to be false the value of the entire expression is set to false. No further evaluations of the expressions to the right are performed.
If two, or more, expressions are joined using the || (logical OR) operator then the expressions are evaluated from left to right. Immediately after any evaluation is found to be true the value of the entire expression is set to true. No further evaluations of the expressions to the right are performed.
while loops and for loops are exactly the same as in C and C++.
The if, if else, and switch statements are exactly the same as in C or C++.
The first element's index in a Java array is 0.
Like classes and vectors, arrays are reference variables. Use the new operator to create an instance of an array.
For example:
int studentId[] = new int[5];
Array creation and element insertion can be combined into one statement.
For example:
int studentld[] = {15,67,5,89,6};
is the same as:
int studentId[] = new int[5]; studentId[0] = 15; studentId[1] = 67; studentId[2] = 5; studentId[3] = 89; studentId[4] = 6;
Arrays can store class instances.
For example:
Soccer clubs[] = new Soccer[5];
When we create an array of class instances all the elements are initialised to null.
The creation and element insertion of an array of class instances can be combined into one statement.
For example:
Soccer clubs[] = (new Soccer( "dkit"),new Soccer("gmit"),new Soccer("dit")];
A class instance that is held in an array is treated like any other class instance, so we have access to its public methods and variables.
For example if the class Soccer has a method called int getGoals() then the following is a valid statement.
Soccer clubs[] = new Soccer[5]; int x; x = clubs[2].getGoals();
To specify that a method's parameter is an array we include brackets with the parameter type specification. To specify that a method returns an array we include brackets with the return value type specification.
The example below takes as its parameter an array of Soccer[] and returns an array of Soccer[].
public Soccer[] getCollegeSoccerClubs(Soccer[] clubs);
When we pass an array to a method, we are actually passing the array's address to the method. Therefore, any changes made to the array inside the method will remain in place after the array has returned.
In Java an array of class instances only actually holds the addresses of the class instances. The actual class instances are held elsewhere in memory. This feature is hidden from the user. The myth that Java does not use pointers is false. What is true is that Java is designed so that all the features of pointer based languages (such as C or C++) are still implemented but that programmers can not gain access to the pointers.
In C++ an array can hold either actual class instances or the addresses of class instances. If an array contains the addresses of class instances then it is up to the programmer to keep track of the pointers.
In Java, the Vector class is used to implement dynamically linked lists. To use Vectors you must import java.util.Vector into your program.
Vectors are not of a fixed size. Elements can be added to, or removed from, vectors at any time and at any location within the Vector.
Vectors can only store class instances. They cannot store primitive types, such as int.
To store primitive types in a Vector we use the primitive's wrapper class. Java provides wrapper classes for each of the primitive types.
For example:
Integer myIntClass = new Integer();
As a Vector is a class, its declaration and creation are the same as for any other class.
For example:
Vector stack = new Vector();
To add an element to the end of a Vector use the addElement() method.
For example:
stack.addElement(new Integer(34));
To insert an element at a particular index within a Vector use the insertElementAt() method.
For example:
stack.insertElementAt(3, new Integer(78));
To change the value of an element at a particular index within a Vector use the setElementAt() method.
For example:
stack.setElementAt(23, new Integer(7));
To delete an element from a particular index within a Vector use the removeElementAt() method.
For example:
stack.removeElementAt(2);
To retrieve the first element from a Vector use the firstElement() method.
For example:
stack.firstElement();
To retrieve the last element from a Vector use the lastElement() method.
For example:
stack.lastElement();
To retrieve an element from a particular index within a vector use the elementAt() method.
For example:
stack.elementAt(6);
To obtain the number of elements in a Vector use the size() method.
For example:
stack.size();
We must be careful when trying to access the public methods and variables of a class instance that is stored in a Vector. Because Vectors are not a subclass of the class instance that we wish to access they will not have access to the public methods and variables of the class instance that we wish to access.
To access the public methods and variables of a class instance that is stored in a Vector we must first cast the Vector to be the same class type as the class instance.
The cast syntax is:
((cast type)vectorMethod).classMethod
For example:
((Soccer)stack.firstElement()).clubName();
Denote a particular character by placing a pair of single quotes around it. We declare a character using the char keyword.
For example:
char c = 'A';
Use the \ escape character to implemented various special characters. The special characters that we can implement are:
\t | tab |
\r | carriage return |
\n | new line |
\f | form feed |
\b | backspace |
\" | double quote |
\' | single quote |
\\ | backslash |
Use the String class to declare and create instances of strings.
For example:
String s = new String("hello");
Strings are constants. We can concatenate two strings to produce a new, longer string, but we cannot add to or delete from a string.
To get the length of a string use the length() method.
For example:
s.length();
To extract a character from a string use the charAt() method.
For example:
s.charAt(4);
Strings are instances of the String class. They are not arrays.
As with arrays and vectors, the first index in a string is 0.
Java expects a programmer to acknowledge certain methods (e.g. attempting to open a non-existent file) might lead to a run-time error. By using exception handling we can remove the error handling code from the main body of the program. This improves program clarity and enhances modifiability. Exception handling can be implemented using the try-catch statement. In the examples in these notes, exception handling code has been largely ignored. This is done to simplify the examples and to keep attention on the essential code of each example. However, in the real world, you should NEVER ignore exception handling. It is put there to help you to (at best) recover or (at worst) exit in a controlled fashion from code that might otherwise cause your applet to terminate in an unknown manner. Note, also, however, that no matter how badly your applet crashes, it can NEVER cause any harm to its host computer.
Use try-catch by placing the keyword try before a statement.
For example:
try { inputFileStream inFile = new InputFileStream( "input.dat"); }
If the file "input.dat" does not exist, then Java will throw an IOException. To implement our own exception handling code that ties in with our try statement we use the keyword catch followed by an IOException parameter.
For example:
catch (IOException e) { // code to deal with an IOException caused within the try statement // for example showStatus(e); }
If a try block of code throws an exception of the class specified in the catch clause then:
More than one catch can be associated with a try statement.
For example:
try { inputFileStream inFile = new inputFileStream("input.dat"); } Catch (FileNotFoundException e) { // code to deal with an FileNotFoundExcephon caused within the try statement // for example showStatus( "The file \" input. dat\" does not exist"); } Catch(IOException e) { // code to deal with an IOException caused within the try statement // for example showStatus( "An input/output error has occured"); }
To stop a program's execution use the Applet class's stop() method.
For example:
stop(O);
Use the finally keyword to force a block of statements to be executed whether or not an exception has been thrown.
The syntax of the finally clause is:
try { } catch (exceptionClassName e) { } finally { }
The finally clause forces code to execute, whether an exception occurs or not. This can be sometimes necessary to perform house cleaning.
For example
Graphics g = image.getGraphics(); try { // some code that might cause an exception } catch (IOException e) { // catch any IOException } finally { // guarantee that the graphics is disposed of. g.dispose(); }
It is possible to propagate an exception up the calling chain. This is useful as higher level methods are usually in a better position to inform the user of errors or to abandon unsuccessful commands.
Exception handling involves a large processing overhead and significantly slows down the execution speed of applets. To handle exceptions more efficiently follow the following rules:
In Java a file that holds class code is called a compilation unit. Java allows us to place more than one class in a compilation unit. However, only one class in any compilation unit can be public. The public class always has the same name as the compilation unit. It is good programming practice to place only one class in any compilation unit.
To package classes together, place their compilation units into a common package.
For example:
package myProjs.lib.Games; public class Sports { }
The components of a package name always correspond to the final components of the path that specifies the location of the corresponding units.
The initial components of the path name are taken from the value of CLASSPATH, an operating system environment variable.
Java simply concatenates the value of CLASSPATH to the package name to locate the package's compilation units.
For example, if CLASSPATH is set to c:\java then:
package myProjs.lib.Games; public class Sports { }
will package the class Sports into a package called Games in the directory c:\Java\myProjs\lib.
Use the keyword import to use a compilation unit from a given package.
To import only one class from a package, give the name of the class in the import statement.
For example:
import myProjs.lib.Games.Sport;
To import all classes from a package, use the wildcard * in the import statement.
For example:
import myProjs.lib.Games.*;
Copyright Derek O' Reilly, Dundalk Institute of Technology (DkIT), Dundalk, Co. Louth, Ireland.