Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
114 views

Java 3

The document discusses inheritance in object-oriented programming using Java. It explains that inheritance allows a subclass to inherit and reuse attributes and behaviors of its parent superclass through the "extends" keyword. This creates an "is-a" relationship where the subclass is a type of the superclass. The document provides an example where the Parrot class extends the Bird class, allowing it to both use methods defined in Bird like eat() and define its own methods like food(). It contrasts inheritance with composition and discusses how subclasses can access superclass members but not vice versa.

Uploaded by

naresh maddu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
114 views

Java 3

The document discusses inheritance in object-oriented programming using Java. It explains that inheritance allows a subclass to inherit and reuse attributes and behaviors of its parent superclass through the "extends" keyword. This creates an "is-a" relationship where the subclass is a type of the superclass. The document provides an example where the Parrot class extends the Bird class, allowing it to both use methods defined in Bird like eat() and define its own methods like food(). It contrasts inheritance with composition and discusses how subclasses can access superclass members but not vice versa.

Uploaded by

naresh maddu
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

Inheritance:::

After Encapsulation, the second OOPS feature is "Inheritance". In the


previous Parrot program, the Parrot created an object of Bird and used
Bird's method eat(). Now in inheritance, we call the eat() method with
Parrot object itself (and not with Bird object). This is the difference
between composition and inheritance. In composition, same class object is
used and in inheritance another class object is used; the another class
is known as subclass or derived class. Let us go into the details. Let us
revise the earlier Parrot.java program as follows.

class Bird
{
public void eat()
{
System.out.println("All birds eat for their metabolic
activities");
}
}
public class Parrot extends Bird
{
public static void main(String args[])
{
Parrot p1 = new Parrot();
p1.eat();
}
}

You observe one new keyword "extends" in the above code; Parrot extends
Bird. By extending Bird class, Parrot can create an object of itself and
call eat() method of Bird. By extending, Parrot makes a relationship with
Bird. This relationship is known as "inheritance". The class which
extends is known as subclass (or derived class) and the class getting
extended is known as super class (or base class). Bird is called as base
class and Parrot is known as derived class. Observe the next program
where a subclass uses both composition and inheritance.

Composition and Inheritance

By virtue of inheritance, the subclass object can call super class


methods and variables. But remember, the super class cannot call subclass
members. In inheritance subclass is very rich because it can make use of
its own methods and also super class methods. Following program explains.

class Bird
{
String mouth = "red";
public void eat()
{
System.out.println("All birds eat for their metabolic
activities");
}
}
public class Parrot extends Bird
{
String body = "green";
public void food()
{
System.out.println("Parrot eats seeds and fruits");
}
public static void main(String args[])
{
Parrot p1 = new Parrot();
// calling its own members with its object
System.out.println(p1.body);
p1.food();
// calling super class members with its
object; inheritance
System.out.println(p1.mouth);
p1.eat();
// calling super class members with super
class object; composition
Bird b1 = new Bird();
System.out.println(b1.mouth);
b1.eat();
}
}
In the above code, the Parrot class uses both composition (as b1.eat())
and inheritance (as p1.eat()) to use super class members.

Inheritance – "is-a" Relationship

We know earlier, composition uses "has-a" relationship. Now inheritance


uses "is-a" relationship. We can feel as, a super class method is a
subclass method; that is, the super class eat() method exists as if in
the subclass; thereby the subclass object calls the super class method
without any hesitation and straightway. This is known as "is-a "
relationship. "is-a" relationship is achieved through inheritance.

Java Extends:::
An OOPs language is meant more for reusability. It achieves reusability
with "has-a" relation (through composition) and "is-a" relation (through
inheritance). For "has-a" relationship, known as composition in Java,
refer Composition – "has-a" Relationship. Now let us discuss inheritance
and how the reusability is achieved. To get the concept, very small
programs are given.

Before going into the discussion, you are expected to know what a class
is in Java and the syntax of writing a Java class. This you can get from
What is a class in Java? and if you would like to know from the beginning
know from, Java for Beginners.

Observe the following to classes.

public class Bird


{
public void walk()
{
System.out.println("Bird can walk");
}
}

public class Ostrich


{
public void run()
{
System.out.println("Ostrich can run at good speeds");
}
}
Now observe, the Bird and Ostrich are two different classes which are in
no way connected. Both are practically disjoint. One does not know the
other. Now let us go into our topic.

Because Ostrich is a bird and also can walk, I must write a method called
walk() in Ostrich class because Ostrich does not have the method. Yes,
you and everyone accept. OOPs comes into play here. OOPs is meant for
reusability, I told earlier. OOPs says, do not write, I give a solution
for it.

OOPs says, connect Ostrich with Bird so that Ostrich can use Bird’s
walk() method (like a son is connected to father, so that son can make
use of father’s property). Idea is good, but how to do it
programmatically. Java say, use "extends" keyword and the problem is
solved.

The above two classes are modified as follows just with an addition of
extends keyword.

public class Bird


{
public void walk()
{
System.out.println("Bird can walk");
}
}

public class Ostrich extends Bird


{
public void run()
{
System.out.println("Ostrich can run at good speeds");
}
}
Observe, "Ostrich extends Bird". When Ostrich extends Bird class, Ostrich
can make use of all the property of Bird like variables, methods and
constructors (right now we are having methods only here). Just for
execution purpose, I add one main() method in Ostrich class.

class Bird
{
public void walk()
{
System.out.println("Bird can walk");
}
}

public class Ostrich extends Bird


{
public void run()
{
System.out.println("Ostrich can run at good speeds");
}
public static void main(String args[])
{
Bird b1 = new Bird(); // create a Bird object
b1.walk(); // Bird object b1 is calling its own
walk() method

Ostrich o1 = new Ostrich(); // create a Ostrich object


o1.run(); // Ostrich object1 o1 is calling its
own run() method
o1.walk(); // now Ostrich object1 o1 is calling
Bird’s walk() method. THIS IS THE POWER OF INHERITANCE
}
}
Now let us watch the code.

public class Ostrich extends Bird

The disjoint two classes are joined with extends keyword. That is,
"extends" joins or links two classes in Java. The advantage of linking is
now the Ostrich can make use of Bird’s methods. This is discussed down.

Bird b1 = Bird();
b1.walk();

Nothing great in the above code, as Bird object b1 is calling its own
walk() method (like you are eating from your own plate). Observe the
following code.

Ostrich o1 = new Ostrich();


o1.run();
o1.walk();

Ostrich object o1 is calling its own method run() and is no great. The
greatness comes now. Observe, the Ostrich object o1 is calling walk()
method of Bird (like you are eating from other’s place which is not
permitted by the other). Here object belongs to Ostrich and method
belongs to Bird. That is, walk() method of Bird is used by Ostrich. This
avoids writing again walk() method in Ostrich class (because Ostrich also
wants to walk). This we call as "code reusability".

Shall I go a little further? Does the following is works?

b1.run();

The strange thing here is the Bird object is calling Ostrich method
run(). No it is not possible (like a father does not have right over
son’s property).

Inheritance

Now let us add some technical words (for nothing but to confuse you, but
no escape). When Ostrich extends Bird, there establishes a relation
between them (earlier not as they are disjoint). The relation we call as
"inheritance", one of the OOPs concepts, the other being encapsulation
and polymorphism. To inherit we used extends keyword. The class which
extends is known as subclass and the class which is getting extended is
known as super class. In the above code, Ostrich is subclass and Bird is
super class.

The rule says, "subclass can make use of super class members but super
class cannot make use of subclass members". That is, Bird cannot make use
of Ostrich methods.

Now, I am sure you are clear of what is inheritance, extends, super class
and subclass. Any query may be posted to me in the comment box down.
Note: Would you like to know a how super class can call subclass methods?
It is very secret. To know the secret click here (which is possible
through object casting that leads to polymorphism).

Java Extend Multiple Classes::


In the earlier, Bird-Ostrich inheritance program, Ostrich extends only
one class, Bird, because Ostrich wants to walk and the method is there in
Bird’s class.

Now Ostrich also wants to eat but the eat() method is there in another
class Animal. Now, it is required to Ostrich to extend two classes Bird
and Animal. Observe the following pseudo code.

class Animal
{
// eat() method exists her
}

class Bird
{
// walk() method exists her
}

public class Ostrich extends Bird, Animal


{
// Ostrich wants both walk() and eat()
}

As you can observe in the above code, after extends two classes exist,
Bird and Animal. This is not permitted by Java. If you write multiple
classes after extends, it comes under multiple inheritance and Java does
not support. That is, Java permits to extend only one class. But Ostrich
wants both. How to solve the problem?

Very simple. As Java permits to extend only one class, we write multiple
classes that extends only one to the other like a ladder.

class Animal
{
// eat() method exists her
}

class Bird extends Animal


{
// walk() method exists her
}

public class Ostrich extends Bird


{
// Ostrich wants both walk() and eat()
}
You can see in the above code, one-to-one ladder like Ostrich extends
Bird and Bird extends Animal (and infact, this ladder can go any extent).

Let us rewrite the earlier Bird-Ostrich code where we add one more class
Animal.

class Animal
{
public void eat()
{
System.out.println("Animal can eat");
}
}

class Bird extends Animal


{
public void walk()
{
System.out.println("Bird can walk");
}
}

public class Ostrich extends Bird


{
public void run()
{
System.out.println("Ostrich can run at good speeds");
}
public static void main(String args[])
{
Animal a1 = new Animal(); // create a Animal object
a1.eat(); // Animal object a1 is calling its
own eat() method

Bird b1 = new Bird(); // create a Bird object


b1.walk(); // Bird object b1 is calling its own
walk() method
b1.eat(); // Bird object b1 calling its super
class Animal method eat(), permitted by inheritance

Ostrich o1 = new Ostrich(); // create a Ostrich object


o1.run(); // Ostrich object1 o1 is calling its
own run() method
o1.walk(); // now Ostrich object1 o1 is calling
Bird’s walk() method.
o1.eat(); // Ostrich also can call Animal's
eat() due to inheritance. THIS IS THE POWER OF INHERITANCE
}
}

Ostrich extends Bird and Bird extends Animal, it is one-to-one relation.


This type of relation is known as "multilevel inheritance". Other
inheritance is multiple inheritance.

Types of Inheritance:::
There exists basically three types of inheritance.

Multilevel inheritance
Multiple inheritance
Hierarchical inheritance
1. In single inheritance, one class extends one class only. In multilevel
inheritance, the ladder of single inheritance increases.
2. In multiple inheritance, one class directly extends more than one
class.
3. In hierarchical inheritance one class is extended by more than one
class.

For a fresher, it will be very confusing, no doubt. Let us go in detail


of each one programmatically. Remember, to learn Java, C++ knowledge is
not at all required. In fact, you learn OOPs concepts through C++ syntax
in C++ and through Java syntax in Java. That is all.

1. Multilevel Inheritance

In multilevel, one-to-one ladder increases. Multiple classes are involved


in inheritance, but one class extends only one. The lowermost subclass
can make use of all its super classes' members. Multilevel inheritance is
an indirect way of implementing multiple inheritance. Following program
explains.

class Aves
{
public void nature()
{
System.out.println("Generally, Aves fly");
}
}
class Bird extends Aves
{
public void eat()
{
System.out.println("Eats to live");
}
}
public class Parrot extends Bird
{
public void food()
{
System.out.println("Parrot eats seeds and fruits");
}
public static void main(String args[])
{
Parrot p1 = new Parrot();
p1.food(); // calling its own
p1.eat(); // calling super class Bird
method
p1.nature(); // calling super class Aves
method
}
}

Now, Parrot has two super classes Bird and Aves; but extended one-to-one.
Parrot can make use of the methods of Bird and Aves. Bird can make use of
the methods of Aves, but Parrot as a super class cannot access subclass
members. Following figure gives a schematic representation of the
multilevel hierarchy with the classes involved in the program.
Diagrammmmmmmmmmm

2. Multiple Inheritance

In multiple inheritance, one class extends multiple classes. Java does


not support multiple inheritance but C++ supports. The above program can
be modified to illustrate multiple inheritance. The following program
does not work.

calss Aves { }
class Bird { }
public class Parrot extends Aves, Bird { }
In the above code, Parrot extends both Aves and Bird. This is not
supported by Java and the above code raises compilation error. Following
is the schematic representation.

Diagrammmmmmmmmmmm

Note: Java supports multiple inheritance partially through interfaces.

3. Hierarchical Inheritance

In hierarchical type of inheritance, one class is extended by many


subclasses. It is one-to-many relationship. A realtime example is
available at dynamic binding.

class Aves
{
public void fly()
{
System.out.println("Generally, aves fly");
}
}
class Parrot extends Aves
{
public void eat()
{
System.out.println("Parrot eats fruits and seeds");
}
}
class Vulture extends Aves
{
public void vision()
{
System.out.println("Vulture can see from high altitudes");
}
}
public class FlyingCreatures
{
public static void main(String args[])
{ // all the
following code is composition for FlyingCreatures
Parrot p1 = new Parrot();
p1.eat(); // calling its
own member
p1.fly();
// calling super
class member by inheritance
Vulture v1 = new Vulture();
v1.vision(); // calling its own
member
v1.fly(); // calling super class member by
inheritance
}
}

In the above code, Aves class is extended by two classes – Parrot and
Vulture. Both classes can make use of the methods of Aves. Even though
the Parrot and Vulture are subclasses of the same class Aves, but still
they cannot make use of each other members. Parrot and Vulture are known
as "siblings". Siblings are disjoint and they cannot make use of other
members as between them no inheritance is involved (like two sons of a
father; one son's property cannot be shared by other but both can share
the property of father). Following is the schematic representation of the
classes involved.
Diagrammmmmmmm

Dynamic binding and dynamic polymorphism use hierarchical inheritance.

Disadvantages of Inheritance

Both classes (super and subclasses) are tightly-coupled.


As they are tightly coupled (binded each other strongly with extends
keyword), they cannot work independently of each other.
Changing the code in super class method also affects the subclass
functionality.
If super class method is deleted, the code may not work as subclass may
call the super class method with super keyword. Now subclass method
behaves independently.

Method Overriding::

Subclass can make use of super class methods straight away by virtue of
inheritnace. If the subclass does not satisfy about the functionality
(output) of the super class method, the subclass can rewrite with its own
functionality with the same method name. This concept is known as "method
overriding", supported by OOP languages like C++/Java. In method
overriding, super class and subclass have the method with the same
signature – same parameters and same return type.

Let us discuss rules of method overriding with the following example.

class Aves
{
public void nature()
{
System.out.println("Aves fly");
}
}
public class Vulture extends Aves
{
public void nature()
{
System.out.println("Flies very high altitudes");
}
public static void main(String args[])
{
Vulture v1 = new Vulture();
v1.nature();
}
}

In the above program, Aves and Vulture classes have the same method
nature() with their own functionalities (outputs).

If the super class and subclass have the same method, the subclass calls
its own method. By this rule, the subclass object, v1, calls its own
overridden method.

The method overloading and method overriding sounds similar; but they
differ completely.
Method Overloading Method Overriding
1. Happens in the same class Happens among two classes – a super class and
a subclass
2. No inheritance Happens in inheritance only
3. One method does not hide another Subclass method hides super class
method
4. Should have different parameters Should have same parameters
5. Return type is not bothered Should have the same return type
6. Leads to static binding and static polymorphism Leads to dynamic
binding, dynamic polymorphism and dynamic method dispatch
Table: Differences among overloading and overriding

Java Static Inheritance

Here, one rule to remember in inheritance is "static members of a class


cannot be overridden".

Why the static members cannot be overridden?

Generally, any member (variable or method) when overridden by the


subclass, the subclass can call the super class member with "super"
keyword. But "static member" cannot be called as with static members
"this" reference cannot be used because static members can be called
without the help of an object. When static members are overridden, the
compiler does not raise error as compiler treats both are different
belonging to their own class.

The above explanation will be clearer with the following program.

class Test
{
public static void display()
{
System.out.println("Hello 1");
}
}
public class Demo extends Test
{
public static void display()
{
// super.display(); // raises compilation error
System.out.println("Hello 2");
}
public static void main(String args[])
{
display();
Test.display();
}
}

The display() method is static in the super class Test and also in
subclass Demo. Compiler does not treat it as method overriding as it
feels each display() method belong to it's own class.

// super.display();

"super" cannot be used with static members and raises compilation error.

display();
Test.display();

The display() declared in Demo class calls its own and Test.display()
calls Test class display() method. No ambiguity in understanding by the
compiler.

Final conclusion: Static members of a class cannot be overridden and


"super" keyword cannot be used with static members (say, to call super
class static method from subclass static method).

Note: Private members of a class cannot be overridden. But public,


protected and default members can be overridden.

Member Hiding – super Keyword::

We know earlier, in method overriding, the subclass method supersedes the


super class method. When the method is overridden in inheritance, the
subclass object calls its own method. If it calls its own method, the
subclass looses the functionality of the super class method (of course,
subclass is at liberty). If the subclass would like to call the super
class method also, the subclass can do so using "super" keyword. "super"
keyword is used by the subclass to call that of super class also when the
methods or variables are overridden. "super" keyword can be used with
instance variables and methods but not with classes.

1. super with Methods

In the following program, subclass overrides the eat() method of super


class and at the same uses both with "super" keyword.

class Bird
{
public void eat()
{
System.out.println("Eats insects.");
}
}
public class Sparrow extends Bird
{
public void eat()
{
super.eat();
System.out.println("Eats grains.");
super.eat(); // again you can call
}
public static void main(String args[])
{
Sparrow s1 = new Sparrow();
s1.eat();
}
}
The eat() method exists in both Bird and Sparrow classes. We say, super
class method is overridden by subclass. s1.eat() calls its own (Sparrow)
method. Sparrow uses "super.eat();" to call Bird's eat() method. The next
program illustrates "static" with variables.
Note:

"super" keyword cannot be used from static methods like main().


Static methods cannot be overridden (cannot be called with super
keyword).
2. super with Variables

You have seen earlier "super" with methods. Let us go for with variables.

class Packing
{
int cost = 50;
}
public class TotalCost extends Packing
{
int cost = 100;
public void estimate()
{
System.out.println("Cost of articles Rs." + cost);
System.out.println("Packing expenses Rs." + super.cost);
System.out.println("Total to pay Rs." + (cost + super.cost));
}
public static void main(String args[])
{
TotalCost tc1 = new TotalCost();
tc1.estimate();
}
}

In the above code, cost variable of Packing class is overridden by


TotalCost. In this case, the subclass object prefers to call its own
variable. super.cost calls super class cost variable. super.cost cannot
be called from static methods like main() method.
Programming Tip: Do not attempt to use super keyword with classes. It is
a compilation error.

"super" and "this"

In java, "super" keyword is used to call super methods and variables


(when overridden only, else, not necessary to use) and "this" keyword is
used to refer the current object.

Constructors and Constructor overloading:::


A constructor looks more like a method but without return type. Moreover,
the name of the constructor and the class name should be the same. The
advantage of constructors over methods is that they are called implicitly
whenever an object is created. In case of methods, they must be called
explicitly. To create an object, the constructor must be called.
Constructor gives properties to an object at the time of creation only.
programmer uses constructor to initialize variables, instantiating
objects and setting colors. Constructor is equivalent to init() method of
an applet.

Default Constructor – No Argument Constructor

A constructor without parameters is called as "default constructor" or


"no-args constructor". It is called default because if the programmer
does not write himself, Java creates one and supplies. The default
constructor supplied does not have any functionality (output).

public class Demo


{
public Demo()
{
System.out.println("From default constructor");
}
public static void main(String args[])
{
Demo d1 = new Demo();
Demo d2 = new Demo();
}
}

public Demo()

"public" is the access specifier and "Demo()" is the constructor. Notice,


it does not have return type and the name is that of the class name.

Demo d1 = new Demo();

In the above statement, d1 is an object of Demo class. To create the


object, the constructor "Demo()" is called. Like this, any number of
objects can be created like d2 and for each object the constructor is
called.

Constructor Overloading

Just like method overloading, constructors also can be overloaded. Same


constructor declared with different parameters in the same class is known
as constructor overloading. Compiler differentiates which constructor is
to be called depending upon the number of parameters and their sequence
of data types.

public class Perimeter


{
public Perimeter()
// I
{
System.out.println("From default");
}
public Perimeter(int x)
// II
{
System.out.println("Circle perimeter: " + 2*Math.PI*x);
}
public Perimeter(int x, int y) //
III
{
System.out.println("Rectangle perimeter: " +2*(x+y));
}
public static void main(String args[])
{
Perimeter p1 = new Perimeter(); // I
Perimeter p2 = new Perimeter(10); // II
Perimeter p3 = new Perimeter(10, 20); // III
}
}

Perimeter constructor is overloaded three times. As per the parameters,


an appropriate constructor is called. To call all the three constructors
three objects are created. Using this(), all the three constructors can
be called with a single constructor.
this() with Constructors
Suppose by accessing one constructor, the programmer may require the
functionality of other constructors also but by creating one object only.
For this, Java comes with this(). "this()" is used to access one
constructor from another "within the same class". Depending on the
parameters supplied, the suitable constructor is accessed.

public class Perimeter


{
public Perimeter()
// I
{
System.out.println("From default");
}
public Perimeter(int x)
// II
{
this();
System.out.println("Circle perimeter: " + 2*Math.PI*x);
}
public Perimeter(int x, int y)
// III
{
this(100);
System.out.println("Rectangle perimeter: " +2*(x+y));
}
public static void main(String args[])
{
Perimeter p3 = new Perimeter(10, 20); // III
}
}

In the code, creating object p3, the III constructor is accessed. From
III, with "this(100)" statement, the II constructor is accessed. Again
from II, the I is accessed without the statement "this()". As per the
parameter supplied to this(), the appropriate or corresponding
constructor is accessed.
Rules of using this()

A few restrictions exist for the usage of this().

If included, this() statement must be the first one in the constructor.


You cannot write anything before this() in the constructor.
With the above rule, there cannot be two this() statements in the same
constructor (because both cannot be the first).
this() must be used with constructors only, that too to call the same
class constructor (but not super class constructor).

Java Constructor Properties:::

Java comes with a set of special properties to constructors.


What can not:

1. "A constructor cannot be abstract, static, final, native, strictfp,


or synchronized".
2. Interface cannot have constructor.
3. Constructor cannot return a value.

What can:

1. A constructor can be private.


2. Abstract class can have constructor.
3. A constructor can be overloaded.

Instance variables and methods of a class are known as members of a


class. Constructors are not members. For this reason, constructors cannot
be inherited; but can be accessed by a subclass. What does it mean?
Constructors cannot be called with objects like d1.display(). To access a
constructor create an object or access with subclass constructor
(explicitly with super()).

Constructors are not inherited; only members (variables and methods) are
inherited. So declaring a constructor final does not have any meaning as
constructors cannot be overridden.

If a constructor is abstract, it cannot be implemented (cannot have body


or no code). A constructor should have a body as constructor gives
properties to an object at the time of creation itself.

Constructors are called when an object is created but cannot be called


like a method (like d1.show()) with an object; so no necessity for a
constructors to be static.

A constructor should not be synchronized as it locks the object in


creation and thereby, as long as the object is not created no other
object can be instantiated .

The methods which cannot be executed by JVM alone and depends on the
underlying OS are known as native methods. Native methods execution is
slow and for this reason many native methods throw a checked exception.

Declaring a constructor native is unnecessarily inviting trouble and also


a subclass constructor cannot call super class constructor easily.

Many Meanings of final Keyword – In and Outs:::


After going through "static" and "super" keywords, let us go another
keyword "final". These three keywords, known as access modifiers, are
used very often in Java code. The final keyword behaves very differently
when applied to variables, methods and classes. Even though its
functionality (purpose) is different in the three contexts, but one thing
is common; it does not allow the programmer to do certain actions.

A final variable cannot be reassigned.


A final method of the super class cannot be overridden by subclass
A final class cannot be extended by any other class. Final class does not
fit for inheritance.
Three programs are given to explain the above three rules.

1. final Keyword with Variables

"const" keyword of C/C++ is not supported by Java and in its place, Java
uses "final" keyword. That is, a final variable cannot be reassigned.
Once assigned, cannot be modified later.

public class Book


{
public static void main(String args[])
{
int cost = 400; // non-final, can be
modified later
System.out.println("Original Book cost Rs." + cost);
cost = 500;
System.out.println("Modified Book cost Rs." + cost);

final int packing = 50; // final, cannot be modified


later
System.out.println("Packing cost Rs." + packing);
// packing = 100; // raises error
}
}

In the above code, the variable cost is declared as non-final and packing
as final. The cost variable is reassigned to 500 but packing cannot be(if
the comments are removed in the code, it is compilation error). After
comfortable with final variables let us go to final methods.
2. final Keyword with Methods

In inheritance, the subclass is at liberty to use super class methods or


override and use its own methods. Moreover, with "super" keyword, it can
make use of its own and that of super class also. This is possible as
long as super class permits. We know earlier subclass is rich; but now I
say one more "super class is powerful". Subclass can play with super
class as long super class permits. At any time, super class can place
some restrictions on subclass about it' members usage.

Now the super class would like to place a small restriction on subclass;
it says, few methods of it's cannot be overridden. The super class
declares those methods as final. That is, final methods of the super
class cannot be overridden.

class Bird
{
public final void eat() // final method, cannot be
overridden
{
System.out.println("Birds eat");
}
public void fly() // non-final method, can be
overridden
{
System.out.println("Birds fly");
}
}
public class Peacock extends Bird
{
public void fly()
{
System.out.println("Peacock flies small distances");
}
public static void main(String args[])
{
Peacock p1 = new Peacock();
p1.eat(); // calling super class final method
p1.fly(); // calling its own overridden
method
}
}

In Bird's class, eat() method is declared as final and fly() as non-


final. The eat() method cannot be overridden by the subclass Peacock and
regarding fly() method, subclass is at liberty to override (method
overriding). In the above code, it is overridden. Infact, the subclass
can call super class fly() method also with super.fly() (not used in the
above code).

3. final Keyword with Classes

In inheritance, a class can be extended by another class; but it is at


the mercy of the super class. If the super class does not like any one to
inherit, simply it declares its class as "final". A final class cannot be
extended by any other class. A final class does not fit for inheritance.

final class Spacecraft // class is final


{
public void fly()
{
System.out.println("Spacecraft flies");
}
}
public class Aeroplane
{
public void fuel()
{
System.out.println("Aeroplane uses Hi-Octane petrol");
}
public static void main(String args[])
{
Aeroplane a1 = new Aeroplane();
a1.fuel();

Spacecraft s1 = new Spacecraft();


s1.fly(); // calling final class method with
composition
}
}
Spacecraft class is declared as final and for this reason, Aeroplane
cannot extend it. But Aeroplane class can make use of final class methods
by "composition".

Abstract Classes::

You have seen earlier two access modifiers – static and final. Now let us
go for another modifier "abstract". "abstract" modifier can be applied to
methods and classes, but not with variables. "abstract" means no code or
no implementation and just declares the method without the code.

We know earlier, super class is powerful and subclass is rich. Super


class can impose many restrictions on the usage of its members by
subclasses. One such you have seen earlier is final methods. Final
methods of the super class cannot be overridden by the subclass. Now the
super class would like a new restriction on the other way, just opposite.
Super class would like to force the subclass to override (just, the
opposite of final).

To achieve this, super class just declares its method without giving the
body. As compiler does not accept the method without body, to satisfy the
compiler, we declare the method as "abstract". That is, abstract method
does not have body (no implementation). If the super class declares the
method as abstract, subclass should and must override; else it is a
compilation error. This is how a super class imposes a restriction on the
subclass to forcibly override its method.
The compiler does not allow the super class to create an object as the
class contains some methods without body. To satisfy the compiler,
declare the class abstract. Declaring the class abstract, is a promise to
the compiler that the programmer is not going to create an object of it.
That is, with abstract classes, objects cannot be created.

Writing an Abstract Class

Let us see a program using abstract class.

abstract class Gandhiji


{
public abstract void fatherOfNation();
public abstract void independence();
}
public class GreatPeople extends Gandhiji
{
public void fatherOfNation()
{
System.out.println("Gandhiji is the father of Indian nation");
}
public void independence()
{
System.out.println("Gandhiji's great principle, Ahimsa, got
India, the independence");
}
public static void main(String args[])
{
GreatPeople gp1 = new GreatPeople();
gp1.fatherOfNation();
gp1.independence();
}
}

In the above program, methods fatherOfNation() and independence() are


declared as abstract as they do not contain body. Moreover, the Gandhiji
class is declared as abstract as it contains abstract methods. These
methods are overridden (given body) by the subclass GreatPeople. If
GreatPeople does not override with implementation details, the program
does not compile.

Super class gives the names and these names are used by the subclass with
its choicest code. Let us make some rules as per the understanding of the
program.

Abstract method does not have body.


If one of the methods of a class is abstract, the class should be
declared as abstract.
All the abstract methods of the super class should be overridden by the
some class.
With abstract classes, we cannot create objects (that is, abstract class
cannot be instantiated).
Abstract Classes – Combinations

Abstract methods are designed to force the subclass to override. It is


one of the design patterns. There are three variations of abstract
classes.

An abstract class having all abstract methods.


An abstract class having a mixture of concrete and abstract methods.
An abstract class having all concrete (non-abstract) methods.
Each combination has its own importance in coding design and the
neecessity is explained hereunder.

1. An abstract class having all abstract methods

In the earlier Gandhiji program all methods are abstract (includes two
methods). All the methods are implemented with body by subclass,
GreatPeople. If the programmer would like the subclass to give coding for
all the methods, he declares all the methods as abstract.

2. Containing Abstract and Concrete Methods

Non-abstract methods are called as "concrete methods". The abstract class


can contain a mixture of abstract and concrete methods. The architect
chooses this style when the super class forces only a few of its methods
to override and the other need not; then declares some methods as
abstract and others not. This style permits the super class to give body
(implementation) for some methods and some do not.

abstract class MotorCar


{
public abstract void fuel();
public abstract void brake();
public void airConditioning()
{
System.out.println("Air conditioning is optional");
}
}
public class Car extends MotorCar
{
public void fuel()
{
System.out.println("Must to use fuel");
}
public void brake()
{
System.out.println("Must to have brakes");
}
public static void main(String args[])
{
Car c1 = new Car();
c1.fuel();
c1.brake();
c1.airConditioning();
}
}

MotorCar includes two abstract methods and one concrete class. The
abstract methods, as per rule, are overridden by the subclass Car and the
concrete method, airConditioning(), is used as it is. The concrete method
is left to the discretion of the subclass to override or not.

3. Containing only Concrete Methods

Generally, many novices think that an abstract class should contain


atleast one abstract method. But it is a wrong idea because an abstract
class may contain all concrete methods and not even one abstract method.
Why this style? It looks not necessary. Just go through the next program
and notes.

abstract class MotorCar


{
public void fuel()
{
System.out.println("Must to use fuel");
}
public void brake()
{
System.out.println("Must to have brakes");
}
public void airConditioning()
{
System.out.println("Air conditioning is optional");
}
}
public class Car extends MotorCar
{
public static void main(String args[])
{
Car c1 = new Car();
c1.fuel();
c1.brake();
c1.airConditioning();
}
}

The previous program is modified to suit the concept; an abstract class


containing all concrete methods. All the methods, fuel(), brake() and
airConditioning() are given body. Subclass can straight away use them.
Then, what is the necessity for the super class to declare abstract (when
no method is abstract)? It just not to allow the subclass to create an
object of super class. Subclass can make use of super class methods by
composition.

More In and Outs of abstract methods and classes is available in the


following topics.

Interfaces – Partial implementation of Multiple Inheritance


We know earlier, Java does not support multiple inheritance, basically.
But to support multiple inheritance, partially, Java introduced
"interfaces". An interface is not altogether a new one for us; just it is
a special flavor of abstract class where all methods are abstract. That
is, an interface contains only abstract methods.

interface Suzuki
{
public abstract void body();
}
interface Ford
{
public abstract void engine();
}
public class MotorCar implements Suzuki, Ford
{
public void body()
{
System.out.println("Fit Suzuki body");
}
public void engine()
{
System.out.println("Fit Ford engine");
}
public static void main(String args[])
{
MotorCar mc1 = new MotorCar();
mc1.body();
mc1.engine();
}
}

In the above code there are two interfaces – Suzuki and Ford. Both are
implemented by MotorCar because it would like to have the features of
both interfaces. For this reason (to have the functionality of many
classes) only, Java supports multiple inheritance through interfaces.
Just to inform there are multiple interfaces and not classes, tell the
compiler by replacing "extends" with "implements". MotorCar, after
implementing both the interfaces, overrides the abstract methods of the
both – body() and engine(); else program does not compile. Java supports
multiple inheritance partially through interfaces. Following figure gives
the view of the above interfaces.
Diagrammmmmmmm

Features of Interfaces

Interfaces are derived from abstract classes with a special additional


rule that interfaces should contain only abstract methods. Let us see
some more properties.

- Interfaces support multiple inheritance which is not possible with


concrete and abstract classes.
"implements" keyword is used in place of "extends". "extends" comes with
concrete and abstract classes.
Interfaces must contain abstract methods only.
As in abstract classes, all the abstract methods of the interfaces should
be overridden by the subclass.
As with abstract classes, with interfaces also, objects cannot be created
but reference variables can be created.
Interface reference variable can be assigned with concrete subclass
objects. Once assigned, the interface reference variable works like an
object. This feature applies to abstract classes also.
As all methods must be abstract and public, these two keyword can be
omitted in method declaration. If omitted, JVM takes by default.
All interface variables must be public, static and final. If omitted,
they are taken by default.
All interface methods should be overridden with public only as overridden
method cannot have a weaker access specifier.
Later you get a table where actual differences between abstract classes
and interfaces are given.

Defining an Interface

We know earlier, interface should have only abstract methods (without any
body or implementation code). The abstract methods give a template
structure of methods from which subclasses can be developed easily.
Subclass job is just to override (or give the code) as per its
convenience and need not think about the design part (how many methods it
should contain, what are they, how they are related etc). Interfaces play
a vital role in Java coding and designing modules.

The interface methods can be implemented by various subclasses as per the


code appropriate to them. For example, the following "interface Mammal"
can be implemented by thousands of mammals as per their nature. Following
program is one of the generic implementations.
interface Mammal
{
String chambers = "4-chambered";
void offSpring();
void feed();
void blood(String str);
}
public class Nature implements Mammal
{
public void offSpring()
{
System.out.println("Only 3 mammals lay eggs and others give birth to
young ones");
}
public void feed()
{
System.out.println("Mammals feed the offspring with milk");
}
public void blood(String str)
{
System.out.println("Mammals are " + str + " and contains " + cambers
+ " heart");
}
public static void main(String args[])
{
Nature n1 = new Nature();
n1.offSpring();
n1.feed();
n1.blood("warm-blooded");
}
}
-
"interface Mammal" includes three methods and one variable. In the method
declaration, the keywords public and abstract are omitted as a style and
if omitted, we know earlier, they are taken by default. Similarly, the
string variable "chambers" is, by default, public, static and final. That
is, interface variables cannot be reassigned (as they are implicitly
final).

The interface methods offSpring(), feed() and blood(String) can be


implemented by different species of animals in different ways as per
their nature. The above code is just one example of such implementations.

Compare and Contrast Abstract classes with Interfaces?

Even though the interface is a special derivative of abstract class; it


differs a lot with abstract class. Following table gives their
differences.

Abstract class Interface


1. Multiple inheritance is not supported Multiple inheritance is
supported
2. To inherit "extends" keyword is used To inherit "implements" keyword
is used
3. May include concrete methods also All must be abstract methods
4. Methods may be of any specifier except private. That is, may be
public, protected or default Methods must be public only
5. Access specifier should be written If omitted, taken by default (as
public)
6. Access modifier abstract should be written If omitted, taken by
default (as abstract)
7. Variables can be any access specifier including private Variables
should be public, static and final. If omitted, taken by default.
8. Constructors can be included in code No constructors
9. main() can be included in code main() method cannot be included
Table: Differences between abstract classes and interfaces
After knowing the differences, let us see the similarities.

With abstract classes and interfaces, objects cannot be created; but


reference variables can be created.
All the abstract methods of the both should be overridden by the
inherited class.
"Dynamic polymorphism" is supported by both.
Both works as template (structure of methods) from which new classes can
be derived easily.

Java Extend Multiple Classes::

In the earlier, Bird-Ostrich inheritance program, Ostrich extends only


one class, Bird, because Ostrich wants to walk and the method is there in
Bird’s class.

Now Ostrich also wants to eat but the eat() method is there in another
class Animal. Now, it is required to Ostrich to extend two classes Bird
and Animal. Observe the following pseudo code.

class Animal
{
// eat() method exists her
}

class Bird
{
// walk() method exists her
}

public class Ostrich extends Bird, Animal


{
// Ostrich wants both walk() and eat()
}

As you can observe in the above code, after extends two classes exist,
Bird and Animal. This is not permitted by Java. If you write multiple
classes after extends, it comes under multiple inheritance and Java does
not support. That is, Java permits to extend only one class. But Ostrich
wants both. How to solve the problem?

Very simple. As Java permits to extend only one class, we write multiple
classes that extends only one to the other like a ladder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Animal
{
// eat() method exists her
}

class Bird extends Animal


{
// walk() method exists her
}

public class Ostrich extends Bird


{
// Ostrich wants both walk() and eat()
}
You can see in the above code, one-to-one ladder like Ostrich extends
Bird and Bird extends Animal (and infact, this ladder can go any extent).

Let us rewrite the earlier Bird-Ostrich code where we add one more class
Animal.

class Animal
{
public void eat()
{
System.out.println("Animal can eat");
}
}

class Bird extends Animal


{
public void walk()
{
System.out.println("Bird can walk");
}
}

public class Ostrich extends Bird


{
public void run()
{
System.out.println("Ostrich can run at good speeds");
}
public static void main(String args[])
{
Animal a1 = new Animal(); // create a Animal object
a1.eat(); // Animal object a1 is calling its
own eat() method
Bird b1 = new Bird(); // create a Bird object
b1.walk(); // Bird object b1 is calling its own
walk() method
b1.eat(); // Bird object b1 calling its super
class Animal method eat(), permitted by inheritance

Ostrich o1 = new Ostrich(); // create a Ostrich object


o1.run(); // Ostrich object1 o1 is calling its
own run() method
o1.walk(); // now Ostrich object1 o1 is calling
Bird’s walk() method.
o1.eat(); // Ostrich also can call Animal's
eat() due to inheritance. THIS IS THE POWER OF INHERITANCE
}
}

Ostrich extends Bird and Bird extends Animal, it is one-to-one relation.


This type of relation is known as "multilevel inheritance". Other
inheritance is multiple inheritance.

Access Specifiers & Access Modifiers:::

Java supports both specifiers and modifiers that can dictate the access.
An access specifier can be applied to any identifier like variables,
methods and classes but modifiers cannot be applied to every identifier,
there are limitations. For example, the modifiers applied to variables
cannot be used with classes and similarly with methods also. A full
discussion of specifiers is given later.

Following list gives the details of access specifiers and modifiers that
can be applied to classes, variables and methods.

Class Specifiers & Modifiers

Three modifiers exist that can be applied to classes. Modifier comes just
before the class name.

Modifier Keyword Meaning


abstract Objects cannot be created
final cannot be inherited
strictfp Guarantees the same precision for floating-point values in the
class irrespective of the OS on which the program is executed
The two access specifiers a class can accept are public or default.
Default means the specifier is not mentioned at all.

Variable Specifiers & Modifiers

Four modifiers and four specifiers exist that can be applied to


variables.

Modifier Keyword Meaning


static Also known as "class variable". No object is necessary to call
final cannot be reassigned
transient Not serialized
volatile Value is more liable to change
All the four access specifiers, Java supports, can be applied to
variables – public, protected, default and private. If the specifier is
not mentioned, it takes default access. A local variable must be default
only.
Method Specifiers & Modifiers

Six modifiers exist that can be used with methods.

Modifier Keyword Meaning


final Subclass cannot override
abstract No method body exists
native Java method takes the help of underlying OS
static Object is not necessary to call
synchronized Used to lock the source and renders a thread-safe
operaton
strictfp Guarantees the same precision for floating-point values in the
class irrespective of the OS on which the program is executed
All the four access specifiers, public, protected, default and private,
can be applied to methods. If not mentioned any access specifier, JVM
takes default access.

Access restrictions of all four access specifiers are discussed in Access


Specifiers – Accessibility Permissions & Restrictions.

Rules of Access Specifiers in Method Overriding:::

The only rule says:

"The subclass overridden method cannot have weaker access than super
class method".

Following program illustrates.

class Test
{
protected void display() // protected specifier
{
System.out.println("Hello 1");
}
}
public class Demo extends Test
{
void display() // overridden with default specifier
{
System.out.println("Hello 2");
}
public static void main(String args[])
{
new Demo().display();
}
}

Protected display() method of Test class is overridden by Demo class with


default (not specified at all) access. It raises compilation error. The
subclass can have either same or stronger access like public or same
protected. But, it cannot have default or private.

Why the methods of an interface should be overridden with public only?

The methods of an interface must be public, if not mentioned, takes by


default as public. So, the subclass which implements the interface should
override with the same specifier or more but not less. No stronger
specifier than public exists in Java. For this, reason, all the methods
of interface must be overridden with public only.
Rules of exceptions also must be taken care in method overriding.

Access Modifiers – Meanings:::

We know access specifiers specify the access and access modifiers modify
the access of variables, methods and classes. In general, an access
modifier works between the classes of the same application or within the
classes of same package.

To understand better, let us take the examples of static and final access
modifiers. Generally a method or variable is called with an object, but
declaring static, you do not require the object. Similarly is with final
modifier also. Declaring a method final, the subclass is not allowed to
override the super method and a final variable cannot be reassigned.
Synchronized gives a meaning of multiple threads cannot access the same
method at a time. Now, you understand the meaning of "modifying the
access".

The access modifiers supported by Java are static, final, abstract,


synchronized, native, volatile, transient and strictfp. Many are
discussed at appropriate places in very detail and a few are explained
hereunder.

1. native Modifier

"native" keyword applies to methods. The code of a native method is


written in some other language like C or C++. At execution time, this
native code is executed separately and put with the Java output and is
given. To do all this, Java includes Java Native Interface (JNI) which is
inbuilt into JDK. “native” permits the Java developer to write the
machine-dependent code in other language (like C/C++) and make use in
Java. Alternatively, if a C or C++ function exists with a very complex
code, it is not required to convert it into Java code and instead can be
used directly in a Java program.

Observe some methods of Java API.

1
2
3
public static native void sleep(long) throws InterruptedException; //
belonging to Thread class

public native int read() throws IOException; // belonging to


FileInputStream class

Observe native keyword in the above two statements. The functions' code
is written in other language (means, not in Java). To execute these
methods, Java takes the help of underlying OS.

2. volatile Modifier

The keyword volatile applies to variables and objects. A volatile


variable value is more likely to get changed in the code. A volatile
variable is treated differently by the JVM.

Volatile variables are not optimized (to minimize execution time) for
performance by the compiler as their values are expected to get changed
at any time without information. Volatile is better used with multiple
threads that can change a variable value often.

Volatile can be used as follows.

public volatile int rate = 10;


Volatile does not have any meaning when applied to final variables or
immutable objects or synchronized block.

The following two statements give compilation error.

final volatile int x = 10;


volatile final int x = 10;

3. transient Modifier

It is used with Serialization. "transient" is a keyword which means the


data is not serialized. In object serialization, the objects along with
the data are serialized. If the data is not required to be serialized and
thereby not written to a file (or sent to the remote client/server), then
declare the data as transient.

Following is the way how to declare a variable as transient.

public transient double goldRate = 210.5;


A program on transient keyword is available at Java Serialization
Example.

4. strictfp Modifier

A floating-point value, in a language, is platform-dependent. That is,


the same floating value, in a Java program, executed on different
operating systems may give different outputs (precision). To get the same
precision (regardless of hardware, software and OS) on every operating
system, declare the class or method as strictfp. "strictfp" is a keyword
added in JDK 1.2 version.

"strictfp" is abbreviation for "strict floating-point".

public strictfp class Demo


public strictfp interface Demo
public strictfp void display()
If a class is strictfp, all the code in the class is evaluated with the
strict floating point precision as laid in IEEE 754 standards. strictfp
follows the rules formatted by IEEE 754. JVM does not apply its own
precision.

IEEE and IEEE 754

IEEE is an abbreviation for Institute of Electrical and Electronics


Engineers. It is a service-oriented body managed by professional
engineers. It is started in 1963 and operated in 150 countries with over
3.5 lakh members. It is an amalgamated body of Institute of Radio
Engineers and American Institute of Electrical Engineers. It sets
standards for many like for floating-point values used by CPU.

Following table gives the list of access specifiers and modifiers that
can be applied to variables, methods and classes.
specifier/modifier local variable instance variable method
class
public NA A A A
protected NA A A NA
default A A A A
private NA A A NA
final A A A A
static NA A A NA
synchronized NA NA A NA
native NA NA A NA
volatile NA A NA NA
transient NA A NA NA
strictfp NA NA A A
A: Allowed NA: Not Allowed

Java Private variable accessibility (Private access specifier)

"private" access specifier requires more elaborate discussion as many


people are not aware of its in and outs.

private variables and methods of a class can be accessed within the same
class only. By inheritance, even subclasses cannot use by composition.
Maximum other classes should call through the public methods of the same
class as in the following program.

class Test
{
private int x = 10;
public void display()
{
System.out.println(x);
}
}
public class Demo extends Test
{
public static void main(String args[])
{
Demo d1 = new Demo();
// System.out.println(d1.x); // error (inheritance)

Test t1 = new Test();


// System.out.println(t1.x); // error (composition)

t1.display(); // works nice


}
}
In the above code, the subclass object d1 of Demo class cannot call the
private variable x of the super class Test. That is, x can be accessed by
Test object only in Test class itself.

Demo can use Test class object to call display() method to print x value.

Dynamic Polymorphism::

Static binding and static polymorphism is achieved through method


overloading. Now let us go for dynamic polymorphism. Observe the
following code.

class Bird
{
public void eat() // I
{
System.out.println("All birds eat");
}
}
class Peacock extends Bird
{
public void eat() // II
{
System.out.println("Peacock eats grains");
}
}
class Vulture extends Bird
{
public void eat() // III
{
System.out.println("Vulture eats flesh");
}
}
class Crane extends Bird
{
public void eat() // IV
{
System.out.println("Crane eats fish");
}
}
public class DynamicPolyDemo
{
public static void main(String args[])
{
Bird b1 = new Bird(); b1.eat(); // calls I
Peacock p1 = new Peacock(); b1 = p1; b1.eat(); // calls II
Vulture v1 = new Vulture(); b1 = v1; b1.eat(); // calls III
Crane c1 = new Crane(); b1 = c1; b1.eat(); // calls IV
}
}

In the above code, Bird is inherited by three classes – Peacock, Vulture


and Crane. It is an example of hierarchical inheritance.

Subclasses Peacock, Vulture and Crane overrides the eat() method of Bird.

b1 = p1;
b1.eat();
In the above statement, subclass Peacock object p1 is assigned to super
class Bird object b1. Earlier, in Object Casting, we know if a subclass
object is assigned to a super class object, the super class object will
call subclass overridden method. As per this rule, b1 will call p1 eat()
method. Infact, the b1 contains the reference of p1.

b1 = v1;
b1.eat();
Now, the Bird object b1 is assigned with the subclass Vulture object v1.
Now the earlier p1 reference is replaced by v1. Now b1 points to v1
location. Now b1 calls v1 eat method.

b1 = c1;
b1.eat();
Again, the v1 reference in the super class object b1 is replaced by Crane
object c1. Now, b1 calls Crane's eat() method.
Observe the code, the statement b1.eat() prints 4 different outputs by
calling 4 different eat() methods. The same method when called different
times giving different values is known a polymorphism ("poly" means many
and "morphism" means forms).

Which eat() method is to be called is decided at runtime because in every


statement the address of the earlier subclass object is replaced. This
address replacement happens at runtime (and not at compile time). Which
overridden method is to be called is decided (or binded) dynamically at
runtime. This feature is known as dynamic binding. Because polymorphism
is achieved dynamically at runtime, this is known as dynamic
polymorphism.

Dynamic binding is also called as dynamic method dispatch as which


overridden method is to be dispatched for execution is known at runtime.

To achieve dynamic polymorphism following rules must be obeyed.

1. There must be method overriding.


2. Subclass object must be assigned to a super class object.

The rule followed is "when a subclass object is assigned to a super class


object, the super object will call subclass overridden method.

We know earlier, static polymorphism which is achieved through method


overloading.

Interface Polymorphism

The same Bird program, in the earlier example, can be modified to suit
with interfaces. Now declare Bird as an interface. We know that reference
variables can be created with abstract classes and interfaces (but not
objects). Read the following program.

interface Bird
{
public abstract void eat(); // I
}
class Peacock implements Bird
{
public void eat() // II
{
System.out.println("Peacock eats grains");
}
}
class Vulture implements Bird
{
public void eat() // III
{
System.out.println("Vulture eats flesh");
}
}
class Crane implements Bird
{
public void eat() // IV
{
System.out.println("Crane eats fish");
}
}
public class DynamicPolyDemo
{
public static void main(String args[])
{
Bird b1; // reference variable of interface
Peacock p1 = new Peacock(); b1 = p1; b1.eat(); // calls II
Vulture v1 = new Vulture(); b1 = v1; b1.eat(); // calls III
Crane c1 = new Crane(); b1 = c1; b1.eat(); // calls IV
}
}
Here Bird is interface and not a concrete class (in the earlier program
it is concrete class).

Bird b1;
b1 is reference variable and not object.

b1 = p1;
b1.eat();
Subclass Peacock object is assigned to the reference variable b1 of
interface Bird. Here, super class is an interface and eat() is an
abstract method. When a subclass object is assigned to a super class
reference variable, the reference variable calls subclass overridden
method. Now, b1 calls subclass Peacock's eat() method.

The addresses of subclass objects, p1, v1 and c1, in the super class
reference variable b1 are replaced in every statement dynamically at
runtime. Every time when b1.eat() method is called, it prints different
outputs. This is known as polymorphism. Because polymorphism is achieved
at runtime dynamically, this is known as dynamic polymorphism. Here,
dynamic polymorphism is achieved through interfaces.

Java static vs non-static::

Java novices are not much aware of static to non-static calling. Let us
find the rules through a program.
In the following code, show() method is non-static and display() is
static. The question is "Can we call a non-static method from static
method?". Everyone says simply "no" because it requires an object to
call. Anyhow, let us observe the compiler message.

public class Demo


{
public void show( )
{
System.out.println("Hello");
}
public static void display( )
{
show( );
}
}

This is an usual compiler message every Java professional come acrosses.

Now let us see the combinations.

show() display() Result


non-static non-static works
static non-static works
static static works
non-static static does not work
The above table can easily be remembered. Only one combination does not
work – calling non-static member from static member (it requires object).

You might also like