1.1 Java Basics
1.1 Java Basics
Suppose that you want to assemble your own PC, you go to a hardware store and pick up a
motherboard, a processor, some RAMs, a hard disk, a casing, a power supply, and put them
together. You turn on the power, and the PC runs. You need not worry whether the motherboard
is a 4-layer or 6-layer board, whether the hard disk has 4 or 6 plates; 3 inches or 5 inches in
diameter, whether the RAM is made in Japan or Korea, and so on. You simply put the hardware
components together and expect the machine to run. Of course, you have to make sure that you
have the correct interfaces, i.e., you pick an IDE hard disk rather than a SCSI hard disk, if your
motherboard supports only IDE; you have to select RAMs with the correct speed rating, and so
on. Nevertheless, it is not difficult to set up a machine from hardware components.
How about software? Can you “assemble” a software application by picking a routine here, a
routine there, and expect the application to run. The answer is obviously no. Unlike hardware, it
is very difficult to “assemble” an application from software components. Since the advent of
computer 60 years ago, we have written tons and tons of programs. However, for each new
application, we have to re-invent the wheels and write the program from scratch.
Object-oriented software technology tries to provide a solution for this problem. By creating
self-contained and reusable software objects or components, it is "hoped" that you can pick from
various ready-made, off-the-shelve software components, and simply assemble them into a
workable software application.
Traditional procedure languages (such as C and Pascal) suffer a few notable drawbacks for
creating reusable software components:
1. The programs are made up of functions. Functions are often not reusable. It is very
difficult to copy a function from one program and reuse in another program because the
the function is likely to reference the headers, global variables and other functions. In
other words, functions are not well-encapsulated as a self-contained reusable unit.
2. The procedural languages are not suitable of high-level abstraction for solving real life
problems. For example, C programs uses constructs such as if-else, for-loop, array,
method, pointer, which is too low-level and hard to abstract real problems such as a
Customer Relationship Management (CRM) system or a computer soccer game. (Imagine
using assembly codes, which is a very low level code, to write a computer soccer game.
C is better but no much better.)
1. The basic unit of OOP is a class, which encapsulates both the static attributes and
dynamic behaviours within a "box", and specifies the public interface for using these
boxes. Since the class is well-encapsulated (compared with the function), it is easier to
reuse these classes.
2. OOP languages permit higher level of abstraction for solving real-life problems. The
traditional procedural language (such as C and Pascal) forces you to think in terms of the
structure of the computer (e.g. memory bits and bytes, array, decision, loop) rather than
thinking in terms of the problem you are trying to solve. The OOP languages (such as
Java, C++, C#) let you think in the problem space, and use software objects to represent
and abstract entities of the problem space to solve the problem.
As an example, suppose you wish to write a computer soccer games. It is very difficult to model
the game in procedural languages. But using OOP languages, you can easily model the program
accordingly to the "real-things" occurred in the soccer games.
● Player: attributes include name, number, location in the field, and etc; operations include
run, jump, kick-the-ball, and etc.
● Ball:
● Reference:
● Field:
● Audience:
● Weather:
Most importantly, some of these classes can be reused in another application, e.g., computer
basketball game, with little or no modification.
● Ease in software design as you could think in the problem space rather than the machine's
bits and bytes. You are dealing with high-level concepts and abstractions. Ease in design
leads to more productive software development.
● Ease in software maintenance: object-oriented software are easier to understand,
therefore easier to test, debug, and maintain.
● Reusable software: you don't need to keep re-inventing the wheels and re-write the same
functions for different situations. The fastest and safest way of developing a new
application is to reuse existing codes - fully tested and proven codes.
Object-Oriented Programming in Java
In Java, a class is a definition of objects of the same kind. In other words, a class is a blueprint,
template, or prototype that defines and describes the static attributes and dynamic behaviours
common to all objects of the same kind.
The term "object" is often used loosely, which may refer to a class or an instance.
Class Definition
We shall explain the access control modifier, such as public and private, later.
Class Naming Convention
A class name shall be a noun, or a noun phrase made up of several words. All the words shall be
initial-capitalized (camel-case). Use a singular noun for class name. Choose a meaningful and
self-descriptive classname. For examples, SoccerPlayer, HttpProxyServer, FileInputStream,
PrintStream and SocketFactory.
For examples, suppose that we have a class called Circle, we can create instances of Circle as
follows:
Dot Operator
The variables and methods belonging to a class are formally called member variables and
member methods. To reference a member variable or method, you must:
1. first identify the instance you are interested in, and then
2. reference the method or variable via the dot operator.
For example, suppose that we have a class called Circle, with two variables (radius and color)
and two methods (getRadius() and getArea()). We have created three instances of the class
Circle, namely, c1, c2 and c3. To invoke the method getArea(), you must first identity the
instance of interest, says c2, then use the dot operator, in the form of c2.getArea(), to invoke
the getArea() method of instance c2. For example,
In general, suppose there is a class called AClass with a member variable called aVariable and
a member method called aMethod(). An instance called anInstance is constructed for AClass.
You use anInstance.aVariable and anInstance.aMethod().
Member Variables
A member variable has a name (or identifier) and a type, as descried in the earlier chapter.
Variable Naming Convention: A variable name shall be a noun, or a noun phrase made up of
several words. The first word is in lowercase and the rest of the words are initial-capitalized, e.g.,
thefontSize, roomNumber, xMax, yMin and xTopLeft. Take note that variable name begins with
an lowercase, while class name begins with an uppercase.
For example,
Member Methods
For examples:
Take note that variable name is a noun (denoting a static attribute), while method name is a verb
(denoting an action). They have the same naming convention. Nevertheless, you can easily
distinguish them from the context. Methods take arguments in parentheses (possibly zero
argument with empty parentheses), but variables do not. In this writing, methods are denoted
with a pair of parentheses, e.g., println(), getArea() for clarity.
A class called Circle is to be defined with two variables: radius of type double and color of
type String; and three methods: getRadius(), getColor(), and getArea(), as illustrated in the
following class diagram:
Compile Circle.java. Notice that the Circle class does not have a main() method. Hence, it is
not a standalone program and you cannot run the Circle class by itself. Circle class is meant to
be used in other classes.
We shall now write another class called TestCircle, which uses the Circle class. TestCircle
has a main() method and can be executed.
Constructors
In the class Circle, there are three so-called constructors Circle(...). A constructor is a
special method that has the same name as the class name. It is used to initialize the instance
constructed. To create a new instance of a class, you need to use a special "new" operator
followed by a call to one of the constructors. For example,
Although we often use the term constructor method, a constructor is different from an ordinary
method is the following aspects:
● The name of the constructor method is the same as the class name, and begins with an
uppercase.
● Constructor has no return type (or implicitly returns void). Hence, no return statement
is allowed inside the constructor's body.
● Constructor can only be invoked via the "new" operator. It can only be used once to
initialize the instance constructed. You cannot call the constructor afterwards.
● Constructors are not inherited (to be explained later).
Method Overloading
Method overloading means that the same method name can have a few different
implementations. However, the different implementations must be distinguishable by their
argument list (either the number of arguments, or the type of arguments, or their order). For
example, the above Circle class has three versions of constructor differentiated by their
argument list, as followed:
Circle();
Circle(double r);
Circle(double r, String c);
Depending on the actual argument list used when invoking the method, the matching constructor
will be invoked. If your argument list does not match any one of the methods, you will get a
compilation error.
An access control modifier can be used to control the visibility of a class, a member variable or a
member method without a class. We begin with the following two access control modifiers:
● public: The class/variable/method is accessible and available to all the other objects in
the system.
● private: The class/variable/method is accessible and available within this class only.
In UML notations, public entity is denoted with a "+", while private entity is denoted with a
"-" in the class diagram.
A class encapsulates the name, static attributes and dynamic behaviours into a "3-compartment
box". Once a class is defined, you can seal up the "box" and put the "box" on the shelve for
others to use and reuse. Anyone can pick up the "box" and use it in their application. This cannot
be done in the traditional procedural language like C, as the static attributes (or variables) are
scattered over the entire program and header files. You cannot "cut" out a portion of C program,
plug into another program and expect the program to run without extensive changes.
Member variables of a class are typically hidden from the outside word (i.e., the other classes),
with the private access control modifier. Access to the member variables are provided via the
public assessor methods, e.g., getRadius() and setRadius().
This follows the principle of information hiding. That is, objects communicate with each others
using well-defined interfaces. Objects are not allowed to know the implementation details of
others. The implementation details are hidden or encapsulated within the class. Information
hiding facilitates reuse of the class.
Rule of Thumb: Do not make any variable public, unless you have a good reason.
To allow other classes to read the value of a private variable says xxx, you shall provide a get
method (or getter or accessor method) called getXxx(). A get method need not expose the data
in raw format. It can process the data and limit the view of the data others will see. get methods
cannot modify the variable.
To allow other classes to modify the value of a private variable says xxx, you shall provide a set
method (or setter or mutator method) called setXxx(). A set method could provide data
validation (such as range checking), and transform the raw data into the internal representation.
For example, in our Circle class, the variables radius and color are declared private. That is
to say, they are only available within the Circle class and not visible in any other classes -
including TestCircle class. You cannot access the private variables radius and color from
the TestCircle class directly - via says c1.radius or c1.color. The Circle class provides two
public accessor methods, namely, getRadius() and getColor(). These methods are declared
public. The class TestCircle can invoke these public accessor methods to retrieve the radius
and color of a Circle object, via says c1.getRadius() and c1.getColor().
There is no way you can change the radius or color of a Circle object, after it is constructed in
the TestCircle class. You cannot issue statements such as c1.radius = 5.0 to change the
radius of instance c1, as radius is declared as private in the Circle class and is not visible to
other classes including TestCircle.
If the designer of the Circle class permits the change the radius and color after a Circle
object is constructed, he/she has to provide the appropriate set methods, e.g.,
With proper implementation of information hiding, the designer of a class has full control of
what the user of the class can and cannot do.
Keyword "this"
You can use keyword "this" to refer to this class inside a class definition.
In the above codes, there are two identifiers called radius - a member variable of the class and
the method's argument. This certainly causes naming conflict. To avoid the naming conflict, you
could name the method's argument r instead of radius. However, radius is certainly more
approximate and meaningful in this context. Java provides a keyword called this to resolve this
naming conflict. "this.radius" refers to the member variable; while "radius" refers to the
method's argument.
Using the keyword "this", the getter and setter methods for a private variable called xxx of
type Ttt are as follows:
Furthermore:
Method toString()
Every well-designed Java class should have a public method called toString() that returns a
string description of the object. You can invoke the toString() method explicitly by calling
instanceName.toString() or implicitly via println() or String concatenation operator '+'.
Running println(anInstance) with an object argument invokes the toString() method of
that instance implicitly.
For example, if the following toString() method is included in our Circle class:
In your TestCircle class, you can get a short text descriptor of a Circle object by:
Constants
Constants are variables defined with the modifier final. A final variable can only be assigned
once and its value cannot be modified once assigned. For example,
Constant Naming Convention: A constant name is a noun, or a noun phrase made up of several
words. All words are in uppercase separated by underscores ' _', for examples, X_REFERENCE,
MAX_INTEGER and MIN_VALUE.
Another Example
Suppose that our application requires us to model a group of students. A student has a name and
address. We are required to keep track of the courses taken by each student, together with the
grades (between 0 and 100) for each of the courses. A student shall not take more than 30
courses for the entire program. We are required to print all course grades, and also the overall
average grade.
● Instance variables name (String), address (String), numCourses, course and grades.
numCourses maintains the number of courses taken by the student so far. courses and
grades two parallel arrays, storing the courses taken (e.g., {"IM101", "IM102",
"IM103"}) and their repectively grades (e.g. {89, 56, 98}).
● A constructor that constructs an instance with the given name and Address.
● Getters for name and address; setter for address. No setter is defined for name as it
cannot be changed.
● A toString() which prints "name(address)".
● A method addCourseGrade(course, grade), which appends the given course and
grade into the courses and grades arrays, respectively.
● A method printGrades(), which prints "name(address) course1:grade1,
course2:grade2,...".
● A method getAverageGrade(), which returns the average grade of all the courses taken.
// constructor
public Student(String name, String address) {
this.name = name;
this.address = address;
courses = new String[MAX_COURSES]; // initially empty string
grades = new int[MAX_COURSES];
numCourses = 0;
}
Let us write a test program to create a student named "Tan Ah Teck", who has taken 3 courses,
IM101, IM102 and IM103 with grades of 89, 57, and 96 respectively. We shall print all the
course grades, and the average grade.