0% found this document useful (0 votes)
4 views61 pages

Java Unit 3

Uploaded by

ryanrenon1385
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views61 pages

Java Unit 3

Uploaded by

ryanrenon1385
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 61

Inheritance in Java

Java Inheritance is a fundamental concept in OOP(Object-Oriented


Programming). It is the mechanism in Java by which one class is allowed to
inherit the features(fields and methods) of another class. In Java, Inheritance
means creating new classes based on existing ones. A class that inherits from
another class can reuse the methods and fields of that class.
Example: In the following example, Animal is the base class and Dog, Cat and
Cow are derived classes that extend the Animal class.
// Parent class
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
// Child class
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
}
// Child class
class Cat extends Animal {
void sound() {
System.out.println("Cat meows");
}
}
// Child class
class Cow extends Animal {
void sound() {
System.out.println("Cow moos");
}
}
// Main class
public class Main {
public static void main(String[] args) {
Animal a;
a = new Dog();
a.sound();
a = new Cat();
a.sound();
a = new Cow();
a.sound();
}
}
Output
Dog barks
Cat meows
Cow moos
Explanation:
 Animal is the base class.
 Dog, Cat and Cow are derived classes that extend Animal class and
provide specific implementations of the sound() method.
 The Main class is the driver class that creates objects and demonstrates
runtime polymorphism using method overriding.
Why Use Inheritance in Java?
 Code Reusability: The code written in the Superclass is common to all
subclasses. Child classes can directly use the parent class code.
 Method Overriding: Method Overriding is achievable only through
Inheritance. It is one of the ways by which Java achieves Run Time
Polymorphism.
 Abstraction: The concept of abstraction where we do not have to
provide all details, is achieved through inheritance. Abstraction only
shows the functionality to the user.
Key Terminologies Used in Java Inheritance
 Class: Class is a set of objects that share common characteristics/
behavior and common properties/ attributes. Class is not a real-world
entity. It is just a template or blueprint or prototype from which objects
are created.
 Super Class/Parent Class: The class whose features are inherited is
known as a superclass(or a base class or a parent class).
 Sub Class/Child Class: The class that inherits the other class is known as
a subclass(or a derived class, extended class or child class). The subclass
can add its own fields and methods in addition to the superclass fields
and methods.
 Extends Keyword: This keyword is used to inherit properties from a
superclass.
How Inheritance Works in Java?
The extends keyword is used for inheritance in Java. It enables the
subclass to inherit the fields and methods of the superclass. When a class
extends another class, it means it inherits all the non-primitive members
(fields and methods) of the parent class and the subclass can also
override or add new functionality to them.
Note: The extends keyword establishes an "is-a" relationship between
the child class and the parent class. This allows a child class to have all
the behavior of the parent class.
Types of Inheritance in Java
Below are the different types of inheritance which are supported by Java.
 Single Inheritance
 Multilevel Inheritance
 Hierarchical Inheritance
 Multiple Inheritance
 Hybrid Inheritance

****************************************************************
1. Single Inheritance
In single inheritance, a sub-class is derived from only one super class. It inherits
the properties and behavior of a single-parent class. Sometimes, it is also
known as simple inheritance.
//Super class
class Vehicle {
Vehicle() {
System.out.println("This is a Vehicle");
}
}
// Subclass
class Car extends Vehicle {
Car() {
System.out.println("This Vehicle is Car");
}
}
public class Test {
public static void main(String[] args) {
// Creating object of subclass invokes base class constructor
Car obj = new Car();
}
}
Output
This is a Vehicle
This Vehicle is Car
***************************************************************
2. Multilevel Inheritance
In Multilevel Inheritance, a derived class will be inheriting a base class and as
well as the derived class also acts as the base class for other classes.

class Vehicle {
Vehicle() {
System.out.println("This is a Vehicle");
}
}
class FourWheeler extends Vehicle {
FourWheeler() {
System.out.println("4 Wheeler Vehicles");
}
}
class Car extends FourWheeler {
Car() {
System.out.println("This 4 Wheeler Vehicle is a Car");
}
}
public class Geeks {
public static void main(String[] args) {
Car obj = new Car(); // Triggers all constructors in order
}
}
Output
This is a Vehicle
4 Wheeler Vehicles
This 4 Wheeler Vehicle is a Car
****************************************************************
3. Hierarchical Inheritance
In hierarchical inheritance, more than one subclass is inherited from a single
base class. i.e. more than one derived class is created from a single base class.
For example, cars and buses both are vehicle

class Vehicle {
Vehicle() {
System.out.println("This is a Vehicle");
}
}
class Car extends Vehicle {
Car() {
System.out.println("This Vehicle is Car");
}
}
class Bus extends Vehicle {
Bus() {
System.out.println("This Vehicle is Bus");
}
}
public class Test {
public static void main(String[] args) {
Car obj1 = new Car();
Bus obj2 = new Bus();
}
}
Output
This is a Vehicle
This Vehicle is Car
This is a Vehicle
This Vehicle is Bus
****************************************************************
**********
4. Multiple Inheritance (Through Interfaces)
An Interface in Java programming language is defined as an abstract type used
to specify the behaviour of a class. An interface in Java is a blueprint of a
behaviour. A Java interface contains static constants and abstract methods.
Key Properties of Interface:
The interface in Java is a mechanism to achieve abstraction.
By default, variables in an interface are public, static and final.
It is used to achieve abstraction and multiple inheritance in Java.
It supports loose coupling (classes depend on behavior, not implementation).
In other words, interfaces primarily define methods that other classes must
implement.
An interface in Java defines a set of behaviours that a class can implement,
usually representing a CAN-DO relationship, but not always in every scenario.
Example: This example demonstrates how an interface in Java defines
constants and abstract methods, which are implemented by a class.
import java.io.*;

// Interface Declared
interface testInterface {

// public, static and final


final int a = 10;

// public and abstract


void display();
}

// Class implementing interface


class TestClass implements testInterface {

// Implementing the capabilities of Interface


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

class Main
{
public static void main(String[] args)
{
TestClass t = new TestClass();
t.display();
System.out.println(t.a);
}
}
Output
Hello
10

Note: In Java, the abstract keyword applies only to classes and methods,
indicating that they cannot be instantiated directly and must be implemented.
When we decide on a type of entity by its behaviour and not via attribute we
should define it as an interface.
Syntax:
interface InterfaceName {
// Constant fields (public static final by default)
int CONSTANT = 10;
// Abstract method (public abstract by default)
void methodName();
// Default method (JDK 8+)
default void defaultMethod() {
System.out.println("Default implementation");
}
// Static method (JDK 8+)
static void staticMethod() {
System.out.println("Static method in interface");
}
// Private method (JDK 9+)
private void privateMethod() {
System.out.println("Private helper method");
}
}
Note:
 Private methods can only be called inside default or static methods in
the interface, not by implementing classes
 Static methods are also accessible via the3interface itself not through
objects
To declare an interface, use the interface keyword. It is used to provide total
abstraction. That means all the methods in an interface are declared with an
empty body and are public and all fields are public, static and final by default. A
class that implements an interface must implement all the methods declared in
the interface. To implement the interface, use the implements keyword.

Relationship Between Class and Interface


A class can extend another class and similarly, an interface can extend another
interface. However, only a class can implement an interface and the reverse (an
interface implementing a class) is not allowed.

When to Use Class and Interface?


Use a Class when:
 Use a class when you need to represent a real-world entity with
attributes (fields) and behaviors (methods).
 Use a class when you need to create objects that hold state and perform
actions
 Classes are used for defining templates for objects with specific
functionality and properties.
Use a Interface when:
 Use an interface when you need to define a contract for behavior that
multiple classes can implement.
 Interface is ideal for achieving abstraction and multiple inheritance.
Implementation: To implement an interface, we use the keyword implements
Let’s consider the example of Vehicles like bicycles, cars and bikes share
common functionalities, which can be defined in an interface, allowing each
class (e.g., Bicycle, Car, Bike) to implement them in its own way. This approach
ensures code reusability, scalability and consistency across different vehicle
types.
Example: This example demonstrates how an interface can be used to define
common behavior for different classes (Bicycle and Bike) that implement the
interface.
import java.io.*;

interface Vehicle {

// Abstract methods defined


void changeGear(int a);
void speedUp(int a);
void applyBrakes(int a);
}

// Class implementing vehicle interface


class Bicycle implements Vehicle{
int speed;
int gear;

// Change gear
@Override
public void changeGear(int newGear){
gear = newGear;
}

// Increase speed
@Override
public void speedUp(int increment){
speed = speed + increment;
}

// Decrease speed
@Override
public void applyBrakes(int decrement){
speed = speed - decrement;
}

public void printStates() {


System.out.println("speed: " + speed
+ " gear: " + gear);
}
}

// Class implementing vehicle interface


class Bike implements Vehicle {

int speed;
int gear;

// Change gear
@Override
public void changeGear(int newGear){
gear = newGear;
}

// Increase speed
@Override
public void speedUp(int increment){
speed = speed + increment;
}

// Decrease speed
@Override
public void applyBrakes(int decrement){
speed = speed - decrement;
}
public void printStates() {
System.out.println("speed: " + speed
+ " gear: " + gear);
}

class Main
{
public static void main (String[] args)
{

// Instance of Bicycle(Object)
Bicycle bicycle = new Bicycle();

bicycle.changeGear(2);
bicycle.speedUp(3);
bicycle.applyBrakes(1);

System.out.print("Bicycle present state : ");


bicycle.printStates();

// Instance of Bike (Object)


Bike bike = new Bike();
bike.changeGear(1);
bike.speedUp(4);
bike.applyBrakes(3);

System.out.print("Bike present state : ");


bike.printStates();
}
}
Output
Bicycle present state : speed: 2 gear: 2
Bike present state : speed: 1 gear: 1
Multiple Inheritance in Java Using Interface
Java does not support multiple inheritance with classes to avoid ambiguity, but
it supports multiple inheritance using interfaces.
In Multiple inheritances, one class can have more than one superclass and
inherit features from all parent classes.
Note: that Java does not support multiple inheritances with classes. In Java, we
can achieve multiple inheritances only through Interfaces.

Example: This example demonstrates how a class can implement multiple


interfaces (Add and Sub) to provide functionality for both addition and
subtraction operations.
import java.io.*;
// Add interface
interface Add{
int add(int a,int b);
}
// Sub interface
interface Sub{
int sub(int a,int b);
}
// Calculator class implementing Add and Sub
class Cal implements Add , Sub
{
// Method to add two numbers
public int add(int a,int b){
return a+b;
}
// Method to sub two numbers
public int sub(int a,int b){
return a-b;
}
}
class Main{
// Main Method
public static void main (String[] args)
{
// instance of Cal class
Cal x = new Cal();
System.out.println("Addition : " + x.add(2,1));
System.out.println("Substraction : " + x.sub(2,1));

}
}
Output
Addition : 3
Substraction : 1
Example:

interface LandVehicle {
default void landInfo() {
System.out.println("This is a LandVehicle");
}
}
interface WaterVehicle {
default void waterInfo() {
System.out.println("This is a WaterVehicle");
}
}
// Subclass implementing both interfaces
class AmphibiousVehicle implements LandVehicle, WaterVehicle {
AmphibiousVehicle() {
System.out.println("This is an AmphibiousVehicle");
}
}
public class Test {
public static void main(String[] args) {
AmphibiousVehicle obj = new AmphibiousVehicle();
obj.waterInfo();
obj.landInfo();
}
}
Output
This is an AmphibiousVehicle
This is a WaterVehicle
This is a LandVehicle

5. Hybrid Inheritance
It is a mix of two or more of the above types of inheritance. In Java, we can
achieve hybrid inheritance only through Interfaces if we want to involve
multiple inheritance to implement Hybrid inheritance.
Explanation:
 class Car extends Vehicle->Single Inheritance
 class Bus extends Vehicle and class Bus extends Fare->Hybrid Inheritance
(since Bus inherits from two sources, forming a combination of single +
multiple inheritance).
Advantages of Inheritance in Java
 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.
 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.
 Class Hierarchy: Inheritance allows for the creation of a class hierarchy,
which can be used to model real-world objects and their relationships.
 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
 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.
 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.
Important Read it : The point Constructor is missing in 2nd chapter so I just put
here the notes about constructors.Is to be covered as follows:
Java Constructors
In Java, constructors play an important role in object creation. A constructor is
a special block of code that is called when an object is created. Its main job is
to initialize the object, to set up its internal state, or to assign default values to
its attributes. This process happens automatically when we use the "new"
keyword to create an object.
Characteristics of Constructors:
 Same Name as the Class: A constructor has the same name as the class
in which it is defined.
 No Return Type: Constructors do not have any return type, not even
void. The main purpose of a constructor is to initialize the object, not to
return a value.
 Automatically Called on Object Creation: When an object of a class is
created, the constructor is called automatically to initialize the object’s
attributes.
 Used to Set Initial Values for Object Attributes: Constructors are
primarily used to set the initial state or values of an object’s attributes
when it is created.
Now, let us look at a simple example to understand how a constructor works in
Java.
Example: This program demonstrates how a constructor is automatically
called when an object is created in Java.
// Java Program to demonstrate
// Constructor usage
import java.io.*;
// Driver Class
class Drive {
// Constructor
Drive()
{
super();
System.out.println("Constructor Called");
}
// main function
public static void main(String[] args)
{
Drive d1 = new Drive();
}
}

Output
Constructor Called
Note: It is not necessary to write a constructor for a class. It is because the Java
compiler creates a default constructor (constructor with no arguments) if your
class doesn't have any.
Why Do We Need Constructors in Java
Constructors play a very important role, it ensures that an object is properly
initialized before use.
What happens when we don't use constructors:
Without constructors:
 Objects might have undefined or default values.
 Extra initialization methods would be required.
 Risk of improper object state
Think of a Box. If we talk about a box class then it will have some class variables
(say length, breadth, and height). But when it comes to creating its object (i.e
Box will now exist in the computer's memory), then can a box be there with no
value defined for its dimensions? The answer is No.
So, constructors are used to assign values to the class variables at the time of
object creation, either explicitly done by the programmer or by Java itself
(default constructor).
When Java Constructor is Called?
Each time an object is created using a new() keyword, at least one constructor
(it could be the default constructor) is invoked to assign initial values to
the data members of the same class. Rules for writing constructors are as
follows:
 The constructor of a class must have the same name as the class name in
which it resides.
 A constructor in Java can not be abstract, final, static, or Synchronized.
 Access modifiers can be used in constructor declaration to control its
access i.e which other class can call the constructor.
So, we have learned constructors are used to initialize the object's state.
Like methods , a constructor also contains a collection of statements (i.e.
instructions) that are executed at the time of object creation.
Types of Constructors in Java
Now is the correct time to discuss the types of the constructor, so primarily
there are three types of constructors in Java are mentioned below:
 Default Constructor
 Parameterized Constructor
 Copy Constructor
1. Default Constructor in Java
A constructor that has no parameters is known as default constructor. A
default constructor is invisible. And if we write a constructor with no
arguments, the compiler does not create a default constructor. Once you
define a constructor (with or without parameters), the compiler no longer
provides the default constructor. Defining a parameterized constructor does
not automatically create a no-argument constructor, we must explicitly define
if needed. The default constructor can be implicit or explicit.
 Implicit Default Constructor: If no constructor is defined in a class, the
Java compiler automatically provides a default constructor. This
constructor doesn’t take any parameters and initializes the object with
default values, such as 0 for numbers, null for objects.
 Explicit Default Constructor: If we define a constructor that takes no
parameters, it's called an explicit default constructor. This constructor
replaces the one the compiler would normally create
automatically. Once you define any constructor (with or without
parameters), the compiler no longer provides the default constructor for
you.
Example: This program demonstrates the use of a default constructor, which is
automatically called when an object is created.
// Java Program to demonstrate
// Default Constructor
import java.io.*;

// Driver class
class Stud{
// Default Constructor
Stud() {
System.out.println("Default constructor");
}
// Driver function
public static void main(String[] args)
{
Stud hello = new Stud();
}
}
Output
Default constructor
Note: Default constructor provides the default values to the object like 0, null,
false etc. depending on the type.

2. Parameterized Constructor in Java


A constructor that has parameters is known as parameterized constructor. If
we want to initialize fields of the class with our own values, then use a
parameterized constructor.
Example: This program demonstrates the use of a parameterized constructor
to initialize an object's attributes with specific values.
// Java Program for Parameterized Constructor
import java.io.*;
class Emp {
// data members of the class
String name;
int id;
Emp(String name, int id) {
this.name = name;
this.id = id;
}
}
class Main
{
public static void main(String[] args)
{
// This would invoke the parameterized constructor
Emp e1 = new Emp ("Shweta", 68);
System.out.println("EmpName: " + e1.name+ " and EmpId: " + e1.id);
}
}
Output
EmpName: Shweta and EmpId: 68
Remember: Does constructor return any value?
There are no "return value" statements in the constructor, but the constructor
returns the current class instance. We can write 'return' inside a constructor.

3. Copy Constructor in Java


Unlike other constructors copy constructor is passed with another object which
copies the data available from the passed object to the newly created object.
Note: Java does not provide a built-in copy constructor like C++. We can create
our own by writing a constructor that takes an object of the same class as a
parameter and copies its fields.
Example: This example, demonstrates how a copy constructor can be used to
create a new object by copying the values of another object's attributes.
// Java Program for Copy Constructor
import java.io.*;
class Emp {
// data members of the class
String name;
int id;
// Parameterized Constructor
Emp(String name, int id)
{
this.name = name;
this.id = id;
}

// Copy Constructor
Emp(Emp obj2)
{
this.name = obj2.name;
this.id = obj2.id;
}
}

class Main {
public static void main(String[] args)
{
// This would invoke the parameterized constructor
System.out.println("First Object");
Emp e1 = new Emp("Shweta", 68);
System.out.println("EmpName: " + e1.name
+ " and EmpId: " + e1.id);

System.out.println();
// This would invoke the copy constructor
Emp e2 = new Emp(e1);
System.out.println(
"Copy Constructor used Second Object");
System.out.println("EmpName: " + e2.name
+ " and EmpId: " + e2.id);
}
}
Output
First Object
EmpName: Shweta and EmpId: 68
Copy Constructor used Second Object
EmpName: Shweta and EmpId: 68

Constructor Overloading
This is a key concept in OOPs related to constructors is constructor overloading.
This allows us to create multiple constructors in the same class with different
parameter lists.
Example: This example, demonstrates constructor overloading, where multiple
constructors perform the same task (initializing an object) with different
types or numbers of arguments.
// Java Program to illustrate constructor overloading
// using same task (addition operation ) for different
// types of arguments
import java.io.*;
class Emp {
// constructor with one argument
Emp(String name)
{
System.out.println("Constructor with one "
+ "argument - String: " + name);
}
// constructor with two arguments
Emp(String name, int age)
{
System.out.println(
"Constructor with two arguments: "
+ " String and Integer: " + name + " " + age);
}
// Constructor with one argument but with different
// type than previous
Emp(long id)
{
System.out.println(
"Constructor with one argument: "
+ "Long: " + id);
}
}

class Main {
public static void main(String[] args)
{
// Creating the objects of the class named ‘Emp’
// by passing different arguments
// Invoke the constructor with one argument of
// type 'String'.
Emp e2 = new Emp("Shweta");
// Invoke the constructor with two arguments
Emp e3 = new Emp("Amiya", 28);

// Invoke the constructor with one argument of


// type 'Long'.
Emp e1 = new Emp(325614567);
}
}
Output
Constructor with one argument - String: Shweta
Constructor with two arguments: String and Integer: Amiya 28
Constructor with one argument: Long: 325614567

Common Mistakes to Avoid


Some common mistakes to avoid when working with constructors in Java are
listed below:
 Forgetting super() in Child Classes: Always call the parent constructor
(super()) if the parent class has no default constructor, or it will lead to
compilation errors.
 Excessive Work in Constructors: Keep constructors simple and focused
on initialization, avoiding heavy logic that slows down object creation.
 Not Handling Null Checks: Always validate parameters to avoid
NullPointerException when constructing objects.
Polymorphism in Java
Polymorphism in Java is one of the core concepts in object-oriented
programming (OOP) that allows objects to behave differently based on their
specific class type. The word polymorphism means having many forms, and it
comes from the Greek words poly (many) and morph (forms), this means one
entity can take many forms. In Java, polymorphism allows the same method or
object to behave differently based on the context, specially on the project's
actual runtime class.
Key features of polymorphism:
 Multiple Behaviors: The same method can behave differently depending
on the object that calls this method.
 Method Overriding: A child class can redefine a method of its parent
class.
 Method Overloading: We can define multiple methods with the same
name but different parameters.
 Runtime Decision: At runtime, Java determines which method to call
depending on the object's actual class.
Real-Life Illustration of Polymorphism
Consider a person who plays different roles in life, like a father, a husband, and
an employee. Each of these roles defines different behaviors of the person
depending on the object calling it.
Example: Different Roles of a Person
// Base class Person
class Person {

// Method that displays the


// role of a person
void role() {
System.out.println("I am a person.");
}
}

// Derived class Father that


// overrides the role method
class Father extends Person {

// Overridden method to show


// the role of a father
@Override
void role() {
System.out.println("I am a father.");
}
}

public class Main {


public static void main(String[] args) {

// Creating a reference of type Person


// but initializing it with Father class object
Person p = new Father();

// Calling the role method. It calls the


// overridden version in Father class
p.role();
}
}
Output
I am a father.
Explanation: In the above example, the Person class has a method role() that
prints a general message. The Father class overrides role() to print a specific
message. The reference of type Person is used to point to an object of type
Father, demonstrating polymorphism at runtime. The overridden method in
Father is invoked when role() is called.
Why Use Polymorphism In Java?
Using polymorphism in Java has many benefits which are listed below:
 Code Reusability: Polymorphism allows the same method or class to be
used with different types of objects, which makes the code more
useable.
 Flexibility: Polymorphism enables object of different classes to be
treated as objects of a common superclass, which provides flexibility in
method execution and object interaction.
 Abstraction: It allows the use of abstract classes or interfaces, enabling
you to work with general types (like a superclass or interface) instead of
concrete types (like specific subclasses), thus simplifying the interaction
with objects.
 Dynamic Behavior: With polymorphism, Java can select the appropriate
method to call at runtime, giving the program dynamic behavior based
on the actual object type rather than the reference type, which
enhances flexibility.
Types of Polymorphism in Java
In Java Polymorphism is mainly divided into two types:
1. Compile-Time Polymorphism (Static)
2. Runtime Polymorphism (Dynamic)
1. Compile-Time Polymorphism
Compile-Time Polymorphism in Java is also known as static polymorphism and
also known as method overloading. This happens when multiple methods in
the same class have the same name but different parameters.
Note: But Java doesn't support the Operator Overloading.

Method Overloading
As we discussed above, Method overloading in Java means 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.
Example: Method overloading by changing the number of arguments
// Method overloading By using
// Different Types of Arguments
// Class 1
// Helper class
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;
}
}
// Class 2
// Main class
class Main
{
// Main driver method
public static void main(String[] args) {
// Calling method by passing
// input as in arguments
System.out.println(Helper.Multiply(2, 4));
System.out.println(Helper.Multiply(5.5, 6.3));
}
}
Output
8
34.65
Explanation:
The Multiply method is overloaded with different parameter types. The
compiler picks the correct method during compile time based on the
arguments.
2. Runtime Polymorphism
Runtime Polymorphism in Java 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.
Method Overriding
Method overriding in Java means when a subclass provides a specific
implementation of a method that is already defined in its superclass. The
method in the subclass must have the same name, return type, and parameters
as the method in the superclass. Method overriding allows a subclass to modify
or extend the behavior of an existing method in the parent class. This enables
dynamic method dispatch, where the method that gets executed is determined
at runtime based on the object's actual type.
Example: This program demonstrates method overriding in Java, where the
Print() method is redefined in the subclasses (subclass1 and subclass2) to
provide specific implementations.
// Java Program for Method Overriding

// Class 1
// Helper class
class Parent {

// Method of parent class


void Print() {
System.out.println("parent class");
}
}

// Class 2
// Helper class
class subclass1 extends Parent {

// Method
void Print() {
System.out.println("subclass1");
}
}

// Class 3
// Helper class
class subclass2 extends Parent {
// Method
void Print() {
System.out.println("subclass2");
}
}

// Class 4
// Main class
class Geeks {

// Main driver method


public static void main(String[] args) {

// Creating object of class 1


Parent a;

// Now we will be calling print methods


// inside main() method
a = new subclass1();
a.Print();

a = new subclass2();
a.Print();
}
}
Output
subclass1
subclass2
Explanation: In the above example, when an object of a child class is created,
then the method inside the child class is called. This is because the method in
the parent class is overridden by the child class. This method has more priority
than the parent method inside the child class. So, the body inside the child
class is executed.
Advantages of Polymorphism
 Encourages code reuse.
 Simplifies maintenance.
 Enables dynamic method dispatch.
 Helps in writing generic code that works with many types.
Disadvantages of Polymorphism
 It can make more difficult to understand the behavior of an object.
 This may cause performance issues, as polymorphic behavior may
require additional computations at runtime.

The following table demonstrates the difference between runtime


polymorphism and compile-time polymorphism:

Compile Time Polymorphism Run time Polymorphism


In Compile time Polymorphism, the In Run time Polymorphism, the call is
call is resolved by the compiler. not resolved by the compiler.
It is also known as Static binding,
It is also known as Dynamic binding,
Early binding and overloading as
Late binding and overriding as well.
well.
It is achieved by virtual functions
It is achieved by method overloading
and pointers.
Compile time polymorphism is less Run time polymorphism is more
flexible as all things execute at flexible as all things execute at run
compile time. time.
Inheritance is not involved. Inheritance is involved.
Java final, finally and finalize
In Java, the keywords "final", "finally" and "finalize" have distinct roles. final
enforces immutability and prevents changes to variables, methods or classes.
finally ensures a block of code runs after a try-catch, regardless of exceptions.
finalize is a method used for cleanup before an object is garbage collected.
Now, we will discuss each keyword in detail one by one.
final Keyword
The final keyword in Java is used with variables, methods and also with classes
to restrict modification.
Syntax
// Constant value
final int b = 100;
Example: The below Java program demonstrates the value of the variable
cannot be changed once initialized.
class A {
public static void main(String[] args)
{
// Non final variable
int a = 5;

// final variable
final int b = 6;

// modifying the non final variable


a++;

// modifying the final variable Immediately gives Compile Time error


b++;
}
}
Output:

Note: If we declare any variable as final, we can't modify its value. Attempting
to do so results in a compile-time error.
In the above example, we used the final keyword to declare a variable that
cannot be modified after its initialization. Similarly, the final keyword can also
be applied to methods and classes in Java to impose certain restrictions.
finally Keyword
The finally keyword in Java is used to create a block of code that always
executes after the try block, regardless of whether an exception occurs or not.
Syntax
try {
// Code that might throw an exception
} catch (ExceptionType e) {
// Code to handle the exception
} finally {
// Code that will always execute
}
Example: The below Java program demonstrates the working of finally block in
exception handling.
public class Geeks {
public static void main(String[] args)
{
try {
System.out.println("Inside try block");
int result
= 10 / 0; // This will cause an exception
}
catch (ArithmeticException e) {
System.out.println("Exception caught: "
+ e.getMessage());
}
finally {
System.out.println(
"finally block always execute");
}
}
}
Output:

Explanation: The try block attempts a division by zero, causing an


ArithmeticException. The finally block executes, whether an exception occurs,
ensuring cleanup or mandatory code execution.
finalize() Method
The finalize() method is called by the Garbage Collector just before an object is
removed from memory. It allows us to perform clean up activity. Once the
finalize() method completes, Garbage Collector destroys that object.finalize
method is present in the Object class.
Syntax:
protected void finalize() throws Throwable{}
Note: finalize() is deprecated in Java 9 and should not be used in modern
applications. It’s better to use try-with-resources or other cleanup mechanisms
instead of relying on finalize().
Example: The below Java program demonstrates the working of finalize()
method in context of garbage collection.
import java.util.*;

public class Geeks {


public static void main(String[] args)
{
Geeks g = new Geeks();

System.out.println("Hashcode is: " + g.hashCode());

// Making the object eligible for garbage collection


g = null;

System.gc();

// Adding a short delay to allow GC to act


try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End of the garbage collection");
}

// Defining the finalize method


@Override protected void finalize()
{
System.out.println("Called the finalize() method");
}
}
Output:

Output
Explanation: In the above example, an object "g" is created and its hash code is
printed. The object is made eligible for garbage collection by setting it to null
and invoking System.gc().
final vs finally vs finalize
The table below illustrates the differences between "final", "finally" and
"finalize."
final finally finalize
The finally block in
final keyword applies
exception handling is finalize is a method of
restrictions on variable,
used with try-catch object class
method and classes.
block.
The code that is written
finalize method in Java
Prevent modification of inside finally block is
is used to perform
variables, inheritance of always executed after
cleanup operations
classes or overriding of the try-catch block
before an object is
methods. whether an exception
garbage collected.
occurs or not .
Objects, specifically by
Variables, methods and Only within a try-catch
overriding the method
classes. block.
in a class
Called by the garbage
collector when an
Executes when Always executed after
object is about to be
declared. try-catch block.
deleted, but it's not
guaranteed to run.

Controlling the Visibility of Class and Interface in Java


Maintenance is one of the important aspects of software development, and
experience has shown that software that maintains its component's visibility
low is more maintainable than one that exposes its component more. You're
not going to know it upfront, but when redesigning the application, you're
going to miss it terribly.
You end up patching and repeating the same errors, as maintaining backward
compatibility is a must-have requirement for many applications. You will not do
much because the class and interfaces are tightly integrated with a lot of other
applications. Java has always prioritized encapsulation, providing access
modifiers of support from the very beginning. By making them public, package-
private or private provides ways to monitor the visibility of some type, such as
class or interface.
Below are some rules to control the visibility:
1. A top-level class (a class whose name is the same as the Java source file
that contains it) can also be either a public or a private package (without
an access modifier) and cannot be a private one. Private, public, or
package-private may only be a nesting class.
2. A public class is accessible to all and most visible, try to keep public only
key interfaces, never let the implementation go public until you believe
it's complete and mature.
3. The private type, on the other hand, is less visible, and in Java, only the
nested class or interface can be private. You have full control over this
class to change its actions with experiences, new technology, tools, and
redesign, as it's least visible.
4. Package-private visibility is a clever midway and is also default visibility,
there's no such keyword as package-private, instead if you don't have
any access modifier as Java thinks it's package-private, and then make it
only visible on the same package.
5. If the classes and interfaces are only shared within the same package
between other classes, make them package-private. As the client is
unable to reach them, they are therefore reasonably safe to change.
How to control Visibility of Class or Interface in Java?
In addition to decreasing class or interface visibility using the access modifier,
based on your runtime environment, there are many other ways to do so. At
the component level, such as Websphere, Weblogic, or JBoss in Application
Server, an interface class may be proxied or wrapped to reduce external
visibility.
No matter what you do, there will still be certain types that need to be exposed
to the outside world, but you can always handle them with proxy or wrapper.
Although client programs will load proxied implementation classes, an
immutable proxy or wrapper would often be obtained.
For example, the Java Servlet API (javax.servlet) getServletContext() returns an
implementation of javax.servlet.ServletContext, which is typically an
immutable proxy to satisfy the ServletContext framework promises. It is most
possible that a separate version of the javax.servlet.ServletContext
specification operates on the application server.
It is possible to use a similar pattern in the implementation of other externally
accessible interfaces, e.g. Javax.ejb.EJBContext, Javax.ejb.TimerService,
ServletRequest, ServletResponse, etc. To support these global interfaces,
various application servers can use various applications.
JDK Example of Controlling Visibility of Java Class
EnumSet class is another fascinating example of managing visibility. In order to
prevent instantiation, the Java designer made the abstract class and provided
factory methods as the only way to create an instance of that class, e.g.
Methods from EnumSet.of() or EnumSet.noneOf().
Internally, in the form of RegularEnumSet and JumboEnumSet, they have two
separate implementations, which are automatically selected based on the size
of the main universe by static factory methods.
For instance, if the number of values in Enum is less than 64, then
RegularEnumSet is used, otherwise, the JumboEnumSet instance is returned.
The beauty of this design is that package-private means that consumers have
no idea about any of these implementations.

Modifier Description
Default declarations are visible only within the package (package private)
Private declarations are visible within the class only
Protected declarations are visible within the package or all subclasses
Public declarations are visible everywhere

// Java program for showcasing the behaviour


// of Private Access Modifier

class Data {

// private variable
private String name;
}
public class Main {
public static void main(String[] main){

// create an object of Data


Data d = new Data();

// access private variable and field from another class


d.name = "Kapil";
}
}
Output:
Main.java:18: error: name has private access in Data
d.name = "Programiz";
^
In the above example, we have declared a private variable named name and a
private method named display(). When we run the program, we will get the
above error:
Protected Access Modifier
// Java program for showcasing the behaviour
// of Protected Access Modifier

class Animal {

// protected method
protected void display() {
System.out.println("I am an animal");
}
}

class Dog extends Animal {

public static void main(String[] args) {

// create an object of Dog class


Dog dog = new Dog();
// access protected method
dog.display();
}
}
Output
I am an animal
// Java program for showcasing the behaviour
// of Public Access Modifier

// Animal.java file
// public class

class Animal {

// public variable
public int legCount;

// public method
public void display() {
System.out.println("I am an animal.");
System.out.println("I have " + legCount + " legs.");
}
}

// Main.java
public class Main {
public static void main( String[] args ) {
// accessing the public class
Animal animal = new Animal();

// accessing the public variable


animal.legCount = 4;
// accessing the public method
animal.display();
}
}
Output
I am an animal.
I have 4 legs.

Java Packages
Packages in Java are a mechanism that encapsulates a group of classes, sub-
packages and interfaces. Packages are used for:
 Prevent naming conflicts by allowing classes with the same name to exist
in different packages, like college.staff.cse.Employee and
college.staff.ee.Employee.
 Make it easier to organize, locate and use classes, interfaces and other
components.
 Provide controlled access for Protected members that are accessible
within the same package and by subclasses. Default members (no access
specifier) are accessible only within the same package.
By grouping related classes into packages, Java promotes data encapsulation,
making code reusable and easier to manage. Simply import the desired class
from a package to use it in your program.
Creating Custom Packages
Step 1: Create a directory in which we create our packages and Java files.
mkdir PROGRAMMING
Step 2: Now, change the directory and create another folder inside the main
folder
cd PROGRAMMING
mkdir JavaProgramming
cd JavaProgramming
mkdir arrays
Step 3: Now create an empty text file and write the below Java code and don't
forget to save it with the same name as the class with .java extension
(TwoPointers.java)
TwoPointers Class.

package JavaProgramming.arrays;

// Main class present inside the package


public class TwoPointers {

public static void main(String[] args) {


System.out.println("Inside the package");
}
}
Note: Do not forget to add the package name inside the program file.
Step 4: Now run the program with the define folder path
javac src\JavaProgramming\arrays\TwoPointers.java
java src\JavaProgramming\arrays\TwoPointers.java
Output:
Runing program with Folder path
Folder Structure:
This is the visual representation of a custom package in Java in the below
image. First, we create a folder named Progamming and inside it we create a
package Javaprogramming and then create another subpackage, which is
called arrays. Then, we create a Java class file inside it, which is shown in the
image below:

Folder Structure
Working of Java Packages
Directory Structure: Package names and directory structures are closely
related. For example, if a package name is college.staff.cse, then three
directories are, college, staff and cse, where cse is inside staff and staff is inside
the college.
Naming Conventions: Package names are written in reverse order of domain
names, e.g., org.geeksforgeeks.practice. In a college, the convention might be:
 college.tech.cse
 college.tech.ee
 college.art.history
Example:
import java.util.*;
Here, util is a sub-package created inside the java package.
Accessing Classes Inside a Package
In Java, we can import classes from a package using either of the
following methods:
1. Import a specific class:
import java.util.Vector;
This imports only the Vector class from the java.util package.
2. Import all classes from a package:
import java.util.*;
This imports all classes and interfaces from the java.util package but does not
include sub-packages.
Example: Import the Vector class
import java.util.Vector;

public class Geeks {

public Geeks() {

// java.util.Vector is imported, We are able to access it directly in our code.


Vector v = new Vector();
java.util.ArrayList l = new java.util.ArrayList();
l.add(3);
l.add(5);
l.add(7);

System.out.println(l);
}

public static void main(String[] args) {

new Geeks();
}
}
Output
[3, 5, 7]
Note:
 Using import package.*; imports all classes in a package, but not classes
from its sub-packages.
 When two packages have classes with the same name (e.g.,
java.util.Date and my.package.Date), use the fully qualified name to
avoid conflicts:
import java.util.Date;
import my.package.Date;
Types of Java Packages
 Built-in Packages
 User-defined Packages
1. Built-in Packages
These packages consist of a large number of classes which are a part of
Java API.Some of the commonly used built-in packages are:
 java.lang: Contains language support classes(e.g classes which defines
primitive data types, math operations). This package is automatically
imported.
 java.io: Contains classes for supporting input / output operations.
 java.util: Contains utility classes which implement data structures like
Linked List, Dictionary and support ; for Date / Time operations.
 java.applet: Contains classes for creating Applets.
 java.awt: Contain classes for implementing the components for graphical
user interfaces (like button , ;menus etc). 6)
 java.net: Contain classes for supporting networking operations.
2. User-defined Packages
These are the packages that are defined by the user.
1. Create the Package:
First we create a directory myPackage (name should be same as the name of
the package). Then create the MyClass inside the directory with the first
statement being the package names.
Example:
package myPackage;

public class MyClass


{
public void getNames(String s)
{
System.out.println(s);
}
}

2. Use the Class in Program:


Now we will use the MyClass class in our program.
import myPackage.MyClass;

public class Main {


public static void main(String args[]) {

// Initializing the String variable with a value


String s = "Hello";

// Creating an instance of class MyClass in the package.


MyClass o = new MyClass();

o.getNames(s);
}
}

Note: MyClass.java must be saved inside the myPackage directory since it is a


part of the package.
Static Import In Java
Static Import in Java is about simplifying access to static members and
separates it from the broader discussion of user-defined packages.
Static import is a feature introduced in Java programming language (versions 5
and above) that allows members (fields and methods) defined in a class as
public static to be used in Java code without specifying the class in which the
field is defined.
Example:
import static java.lang.System.*;

class Main {
public static void main(String args[]) {

// We don't need to use 'System.out' as imported using static.


out.println("Hello");
}
}

Output
Hello
Handling Name Conflicts
When two packages contain a class with the same name (e.g., java.util.Date
and java.sql.Date), specify the full package name to avoid conflicts.
import java.util.*;
import java.sql.*;
//And then use Date class, then we will get a compile-time error :
Date today ; //ERROR-- java.util.Date or java.sql.Date?
The compiler will not be able to figure out which Date class do we want. This
problem can be solved by using a specific import statement:
import java.util.Date;
import java.sql.*;
If we need both Date classes then, we need to use a full package name every
time we declare a new object of that class. For Example:
java.util.Date deadLine = new java.util.Date();
java.sql.Date today = new java.sql.Date();
Directory Structure and CLASSPATH
Package names correspond to a directory structure. For example, a class Circle
in package com.zzz.project1.subproject2 is stored as:

$BASE_DIR/com/zzz/project1/subproject2/Circle.class

 Here $BASE_DIR represents the base directory of the package.


 The "dot" in the package name corresponds to a sub-directory of the file
system.
 The base directory ($BASE_DIR) could be located anywhere in the file
system.
 Hence, the Java compiler and runtime must be informed about the
location of the $BASE_DIR so as to locate the classes.
 It is is accomplished by an environment variable called CLASSPATH.
 CLASSPATH is similar to another environment variable PATH, which is
used by the command shell to search for the executable programs.
Setting CLASSPATH
CLASSPATH can be set by any of the following ways:
 CLASSPATH can be set permanently in the environment the steps In
Windows is
Go to Control Panel -> System -> Advanced -> Environment Variables.
 Select "System Variables" to apply the CLASSPATH for all users on the
system.
 Select "User Variables" to apply it only for the currently logged-in user.
 Edit or Create CLASSPATH : If CLASSPATH already exists, select it and click
"Edit" or If it doesn't exist, click "New"
 Enter CLASSPATH Details: In the "Variable name" field, enter:
"CLASSPATH", In the "Variable value" field, enter the directories and JAR
files separated by semicolons.
 In the "Variable value" field, enter the directories and JAR files separated
by semicolons. Example:

.c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar
 The dot (.) represents the current working directory.
 To check the current setting of the CLASSPATH, issue the following
command:
> SET CLASSPATH
CLASSPATH can be set temporarily for that particular CMD shell session by
issuing the following command:
> SET CLASSPATH=.;c:\javaproject\classes;d:\tomcat\lib\servlet-api.jar
Instead of using the CLASSPATH environment variable, you can also use the
command-line option -classpath or -cp of the javac and java commands, for
example,

> java –classpath c:\javaproject\classes


com.abc.project1.subproject2.MyClass3

Illustration of user-defined packages: Creating our first package: File name –


ClassOne.java
package package_name;

public class ClassOne {


public void methodClassOne()
{
System.out.println("Hello there its ClassOne");
}
}
Creating our second package: File name – ClassTwo.java
package package_one;
public class ClassTwo {
public void methodClassTwo()
{
System.out.println("Hello there i am ClassTwo");
}
}
Making use of both the created packages: File name – Testing.java
import package_name.ClassOne;
import package_one.ClassTwo;

public class Testing {


public static void main(String[] args)
{
ClassTwo a = new ClassTwo();
ClassOne b = new ClassOne();
a.methodClassTwo();
b.methodClassOne();
}
}
Now having a look at the directory structure of both the packages and the
testing class file:
Access Modifiers in the Context of Packages
 Public: Members with the public modifier are accessible from anywhere,
regardless of whether the accessing class is in the same package or not.
 Protected: Members with the protected modifier are accessible within
the same package, In subclasses
 Default: Members with no modifier are accessible only within the same
package
 Private: Members with the private modifier are accessible only within
the same class. They cannot be accessed by classes in the same package,
subclasses, or different packages.

You might also like