Module 2
Module 2
Introducing Classes
A class is that it defines a new data type. Once defined, this new
type can be used to create objects of that type.
The classes that have been used up to this point are actually very
limited examples of its complete form.
type methodname1(parameter-list) {
// body of method
}
type methodname2(parameter-list) {
// body of method
}
// ...
type methodnameN(parameter-list) {
// body of method
}
}
The General Form of a Class Contd…
The data, or variables, defined within a class are called instance variables.
The code is contained within methods.
Collectively, the methods and variables defined within a class are called
• members of the class.
The general rule, it is the methods that determine how a class’ data can be
used.
Variables defined within a class are called instance variables because
each instance of the class (that is, each object of the class) contains its
own copy of these variables.
The general form of a class does not specify a main( ) method.
Java classes do not need to have a main( ) method.
You only specify one if that class is the starting point for your program.
A Simple Class
Here is a class called Box that defines three instance variables: width, height,
and depth. Currently, Box does not contain any methods.
class Box
{
double width;
double height;
double depth;
}
Classes
A class defines a new type of data. In this case, the new data type is called Box. You
will use this name to declare objects of type Box.
It is important to remember that a class declaration only creates a template; it does not
create an actual object. Thus, the preceding code does not cause any objects of type Box
to come into existence.
To actually create a Box object, you will use a statement like the following:
Box mybox = new Box(); // create a Box object called mybox
After this statement executes, mybox will refer to an instance of Box. Thus, it will have
“physical” reality Each time you create an instance of a class, you are creating an object
that contains its own copy of each instance variable defined by the class. Thus, every
Box object will contain its own copies of the instance variables width, height, and
depth.
Classes Contd…
To access these variables, you will use the dot (.) operator.
The dot operator links the name of the object with the name of an
instance variable.
For example, to assign the width variable of mybox the value 100,
you would use the following statement:
mybox.width = 100;
In general, we use the dot operator to access both the instance
variables and the methods within an object.
Classes Contd…
class Box {
double width;
double height;
double depth;
}
For example:
Box b1 = new Box();
Box b2 = b1;
// ...
b1 = null;
type name(parameter-list) {
// body of method
}
Here, type specifies the type of data returned by the method. This can be any
valid type, including class types that you create. If the method does not return a
value, its return type must be void.
Introducing Methods
The name of the method is specified by name. This can be any legal identifier other than those
already used by other items within the current scope.
The parameter-list is a sequence of type and identifier pairs separated by commas. Parameters are
essentially variables that receive the value of the arguments passed to the method when it is called.
If the method has no parameters, then the parameter list will be empty.
Methods that have a return type other than void return a value to the calling routine using the
following form of the return statement:
return value;
OUTPUT:
Volume is 3000.0
Volume is 162.0
Adding a Method to the Box Class Contd..
Thus, the call to mybox1.volume( ) displays the volume of the box defined by
mybox1, and the call to mybox2.volume( ) displays the volume of the box
defined by mybox2.
Each time volume( ) is invoked, it displays the volume for the specified box.
Returning a Value
A better way to implement volume( ) is to have it compute the volume of the box
and return the result to the caller. The following example, an improved version of
the preceding program, does just that:
Example: BoxDemo4.java
OUTPUT:
Volume is 3000.0
Volume is 162.0
Returning a Value
There are two important things to understand about returning values:
The type of data returned by a method must be compatible with the return type
specified by the method. For example, if the return type of some method is boolean,
you could not return an integer.
The variable receiving the value returned by a method (such as vol, in this case) must
also be compatible with the return type specified for the method.
The call to volume( ) could have been used in the println( ) statement directly, as
shown here:
System.out.println("Volume is" + mybox1.volume());
While this method does, indeed, return the value of 10 squared, its use is very limited.
However, if you modify the method so that it takes a parameter, as shown next, then you
can make square( ) much more useful.
Adding a Method That Takes Parameters Contd…
int square(int i)
{
return i * i;
}
Now, square( ) will return the square of whatever value it is called with. That is, square( )
is now a general- purpose method that can compute the square of any integer value, rather
than just 10.
Example: BoxDemo5.java
OUTPUT:
Volume is 3000.0
Volume is 162.0
Constructors
Java allows objects to initialize themselves when they are created. This
automatic initialization is performed through the use of a constructor.
A constructor initializes an object immediately upon creation. It has the
same name as the class in which it resides and is syntactically similar to a
method.
Once defined, the constructor is automatically called when the object is
created, before the new operator completes.
Constructors have no return type, not even void. This is because the implicit
return type of a class’ constructor is the class type itself.
Constructors Contd…
Types of Constructors in Java
1. Default Constructor
2. Parameterized Constructor
OUTPUT:-
Constructing Box
Constructing Box
Volume is 1000.0
Volume is 1000.0
Parameterized Constructors
OUTPUT:
Volume is 3000.0
Volume is 162.0
The this Keyword
Sometimes a method will need to refer to the object that invoked it. To
allow this, Java defines the this keyword.
this can be used inside any method to refer to the current object.
That is, this is always a reference to the object on which the method was
invoked.
You can use this anywhere a reference to an object of the current class’ type
is permitted.
To better understand what this refers to, consider following version of Box( ):
Instance variable hiding refers to a state when instance variables of the same
name are present in superclass and subclass.
When a local variable has the same name as an instance variable, the local
variable hides the instance variable. This is why width, height, and depth
were not used as the names of the parameters to the Box( ) constructor inside
the Box class.
Because this lets you refer directly to the object, you can use it to resolve
any namespace collisions that might occur between instance variables and
local variables.
Instance Variable Hiding Contd…
For example, here is another version of Box( ), which uses width, height, and depth
for parameter names and then uses this to access the instance variables by the same
name:
A stack stores data using first-in, last-out ordering. That is, a stack is like a
stack of plates on a table—the first plate put down on the table is the last
plate to be used.
Stacks are controlled through two operations traditionally called push and
pop.
To take an item off the stack, you will use pop. As you will see, it is easy to
encapsulate the entire stack mechanism.
Here is a class called Stack that implements a stack for up to ten integers:
Overloading Methods
In Java, it is possible to define two or more methods within the same class that share
the same name, as long as their parameter declarations are different. When this is the
case, the methods are said to be overloaded, and the process is referred to as method
overloading.
Method overloading is one of the ways that Java supports polymorphism.
When an overloaded method is invoked, Java uses the type and/or number of arguments
as its guide to determine which version of the overloaded method to actually call.
Thus, overloaded methods must differ in the type and/or number of their parameters.
While overloaded methods may have different return types, the return type alone is
insufficient to distinguish two versions of a method.
When Java encounters a call to an overloaded method, it simply executes the version of
the method whose parameters match the arguments used in the call.
Overloading Methods Contd…
Here is a simple example that illustrates method overloading:
As you can see, test( ) is overloaded four times.
The first version takes no parameters, the second takes one integer parameter, the
third takes two integer parameters, and the fourth takes one double parameter.
The fact that the fourth version of test( ) also returns a value is of no consequence
relative to overloading, since return types do not play a role in overload
resolution.
Java’s automatic type conversions can play a role in overload resolution. For
example, consider the following program:
Overloading Constructors
Java supports Constructor Overloading in addition to overloading methods.
In Java, overloaded constructor is called based on the parameters specified when
a new is executed.
Example:
Using Objects as Parameters
The equalTo( ) method inside Test compares two objects for equality and returns the result.
That is, it compares the invoking object with the one that it is passed. If they contain the same
values, then the method returns true. Otherwise, it returns false. Notice that the parameter o
in equalTo( ) specifies Test as its type. Although Test is a class type created by the program,
it is used in just the same way as Java’s built-in types.
One of the most common uses of object parameters involves constructors. Frequently, you
will want to construct a new object so that it is initially the same as some existing object. To
do this, you must define a constructor that takes an object of its class as a parameter.
For example, the following version of Box allows one object to initialize another:
Argument Passing
There are two ways that a computer language can pass an argument to a subroutine.
The first way is call-by-value. This approach copies the value of an argument into the
formal parameter of the subroutine. Therefore, changes made to the parameter of the
subroutine have no effect on the argument.
The second way an argument can be passed is call-by- reference. In this approach, a
reference to an argument (not the value of the argument) is passed to the parameter.
Inside the subroutine, this reference is used to access the actual argument specified in the
call. This means that changes made to the parameter will affect the argument used to
call the subroutine.
When you pass a primitive type to a method, it is passed by value. Thus, a copy of the
argument is made, and what occurs to the parameter that receives the argument has no effect
outside the method.
Examples:
Returning Objects
A method can return any type of data, including class types that you create.
For example, in the following program, the incrByTen( ) method returns an
object in which the value of a is ten greater than it is in the invoking object.
Recursion
Recursion is the process of defining something in terms of itself. As it relates to
Java programming, recursion is the attribute that allows a method to call itself. A
method that calls itself is said to be recursive.
The classic example of recursion is the computation of the factorial of a number.
The factorial of a number N is the product of all the whole numbers between 1
and N.
For example, 3 factorial is 1 × 2 × 3 ×, or 6. Here is how a factorial can be
computed by use of a recursive method:
Here is one more example of recursion. The recursive method printArray( )
prints the first i elements in the array values.
Access Control
Encapsulation links data with the code that manipulates it. However, encapsulation provides another
important attribute: access control. Through encapsulation, you can control what parts of a program
can access the members of a class. By controlling access, you can prevent misuse.
Normally, a class member must be accessed only in conjunction with an object of its class. However, it
is possible to create a member that can be used by itself, without reference to a specific instance.
To create such a member, precede its declaration with the keyword static.
When a member is declared static, it can be accessed before any objects of its class are created, and
without reference to any object.
You can declare both methods and variables to be static. The most common example of a static
member is main( ). main( ) is declared as static because it must be called before any objects exist.
Instance variables declared as static are, essentially, global variables. When objects of its class are
declared, no copy of a static variable is made. Instead, all instances of the class share the same static
variable.
Understanding static Contd…
Methods declared as static have several restrictions:
They can only directly call other static methods of their class.
They can only directly access static variables of their class.
They cannot refer to this or super in any way. (The keyword super relates
to inheritance and is described in the next chapter.)
The following example shows a class that has a static method, some static
variables, and a static initialization block:
Understanding static Contd…
As soon as the UseStatic class is loaded, all of
the static statements are run.
First, a is set to 3, then the static block
executes, which prints a message and then
initializes b to a*4 or 12. Then main( ) is
called, which calls meth( ), passing 42 to x.
The three println( ) statements refer to the two
static variables a and b, as well as to the
parameter x.
Understanding static Contd…
Outside of the class in which they are defined, static methods and variables
can be used independently of any object. To do so, you need only specify the
name of their class followed by the dot operator. For example, if you wish to
call a static method from outside its class, you can do so using the following
general form: classname.method( )
Here, classname is the name of the class in which the static method is declared.
As you can see, this format is similar to that used to call non-static methods
through object-reference variables. A static variable can be accessed in the same
way—by use of the dot operator on the name of the class. This is how Java
implements a controlled version of global methods and global variables.
Understanding static Contd…
Introducing final
A field can be declared as final. Doing so prevents its contents from being modified, making it,
essentially, a constant. This means that you must initialize a final field when it is declared. You
can do this in one of two ways: First, you can give it a value when it is declared.
Second, you can assign it a value within a constructor. The first approach is probably the most
common. Here is an example:
Subsequent parts of your program can now use FILE_OPEN, etc., as if they were constants,
without fear that a value has been changed. It is a common coding convention to choose all
uppercase identifiers for final fields, as this example shows.
Introducing final Contd…
In addition to fields, both method parameters and local variables can be declared final.
Declaring a parameter final prevents it from being changed within the method.
Declaring a local variable final prevents it from being assigned a value more than once.
The keyword final can also be applied to methods, but its meaning is substantially different than
when it is applied to variables. This additional usage of final is explained in the next chapter, when
inheritance is described.
Introducing Nested and Inner Classes
It is possible to define a class within another class; such classes are known as nested classes.
The scope of a nested class is bounded by the scope of its enclosing class. Thus, if class B is
defined within class A, then B does not exist independently of A.
A nested class has access to the members, including private members, of the class in which it is
nested. However, the enclosing class does not have access to the members of the nested class.
A nested class that is declared directly within its enclosing class scope is a member of its enclosing
class. It is also possible to declare a nested class that is local to a block.
Introducing Nested and Inner Classes Contd…
The following program illustrates how to define and use an inner class. The class named
Outer has one instance variable named outer_x, one instance method named test( ), and
defines one inner class called Inner.
Introducing Nested and Inner Classes Contd…
In the program, an inner class named Inner is defined within the scope of class
Outer. Therefore, any code in class Inner can directly access the variable
outer_x.
An instance method named display( ) is defined inside Inner. This method
displays outer_x on the standard output stream.
The main( ) method of InnerClassDemo creates an instance of class Outer and
invokes its test( ) method. That method creates an instance of class Inner and
the display( ) method is called.
It is important to realize that an instance of Inner can be created only in the
context of class Outer.
The Java compiler generates an error message otherwise. In general, an inner
class instance is often created by code within its enclosing scope, as the example
does.
Introducing Nested and Inner Classes Contd…
Although we have been
focusing on inner classes
declared as members within
an outer class scope, it is
possible to define inner
classes within any block
scope. For example, you can
define a nested class within
the block defined by a
method or even within the
body of a for loop, as this
next program shows:
Introducing Nested and Inner Classes
Contd…