JaVa
Introduction to Classes
The objects and classes are the basis for object-oriented programming. In Java, the class facility is used to define new data types. That’s why classes are called user-defined data types. Actually classes help you to organize tasks and assign them to entities. A class encapsulates data and methods (member functions). You can restrict data access. You can build hierarchies of classes. Classes help you to reuse data and code. When you instantiate a class you create an object. In other words you can say that a class is a template for an object and an object is an instance of a class.
Declaring a Class
A class defines the behavior of an object. For example, a scooter is manufactured by Bajaj company. Other types of scooters can be manufactured by the same Bajaj, but each instance of scooter will have its own state and set of attributes. In general a class encapsulates data and methods (known as member functions in other OOP languages, such as C++), as shown in figure 1.
Figure 1
Syntax :
A class is declared by using the keyword – class. A class definition consists of two parts:
• class header
• class body
The class header consists of the keyword class followed by the identifier, class name. The data member(s) and method(s) are defined in the class body. In Java, braces ({ }) mark the beginning and the end of a class or method. The general syntax of declaring a class:
Here the classname is the name of the class and it is mandatory. The classname is used to refer to the class and to create instances of the class. The class body consists of the class data members, class methods and the access specifiers of these class members. We will study about these class access specifiers later on. Note that each class definition introduces a new data type.
class Distance
{
// data member(s)
// method(s)
}
Here the Distance is a user-defined data type.
Rules and Conventions for Naming Classes
A class name must not be a keyword in Java. A class name must begin with a letter, an underscore ‘_’ or a ‘$’ symbol. It must not contain embedded spaces or periods ‘.’. A class name can also contain characters from various alphabets, like Greek, Cyrillic, Japanese, etc.
A class name must be meaningful and usually represents a real life class, for example Distance to measure a distance from one city to another. In order to differentiate it with other data types, just begin class names with an uppercase letters.
Class Members
The class consists of two types of members:
• Data members
• Methods
Data Members
The data or variables defined inside a class are called data members or instance variables. Data members of a class are declared in the same way we declare variables in C/C++.
Syntax :
The syntax of declaring a data member is:
datatype varname;
Here varname is the variable name of datatype. The datatype can be any valid Java data type (either built-in or user-defined). Like class names the variable names must be meaningful. Generallt the variable names begin with lowercase letters.
Example:
class Distance
{
int meter;
float cm;
}
Here the class Distance has two data members – meter and cm of type integer and float respectively
Here the declaration of data members of class Distance is shifted to right. This is called indentation. Indentation is just used to make your code more easily readable. Remind that Java is a free form language. Thus you can also define the above class Distance as:
class Distance { int meter ; float cm; }
Indentation is generally done for data members, methods and blocks.
Rules and Conventions for Data Members
A variable name must not be a keyword. A variable name must begin with a letter, an underscore ‘_’ or a ‘$’ symbol. It can not begin with a digit. It must not contain embedded spaces or periods ‘.’. A variable name can also contain characters from various alphabets, like Greek, Cyrillic, Japanese, etc.
A variable name must be meaningful and usually represents the type of data it contains. Variable names are nouns and begin with a lowercase letters. If a variable name contains two or more words then join the word and begin each word with an uppercase letter. The first word, however, starts with a lowercase letter.
Methods
The functions of a class are called as methods in Java. As we have functions in C/C++, we have methods in Java. Methods are defined inside a class.
Syntax :
The syntax of declaring a method is:
datatype methodname (list_of_arguments)
{
// Statements
}
Here the datatype specifies the data type of the value returned by the method. The datatype can be any valid data type in Java (built-in or user-defined). The methodname is the name of the method and it identifies the method. The methodname can be any legal identifier than those used by other items within current scope. The list_of_arguments is set of information that is passed to a method. It is specified within parentheses.
For example, consider the following method declarations:
- void getdata() – This function receives no value and returns no value
- void setdata(int mm, float cc) – This function receives two values – mm and cc of type integer and float respectively.
- int adddata() – This function receives no value but returns an integer value
Example:
The following code shows the declaration of data members and methods in a class.
class Distance
{
int meter;
float cm;
void getdata()
{
// ….
}
void setdata(int mm, float cc)
{
// ….
}
void display()
{
// ….
}
}
Rules and Conventions for Methods
A method name must not be a keyword. A method name must begin with a letter, an underscore ‘_’ or a ‘$’ symbol. It can not begin with a digit. It must not contain embedded spaces or periods ‘.’. A variable name can also contain characters from various alphabets, like Greek, Cyrillic, Japanese, etc.
A method name must be meaningful and usually represents the type of task it accomplishes. If a variable name contains two or more words then join the word and begin each word with an uppercase letter. The first word, however, starts with a lowercase letter.
Method Overloading
Method overloading is used where we want to create several methods that perform closely related tasks. For example, the class Sample has a method that returns the absolute value of an integer, another method returns the absolute value of a float and a third that returns the absolute value of a double. These three methods perform the same essential operation, and so, it is appropriate to use the same name for them.
Fortunately Java supports method overloading in which we create three methods with the same name.
Example
class Sample
{
public int abs(int a)
{
if ( a < 0 )
a = -a;
return a;
}
public float abs(float b)
{
if ( b < 0 )
b = -b;
return b;
}
public double abs(double c)
{
if ( c < 0 )
c = -c;
return c;
}
….
}
Here we have three abs() methods. At the time of compilation, the compiler resolves the version of the abs() method to be called based on the parameters passed.
While using overloading methods, one should remember that overloading of method is not done on the return type of the method. Thus the following methods results in ambiguity whenever we invoke them:
int add (int m, int n)
{
// ….
}
long add(int x, int y) // Illegal
{
// ….
}
Creating an Object
As stated earlier an object is an instance of a class. An object is declared in the same way as we declare variables of basic data types, such as ints or float.
Syntax :
An object is declared as:
classname objectname;
Here classname is the name of the class and objectname is the name of the object. In Java, an object does not reserve memory space when it is declared. The declaration of an object simply tells the compiler that this variable can refer to an object of type classname. Memory is allocated to an object using new operator in following two ways:
-
classname objectname;
-
classname objectname = new classname();
The new operator dynamically allocates memory form an object and returns a reference to it.
Example:
-
Distance dobj; // declare reference to an object
-
Distance dobj = new Distance();
In first declaration, the statement
Distance dobj;
just declare a reference dobj to an object of type Distance. At this stage the value of ‘dobj’ is null. The null value indicates that it doe not yet point to an actual object. The dobj points to an actual object of type Distance just after the following statement:
dobj = new Distance();
Figure 2 illustrates this.
Figure 2
Accessing Class Members
As stated earlier a class consists of data members as well as methods. We can access the members of a class either from inside the same class in which they are defined or from another class.
Accessing Data members
A data member can be accessed inside the class in which they are defined.
Example:
class Distance
{
int meter;
float cm;
void setdata(int mm, float cc)
// This method sets data members to ‘mm’ and ‘cc’ respectively
{
meter = mm;
cm = cc;
}
}
However a data member can be used in a different class by creating an object of that class and then referring to that data member using the dot ‘.’ Operator.
Example:
class Sample
{
Distance d; // declaring an object of the Distance class
void putdata()
{
d = new Distance(); // allocating memory to an object
d.meter = 20; // Accessing data members of ‘d’
d.cm = 75.5f;
}
}
Accessing Methods
A method can be accessed inside the class in which they are defined by using parentheses and a semicolon. One method of a class can invoke another method of the same class using the name of the method
Example :
class Distance
{
int meter;
float cm;
void setdata(int mm, float cc)
{
meter = mm;
cm = cc;
increment(); // calling increment() method from the same class
}
void increment()
{
meter++;
cm++;
}
}
However a method can also be accessed from a different class by creating an object of that class and then invoking that method using the dot ‘.’ Operator
Example:
class Sample
{
Distance d; // declaring an object of the Distance class
void putdata()
{
d = new Distance(); // allocating memory to an object
d.setdata(20, 75.5f);
}
}
Here we have called method setdata() of the class Distance from the class Sample.
The main() Method
In Java application, there may be many classes and each class may have one or more methods. The method the compiler executes first is the main() method.
Syntax
The syntax of main() method is
public static void main(String args[ ])
{
// ….
}
The main() method is declared as public so that Java interpreter can access it. The method does not return any value, and that’s why it is declared void. The static modifier is used so that an instance of the class can not be created to call the main() method.
One main point to note here is that the primary name of the file in which the code is written and the name of the class that has the main() method should be same.
Example
// The name of this file must be – ClassDemo.java
class ClassDemo
{
public static void main(String args[])
{
// ….
}
}
The order of the modifiers and access specifiers may be interchanged, but the return type, void, must be specified immediately before the method name.
Now let us see a simple program that illustrates the concept of declaring a class, data members, methods and invoking of data members and methods.
// Program – ClassDemo.java
class Distance
{
int meter;
float cm;
void setdata(int mm, float cc)
{
meter = mm;
cm = cc;
}
void display()
{
System.out.println(meter + “ ” + cm);
}
}
class ClassDemo
{
public static void main(String args[])
{
Distance d;
d = new Distance();
d.setdata(20, 75.5f);
d.display();
}
}
The output of this program is….
20 75.5
Passing Arguments to a Method
In earlier example, we have invoked the method setdata(), which receives two arguments 20 and 75.5f of type int and float respectively, of the class Distance from the class classdemo. The method which calls a method is called as calling method and the method which is being called is called as called method. when we call a method the calling method passes arguments to the called method.
In Java, arguments are passed to a method in two ways:
• Call by value
• Call by reference
Call by Value
In Java all arguments of primitive data types are passed by value. It means that the value of the actual arguments can not be altered by the called method. The called method receives the value of the actual arguments in the duplicate copies. The called method only manipulates the duplicates copies and thus any changes made in the duplicate copies are not reflected back in calling method.
Program ValuePass.java illustrates this.
// Program ValuePass.java
class ValuePass
{
static void swap(int aa, int bb)
{
int t;
t = aa;
aa = bb;
bb = t;
}
public static void main(String args[])
{
int a, b;
a = 20;
b = 40;
System.out.println(“Before calling swap() method”);
System.out.println(“A = ” + a + “B = ” + b);
swap(a, b);
System.out.println(“After calling swap() method”);
System.out.println(“A = ” + a + “B = ” + b);
}
}
The output of this program is….
Before calling swap() method
A = 20 B = 40
After calling swap() method
A = 20 B = 40
Here we have declared the method swap() static. We will study about this static word later on. This output clearly shows that the value of actual arguments remains same even when the function swap() is called. Figure 3 shows this.
Figure 3
Call by Reference
In Java, arguments that are objects are passed by reference to the called method. In call by reference, any change made to the object by the called method is reflected back in the calling method.
Program ReferencePass.java illustrates this.
// Program ReferencePass.java
class Obj
{
int a, b;
void setdata((int aa, int bb)
{
a = aa;
b = bb;
}
static void swap(Obj t)
{
int temp;
temp = t.a;
t.a = t.b;
t.b = temp;
}
void display()
{
System.out.println(“A = ” + a + “B = ” + b);
}
}
class ReferencePass
{
public static void main(String args[])
{
Obj p = new Obj();
p.setdata(20, 40);
System.out.println(“Before calling swap() method”);
p.display();
Obj.swap(p);
System.out.println(“After calling swap() method”);
p.display();
}
}
The output of this program is….
Before calling swap() method
A = 20 B = 40
After calling swap() method
A = 40 B = 20
In this program we have declared the display() method static. We will discuss about static word later on. This output clearly shows that the changes made to the passed object in side the method do affect the actual object. Figure 4 shows this.
Figure 4
Arguments in main() Method
Since the main() method is called implicitly, therefore it receives arguments only from the command line, if required, using command line arguments. The command line arguments inside a Java program are accessed easily as they are stored as strings in the String array passed to main() as shown below:
public static void main(String args[])
{
// ….
}
Here args is an array of String (text) variables. When you run the program, the array will be filled with the values of any argument it was given to the command line. The args[0] contains the first parameter on the command line. Remind that all command line arguments are passed as strings; if you want to use numerical values then you have to convert these strings into appropriate numerical values.
Program- CommandLineArgDemo.java illustrates this.
// Program – CommandLineArgDemo.java
class CommandLineArgDemo
{
public static void main(String args[])
{
for (int i=0; i
System.out.println(args[i]);
}
}
When you run this program as:
• java CommandLineArgDemo I am 34 years old.
I
am
34
years
old.
Inheritance
Inheritance is the process of creating new classes, called derived classes, from existing class, called base classes. The base classes are also known as super classes and the derived classes are known as subclasses. The subclass inherits all the capabilities of the super class but can add new features and refinement of its own. For example, a child inherits properties from both its parents.
Actually the superclass represents the generalized properties and the subclass represents specialization in which the behavior of the super class is modified. For example, consider the case of railway tickets. A railway ticket can be of two types, Confirmed and Waiting. Both of these tickets have a lot of common attributes, for example, train number, date, time and destination. However a Confirmed ticket would also have a seta number, while a Waiting ticket would have a status.
Figure 5 illustrates this.
Figure 5
Types of Inheritance
There are two main types of inheritance:
• Single Inheritance
• Multiple Inheritance
In single inheritance, the subclasses are derived from one superclass. For example, the subclasses ConfirmedTicket and WaitingTicket are derivd from the superclass Ticket. Figure shows single inheritance.
In multiple inheritance, subclasses are derived from more than one superclass. The derived class inherits the data members and methods of all its superclasses. Figure 6 shows multiple inheritance in which the Child subclass is derived from two superclasses Father and Mother.
Figure 6
- Note that Java does not support multiple inheritance. But fortunately it provides the taste of multiple inheritance through interfaces.
Implementing Inheritance in Java
Java implements inheritance using the keywords – extends, in order to derive a subclass from the superclass.
Syntax
public class subclassname extends superclassname
{
// ….
// ….
}
Here the subclassname is the name of the subclass or derived class and superclassname is the name of the superclass or base class
In inheritance the basic properties of the superclass are extended to the subclass. The subclass inherits data members and methods from the super class; it may additionally have its own data member as well as methods.
Let us see a simple program that illustrates the concept of single inheritance.
class SuperClass
{
void addNum(int x, int y)
{
int z;
z = x+y;
System.out.println("Addition of numbers = "+z);
}
void subNum(int x, int y)
{
int z;
z = x - y;
System.out.println("Subtraction of numbers = "+z);
}
}
class SubClass extends SuperClass
{
void multNum(int x, int y)
{
int z;
z = x * y;
System.out.println("Multiplication of numbers = "+z);
}
}
class InheritDemo1
{
public static void main(String args[])
{
SubClass s = new SubClass();
s.addNum(10, 20);
s.subNum(55, 10);
s.multNum(25, 12);
}
}
The result of this program is….
Addition of numbers = 30
Subtraction of numbers = 45
Multiplication of numbers = 300
- Note that the SubClass can be the Superclass for another SubSubClass. In such case a class inherits not only from its immediate superclass, but also from any superclass upwards.
Method Overriding
Generally when a method is called using an object then the Java looks for the method definition in the object’s class. If it can not find in the subclass, then it checks one level up in the hierarchy of classes. However if the same method name appears in both the subclass and superclass with the same signature (same number of arguments with the same type) then the method is said to be overridden. Thus method overridden is a concept where the same method name is used in both the subclass and superclass with the same signature. In such case when a method is called by an object of the subclass then it is the subclass’s method which would be called.
Program CallConstDemo2.java illustrates this.
class First
{
int a;
void setdata(int aa)
{
a = aa;
}
void display()
{
System.out.println("A = "+a);
}
}
class Second extends First
{
int b, c;
void setdata(int bb, int cc)
{
b = bb;
c = cc;
}
void display()
{
System.out.println("B = "+b);
System.out.println("C = "+c);
}
}
class CallConstDemo2
{
public static void main(String args[])
{
First f = new First();
Secon s = new Second ();
f.setdata(-1);
s.putdata(200,300);
f.display();
s.display();
}
}
The output of this program is….
A = -1
B = 200
C = 300
But it does not mean that you can’t call the base class method in the derived class method. Of course you can call base class method in the derived class method using the super keyword along with the name of the method. The methods setdata() and display() defined in class Second can be redefined as:
void setdata(int aa, int bb, int cc)
{
super.setdata(aa);
b = bb;
c = cc;
}
void display()
{
super.display(); // Calling display() method of superclass
System.out.println("B = "+b);
System.out.println("C = "+c);
}
Now when you compile and run this program it will produce the following output….
A = -1
A = 100
B = 200
C = 300
- Note that a superclass method is overridden by the subclass method only when they have identical names and identical signature (number of argument and type of arguments). If there is any mismatch then the two methods are simply treated as overloaded method. Also the return type of both overridden methods must be identical.
Encapsulation and Polymorphism
Encapsulation plays an important role in software developments. The wrapping up of data and methods into a single entity is called encapsulation. In Java the basis of encapsulation is class. Encapsulation is also called as information hiding since it involves hiding many of important details of an object from the user. User can not directly access data that resides in an object. It can be accessed by the methods of an object. This insulation of the data from direct access by the program is called as data hiding.
Polymorphism is another important object oriented programming feature. In a general term, polymorphism means the ability of having more than one form. In OOPs world, polymorphism is the ability for a data to be processed in more than one form. This facility helps different objects to react differently to the same operation.
Dynamic Binding
Java supports run-time polymorphism with the help of overridden method. Earlier we have seen that when an object’s method is called, Java looks for the method definition in the object’s class. If it can not find, then it checks one level up in the hierarchy of classes. However if the same method name is used in both the subclass and superclass with the same signature then when the method is called by an object of the subclass then the method defined in he subclass is overridden. Polymorphism is directly or indirectly related to method overriding. Polymorphism is a process in which a call to an overridden method is resolved at run-time, rather than compile time. This process is also called as late binding or dynamic binding.
While using inheritance, one should note that the objects of subclasses can be assigned to super class reference. It means that the super class reference can refer to an object of any of its subclass.
Consider the following class hierarchy:
class First
{
//….
void display()
{
//….
}
}
class Second extends First
{
//….
void display() // Method overridden
{
//….
}
}
class Third extends Second
{
//….
void display() // Method overridden
{
//….
}
}
Now let we create three objects of three classes as:
First f = new First();
Second s = new Second();
Third t = new Third();
These three statements create three objects of classes – First, Second and Third respectively. Now let we create a reference of a super class First as:
First fref;
This superclass reference can refer to object of super class First as well as its subclasses Second and Third as:
fref = f; // valid - refer to super class (First) object
….
fref = s; // valid - refer to sub class (Second) object
….
fref = t; // valid - refer to sub class (Third) object
….
Now when we call a method display() using fref then the compiler invokes that particular version of display() that is being referred by the type of the object rather than type of the reference variable. Thus when an overridden method is called through a super class reference then it is the type of the object being referred to that determines which version of an overridden method will be executed. Let us see the complete program that illustrates this.
// Program – RefSuperDemo1.java
class First
{
void display()
{
System.out.println(“First”);
}
}
class Second extends First
{
void display()
{
System.out.println(“Second”);
}
}
class Third extends Second
{
void display()
{
System.out.println(“Third”);
}
}
class RefSuperDemo1
{
public static void main(String args[])
{
First f = new First();
Second s = new Second();
Third t = new Third();
First fref; // Super class reference
fref = f; // refer to super class (First) object
fref.display();
fref = s; // refer to sub class (Second) object
fref.display();
fref = t; // refer to sub class (Third) object
fref.display();
}
}
The output of this program is….
First
Second
Third
- Note that you can also assign an object of a subclass type to an object of superclass type. Thus the following assignment is also completely valid:
First f = new First();
Second s = new Second();
f = s;
Constructors and Finalizers
Java provides two special kinds of methods – constructor and finalizers.
- Constructors – methods that return new instanbces of the class. If no constructor is specified then a default constructor is provided by the Java to create instances of the class
- Finalizers – methods that are called just before an object is garbage collected
Let us discuss about constructors first.
Constructors
The programs that we have seen so far initializes the data members using member functions like setdata() and you have to explicitly call this function. Like C++, Java provides – constructor, a special member function for initializing the data members of a class. It is executed automatically when an object of the class is created. Constructors has two types:
• Constructors with no arguments
• Constructors with arguments
The constructors have exactly the same name as the class of which they are members.
Example
class Distance
{
int meter;
float cm;
Distance() // no-argument constructor
{
meter = 10;
cm = 10.0f;
}
….
}
In the above example, whenever an object, say d1, of the Distance class is created as:
Distance d1 = new Distance();
the constructor is executed and it initializes the member variables to the specified values 10 and 10.0f respectively.
Rules for Constructors
1. The constructor has the same name as the name of the class in which it is defined. It is so because when an object is created then the Java compiler must know which function should be called implicitly.
2. Another main point to note while using constructors is that it has no return type because it is called implicitly and returning a value would not make sense.
The earlier defined constructor receives no argument. In this case if you create four objects then the data members of all the objects are initialized to 10 and 10.0f respectively. Therefore there is no big use of this type constructor.
Java also provides constructors that receive arguments and such constructors are called parameterized constructors.
Example:
class Distance
{
int meter;
float cm;
Distance(int mm, float cc) // parameterized constructor
{
meter = 10;
cm = 10.0f;
}
….
}
Here the constructor has two arguments in its argument list. This argument list is used to initialize the data members of an object when it is created. Now whenever an object, say d2, of the Distance class is created as:
Distance d2 = new Distance(40, 75.5f);
the parameterized constructor is executed and it initializes the data members to the specified values 40 and 75.5f respectively. Similarly you can create other objects as:
Distance d3 = new Distance(25, 10.5f);
Distance d4 = new Distance(86, 55.0f);
Now let us see a simple program that illustrates the concept of constructors.
class Distance
{
int meter;
float cm;
Distance() // no-argument constructor
{
meter = 10;
cm = 10.0f;
}
Distance(int mm, float cc) // parameterized constructor
{
meter = mm;
cm = cc;
}
void display()
{
System.out.println(meter + “ ” + cm);
}
}
class ConstructorDemo
{
public static void main(String args[])
{
Distance d1, d2;
d1 = new Distance(); // Calling no argument constructor implicitly
d2 = new Distance(20, 75.5f); // Calling two-argument constructor implicitly
d1.display();
d2.display();
}
}
The output of this program is….
10 10.0
20 75.5
In this program you have used more than one constructor in the same class. This is called overloaded constructor. Overloaded constructors are distinguished by the list of arguments they have. Each constructor has unique list of parameters with respect to the number and types of the argument.
Here one should remind that if your program has only one constructor, say
Distance(int mm, float cc)
{
meter = 10;
cm = 10.0f;
}
then the compiler would not let you create a Distance object any other way. It means that all declarations of Distance object must have two arguments of type int and float respectively. If you try to create an object of Distance in some other way, say
Distance d1 = new Distance();
Or
Distance d2 = new Distance (25);
then you will encounter the following error message:
- No constructor matching Distance() found in class Distance
- No constructor matching Distance(int ) found in class Distance
The Default Constructor
However if you don’t specify any type of constructor and you create an object of Distance as:
Distance d1 = new Distance();
Then the compiler calls the default constructor even though it was not defined explicitly. This process is done automatically.
The conclusion is that if you write a constructor then the compiler says – “You have written a constructor, so you know what you are doing and therefore you should write all type of constructors”. If you do not write any type of constructor then the compiler says – “You are bound to need some constructor, so let me make one for you”.
Order of Calling Constructors in Java
As stated earlier when an object is created, it calls the default constructor. When we create an object of the subclass, it automatically calls the super class constructor prior to the subclass constructor. Consider the following code segment:
class First
{
First()
{
System.out.println(“First Constructor.”);
}
}
class Second extends First
{
Second ()
{
System.out.println(“Second Constructor.”);
}
}
Now when we create an object of Second class as:
Second s = new Second();
It will invoke the constructor of the class First and then the constructor of the class Second and displays the following result:
- First Constructor.
- Second Constructor.
This is absolute true for the default constructor or you can say zero-argument constructor. But if you have constructors with arguments then you need to explicitly call the superclass constructors. The superclass constructors are called using the keyword – super, as :
super (list_of_arguments);
The list_of_arguments consists of one or more arguments needed by the constructor in the super class. The super() call must appear as the first statement in the subclass constructor.
Now let us see a simple program that illustrates this concept.
class First
{
int a;
First(int aa)
{
a = aa;
}
}
class Second extends First
{
int b, c;
Second (int aa, int bb, int cc)
{
super(aa); // Calling superclass one-argument constructor
b = bb;
c = cc;
}
int sum ()
{
return(a+b+c);
}
}
class CallConstDemo1
{
public static void main(String args[])
{
Second s = new Second (100, 200, 300);
int d = s.sum();
System.out.println(“Addition = ”+d);
}
}
The output of this program is….
Addition = 600
Note that it is necessary to call superclass constructor in the subclass constructor; otherwise the compiler will report an error message. Also when you invoke the super call with some argument then it must match the order and type of the instance variable declared in the super class.
You can also invoke the superclass constructor with an object of subclass as an argument. Program RefSuperDemo2.java illustrates this concept.
// Program - RefSuperDemo2.java
class First
{
int a;
First()
{
a = -1;
b = -1;
}
First(int aa)
{
a = aa;
}
First (First obj)
{
a = obj.a;
}
void display()
{
System.out.println(“A = ”+d);
}
}
class Second extends First
{
int b, c;
Second()
{
super();
b = -1;
c = -1;
}
Second (int aa, int bb, int cc)
{
super(aa); // Calling superclass one-argument constructor
b = bb;
c = cc;
}
Second (Second obj)
{
super(obj);
b = obj.b;
c = obj.c;
}
void display()
{
super.display(); // Calling display() method of superclass
System.out.println(“B = ”+b);
System.out.println(“C = ”+c);
}
}
class RefSuperDemo2
{
public static void main(String args[])
{
Second s1 = new Second();
Second s2 = new Second (100, 200, 300);
Second s3 = Second (s2);
First f ;
f = s1;
f.display();
f = s2;
f.display();
f = s3;
f.display();
}
}
The only notable point in this program is the following constructor:
Second (Second obj)
{
super(obj);
b = obj.b;
c = obj.c;
}
Here we have called super() with an object, obj, of subclass Second. This is completely valid because reference variable of superclass can refer to an object of any subclass derived from that superclass.
Finalizers
Sometimes an object will need to perform some action when it is destroyed. For example, an object needs to close open files or connections, or to ensure that related tasks are completed before the object id forgotten. To handle such situations, Java provides special functions, known as finalizers. Finalizers are special functions which are called just before an object is garbage collected. And this process is called finalization.
To create a finalizer, you simply define the finalize() method as:
proteced void finalize()
{
// ….
}
The Java runtime calls this finalize() method just before a class is garbage collected. Here the keyword protected is a specifier that prevents access to finalize() by code defined outside the class. Remind that this method is only called when just prior to garbage collection rather than when an object goes out of scope. Therefore you can not predict when – or even if - finalize() will be executed; it could be within microseconds or, if the program is terminated, may never occur. The conclusion is that one must not rely on finalize() method for normal program execution and provide some other means of releasing of releasing of system resources, used by the object.
Garbage Collection
In Java objects are dynamically created by using new operator. What happens when an object goes out of scope or you can say when an object is no longer needed by the system? For example, consider the following code segment and figure 7 illustrates what “no longer needed” means:
d1 = new Distance(40, 75.5);
d1 = new Distance(15, 25.75);
Figure 7
Here two objects are created in this code but only one object variable is here. After the first statement, the distance object d1 points to the object representing meter = 40 and cm = 75.5. After the second statement, d1 points to the object representing meter = 15 and cm = 25.75, and nothing points to the first object.
If you are migrating from C++ then you might think that when an object is created dynamically then it must be released by some means, as we do using delete operator in C++. But Java takes a different approach; it handles deallocation for you dynamically. Java automatically reclaims memory used by an object when no object variables refer to that object. This process is known as garbage collection. Thus no explicit needs to destroy objects in Java as in C++.
Java’s Access Specifiers
Access specifiers determine which features of a class (the data members, the methods, and the class itself) may be used by other classes.
The default Access Specifier
Classes written so far have default access. By default access it means a class is available to any other class in the same package (a package is a collection of classes). Similarly a variable or a method without any access modifier is available to any other class in the same package. The default access specifier is also known as friendly access specifier. Java has four types of access specifiers (also known as access modifiers):
• public
• private
• protected
• private proteced
The public Access Specifier
The public access specifier makes a data member or a method completely available to all classes. Also when a class is defined as public, it can be accessed by any other class.
Example
public class Sample
{
public int count;
public void increment()
{
// ….
}
}
The private Access Specifier
The private access specifier hides a data member or a method from all classes. Classes can not be declared as private, since the classes are to be available to other classes in the same package. A private data member can be used by methods defined in it’s own class but not by objects of any other classes.
class Sample
{
private int count;
private void increment()
{
// ….
}
}
The protected Access Specifier
The protected access specifier applies to data members as well as methods of a class. The protected data member and methods will be available to all classes in the same package. They will also be available to subclasses in other packages subjected to certain conditions.
class Sample
{
protected int count;
protected void increment()
{
// ….
}
}
The private protected Access Specifier
A member can be declared with two keywords – private and protected together as:
private protected int num;
The private protected access specifier makes a member visible in all subclasses regardless of what package they are in. Such members are not accessible by other classes in the same package.
Let us understand this concept. Let we have two packages ‘A’ and ‘B’ as:
• Package ‘A’ has one super class – ‘X’ and one subclass ‘XX’ of ‘X’. The class ‘X’ has a protected method – ‘M’
• Package ‘B’ has a class ‘Y’, derived from the class ‘X’ and a subclass ‘YY’ of ‘Y’.
Figure 8 shows this relationship.
Figure 8
Here the method ‘M’ can be invoked by the classes ‘X’ and ‘XX’ in the same package – ‘A’ as well as by the class ‘Y’ in package – ‘B’.
This Table summarizes these access specifiers.
Access |
Public
|
Protected
|
Default (friendly)
|
Private
|
Private Proteced
|
From the same class |
Yes |
Yes |
Yes |
Yes |
Yes |
From any class in the same package |
Yes |
Yes |
Yes |
No |
No |
From any class outside the package |
Yes |
No |
No |
No |
No |
From a subclass in the same package |
Yes |
Yes |
Yes |
No |
Yes |
From a subclass outside package |
Yes |
Yes |
No |
No |
Yes |