BE Java Module-3
BE Java Module-3
// Parent class
class Parent {
public void printparent()
{
System.out.println("parent");
}
}
class Child extends Parent {
public void printchild() {
System.out.println("child");
}
}
class A {
public void print_A() { System.out.println("Class A"); }
}
class B extends A {
public void print_B() { System.out.println("Class B"); }
}
class C extends A {
public void print_C() { System.out.println("Class C"); }
}
class D extends A {
public void print_D() { System.out.println("Class D"); }
}
// Driver Class
public class Test {
public static void main(String[] args)
{
B obj_B = new B();
obj_B.print_A();
obj_B.print_B();
Multiple Inheritance: In Multiple inheritances, one class can have more than
one superclass and inherit features from all parent classes.
Please note that Java does not support multiple inheritances with classes.
In Java, we can achieve multiple inheritances only through Interfaces. In the
image below, Class C is derived from interfaces A and B.
interface One {
public void print_One();
}
interface Two {
public void print_Two();
}
interface Three extends One, Two {
public void print_One();
}
class Child implements Three {
@Override public void print_One()
{
System.out.println("One");
}
// Drived class
public class MultipleInheritance {
public static void main(String[] args)
{
Child c = new Child();
c.print_One();
c.print_Two();
c.print_One();
}
}
Advantages Of Inheritance in Java:
1. Code Reusability: Inheritance allows for code reuse and reduces the amount of code that
needs to be written. The subclass can reuse the properties and methods of the superclass,
reducing duplication of code.
2. Abstraction: Inheritance allows for the creation of abstract classes that define a common
interface for a group of related classes. This promotes abstraction and encapsulation, making
the code easier to maintain and extend.
3. Class Hierarchy: Inheritance allows for the creation of a class hierarchy, which can be used to
model real-world objects and their relationships.
4. Polymorphism: Inheritance allows for polymorphism, which is the ability of an object to take
on multiple forms. Subclasses can override the methods of the superclass, which allows them
to change their behavior in different ways.
Disadvantages of Inheritance in Java:
1. Complexity: Inheritance can make the code more complex and harder to understand. This is
especially true if the inheritance hierarchy is deep or if multiple inheritances is used.
2. Tight Coupling: Inheritance creates a tight coupling between the superclass and subclass,
making it difficult to make changes to the superclass without affecting the subclass.
Self-assessment program
Create a base class containing the data members roll number and name. Also create a
member function to read and display the data using the concept of single level
inheritance. Create a derived class that contains marks of two subjects and total marks
as the data members
Member access rules
Access modifiers help to restrict the scope of a class, constructor, variable,
method, or data member. It provides security, accessibility, etc to the user
depending upon the access modifier used with the element.
Types of Access Modifiers in Java
There are four types of access modifiers available in Java:
1. Default – No keyword required
2. Private
3. Protected
4. Public
Important Points:
• If other programmers use your class, try to use the most restrictive access
level that makes sense for a particular member. Use private unless you
have a good reason not to.
• Avoid public fields except for constants.
void display()
{
// print maxSpeed of base class (vehicle)
System.out.println("Maximum Speed: "+ super.maxSpeed);
}
}
// Driver Program
class SuperTest {
public static void main(String[] args)
{
Car small = new Car();
small.display();
}
}
// superclass Person
class Person {
Person()
{
System.out.println("Person class Constructor");
}
}
// subclass Student extending the Person class
class Student extends Person {
Student()
{
// invoke or call parent class constructor
super();
// Driver Program
class SuperConstructorTest {
public static void main(String[] args)
{
Student s = new Student();
}
}
Preventing inheritance
There are 2 ways to stop or prevent inheritance in Java programming. By using
final keyword with a class or by using a private constructor in a class.
Problem Statement: Let’s say we have a class A and we don’t want to allow
any other class to be derived from it. What are the possible solutions?
Using final keyword before a class declaration we can stop a class to be
inherited by other classes. For example,
public final class A
{
}
If we try to extend the class A which is final, compiler will flash an error i.e.
“The Type B cannot the subclass the final Class A”, if class B is trying to
extend final class A.
public class B extends A{//Error :The Type B cannot the subclass the Final
Class A
}
We need to put a static method that will create and return an object. Why Static
method? Because, from outside of a class, to call a normal method we need an
object of the class, but, as constructor is private, we cannot create an object,
hence, only solution is to have a static method that can be called using class
name.
So, as a solution to stop a class to be extended, we need to make a constructor
private and have one static method that will create an object of this class and
return it.
class A {
// Make constructor private to prevent object creation
//From outside of this class.
private A() {
}
//Static method to create and return an object.
//this method will be called from outside by using
//class name only.
public static A GetInstance() {
return new A();
}
}
Final classes and methods
final is a keyword in java used for restricting some functionalities. We can
declare variables, methods, and classes with the final keyword.
Using final with inheritance
During inheritance, we must declare methods with the final keyword for which
we are required to follow the same implementation throughout all the derived
classes. Note that it is not necessary to declare final methods in the initial stage
of inheritance(base class always). We can declare a final method in any subclass
for which we want that if any other class extends this subclass, then it must
follow the same implementation of the method as in that subclass.
The object class and its methods
Object class is present in java.lang package. Every class in Java is directly or
indirectly derived from the Object class. If a class does not extend any other
class then it is a direct child class of Object and if extends another class then it
is indirectly derived. Therefore the Object class methods are available to all
Java classes. Hence Object class acts as a root of the inheritance hierarchy in
any Java Program.
Polymorphism
The word polymorphism means having many forms. In simple words, we can
define Java Polymorphism as the ability of a message to be displayed in more
than one form.
Real-life Illustration of Polymorphism in Java: A person at the same time can
have different characteristics. Like a man at the same time is a father, a husband,
and an employee. So the same person possesses different behaviors in different
situations. This is called polymorphism.
Types of Java Polymorphism
In Java Polymorphism is mainly divided into two types:
• Compile-time Polymorphism
• Runtime Polymorphism
Compile-Time Polymorphism in Java
It is also known as static polymorphism. This type of polymorphism is achieved
by function overloading or operator overloading.
Note: But Java doesn’t support the Operator Overloading.
Method Overloading
When there are multiple functions with the same name but different parameters
then these functions are said to be overloaded. Functions can be overloaded by
changes in the number of arguments or/and a change in the type of arguments.
class Helper {
// Method with 2 integer parameters
static int Multiply(int a, int b)
{
// Returns product of integer numbers
return a * b;
}
// Method 2 With same name but with 2 double parameters
static double Multiply(double a, double b)
{
// Returns product of double numbers
return a * b;
}
}
Runtime Polymorphism in Java
It is also known as Dynamic Method Dispatch. It is a process in which a
function call to the overridden method is resolved at Runtime. This type of
polymorphism is achieved by Method Overriding. Method overriding, on the
other hand, occurs when a derived class has a definition for one of the member
functions of the base class. That base function is said to be overridden.
Dynamic binding
Static vs Dynamic Binding in Java
• private, final and static members (methods and variables) use static
binding while for virtual methods (In Java methods are virtual by default)
binding is done during run time based upon the run time object.
• The static binding uses Type information for binding while Dynamic
binding uses Objects to resolve to bind.
• Overloaded methods are resolved (deciding which method to be called
when there are multiple methods with the same name) using static
binding while overridden methods use dynamic binding, i.e, at run time.
Static Binding
The binding which can be resolved at compile time by the compiler is known as
static or early binding. The binding of all the static, private, and final methods is
done at compile-time.
// Java Program to Illustrate Static Binding
// Main class
class NewClass {
// print statement
System.out.println(
"print() in subclass is called");
}
}
Output
print() in superclass is called
print() in superclass is called
Output Explanation: As you can see, in both cases the print method of the
superclass is called. Let us discuss how this happens
• We have created one object of subclass and one object of the superclass
with the reference of the superclass.
• Since the print method of the superclass is static, the compiler knows that
it will not be overridden in subclasses and hence compiler knows during
compile time which print method to call and hence no ambiguity.
Dynamic Binding
In Dynamic binding compiler doesn’t decide the method to be called.
Overriding is a perfect example of dynamic binding. In overriding both parent
and child classes have the same method.
// Print statement
System.out.println("print in superclass is called");
}
}
// Print statement
System.out.println("print in subclass is called");
}
}
Output
print in superclass is called
print in subclass is called
Output Explanation:
• Methods are not static in this code.
• During compilation, the compiler has no idea as to which print has to be
called since the compiler goes only by referencing variable not by the
type of object, and therefore the binding would be delayed to runtime and
therefore the corresponding version of the print will be called based on
type on an object.
Method overriding
Overriding is a feature that allows a subclass or child class to provide a specific
implementation of a method that is already provided by one of its super-classes
or parent classes. When a method in a subclass has the same name, the same
parameters or signature, and the same return type(or sub-type) as a method in its
super-class, then the method in the subclass is said to override the method in the
super-class.
Method overriding is one of the ways by which Java achieves Run Time
Polymorphism. The version of a method that is executed will be determined by
the object that is used to invoke it. If an object of a parent class is used to
invoke the method, then the version in the parent class will be executed, but if
an object of the subclass is used to invoke the method, then the version in the
child class will be executed. In other words, it is the type of the object being
referred to (not the type of the reference variable) that determines which version
of an overridden method will be executed.
// Base Class
class Parent {
void show() { System.out.println("Parent's show()"); }
}
// Inherited class
class Child extends Parent {
// This method overrides show() of Parent
@Override void show()
{
System.out.println("Child's show()");
}
}
// Driver class
class Main {
public static void main(String[] args)
{
// If a Parent type reference refers to a Parent object, then Parent's
// show is called
Parent obj1 = new Parent();
obj1.show();
Java abstract class is a class that can not be initiated by itself, it needs to be
subclassed by another class to use its properties. An abstract class is declared
using the “abstract” keyword in its class definition.
In Java, the following some important observations about abstract classes are as
follows:
1. An instance of an abstract class can not be created.
2. Constructors are allowed.
3. We can have an abstract class without any abstract method.
4. There can be a final method in abstract class but any abstract method in
class(abstract class) can not be declared as final or in simpler terms final
method can not be abstract itself as it will yield an error: “Illegal
combination of modifiers: abstract and final”
5. We can define static methods in an abstract class
6. We can use the abstract keyword for declaring top-level classes (Outer
class) as well as inner classes as abstract
7. If a class contains at least one abstract method then compulsory should
declare a class as abstract
8. If the Child class is unable to provide implementation to all abstract
methods of the Parent class then we should declare that Child class as
abstract so that the next level Child class should provide implementation
to the remaining abstract method
// Abstract class
abstract class Sunstar {
abstract void printInfo();
}
System.out.println(name);
System.out.println(age);
System.out.println(salary);
}
}
// Base class
class Base {
public static void main(String args[])
{
Sunstar s = new Employee();
s.printInfo();
}
}
void Learn(){
System.out.println("Preparing Right Now!");
}
}
class Abstract {
public static void main(String[] args) {
Subject x=new IT();
x.syllabus();
x.Learn();
}
}
Object Class:
There is one special class, Object, defined by java. All other classes are
subclasses of Object.
Object is a superclass of all other classes. i.e reference variable of type Object
can refer to an object of any other class. Also, since arrays are implemented as
classes, a variable of type Object can also refer to any array.
Object defines the following methods, which means that they are available in
every object.
Method Purpose
object clone() Creates a new object that is the same as the object being
cloned.
boolean Determines whether one object is equal to another.
equals(Object object)
void finalize() Called before an unused object is recycled.
Class getClass() Obtains the class of an object at run time.
int hashCode() Returns the hash code associated with the invoking object.
void notify() Resumes execution of a thread waiting on the invoking object
void notifyAll() Resumes execution of all threads waiting on the invoking
object.
String toString() Returns a string that describes the object.
void wait() Waits on another thread of execution.
void wait(long
milliseconds)
void wait(long
milliseconds, int
nanaosecons)
The methods getClass(), notify(), notifyAll() and wait() are declared as final.
equals() method compares the contents of two objects. It returns true if the
objects are equivalent, and false otherwise.
toString() method returns a string that contains a description of the object on
which it is called. Also, this method is automatically called when an object is
output using println().
Interfaces: Interfaces, Default Interface Methods, Use Static Methods in an
interface, private interface methods
interface NewInterface {
// static method
static void hello()
{
System.out.println("Hello, New Static Method Here");
}
// Public and abstract method of Interface
void overrideMethod(String str);
}
// Implementation Class
public class InterfaceDemo implements NewInterface {
public static void main(String[] args)
{
InterfaceDemo interfaceDemo = new InterfaceDemo();
Output:
Hello, New Static Method Here
Hello, Override Method here
private interface methods
Java 9 onwards, you can include private methods in interfaces. Before Java 9 it
was not possible.
These private methods will improve code re-usability inside interfaces and will
provide choice to expose only our intended methods implementations to
users.These methods are only accessible within that interface only and cannot
be accessed or inherited from an interface to another interface or class.
Output
Answer by Abstract method = 6 // mul(2, 3) = 2*3 = 6
Answer by Private method = 4 // sub(6, 2) = 6-2 = 4
Answer by Private static method = 3 // div(6, 2) = 6/2 = 3
Answer by Default method = 8 // add(6, 2) = 6+2 = 8
Answer by Private static method = 1 // div(5, 3) = 5/3 = 1
Answer by Static method = 2 // mod(5, 3) = 5%3 = 2
Rules For using Private Methods in Interfaces
• Private interface method cannot be abstract and no private and
abstract modifiers together.
• Private method can be used only inside interface and other static
and non-static interface methods.
• Private non-static methods cannot be used inside private static
methods.
• We should use private modifier to define these methods and no
lesser accessibility than private modifier.