0% found this document useful (0 votes)
4 views

JAVA Ass1

Uploaded by

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

JAVA Ass1

Uploaded by

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

1.

OOP

Object-Oriented Programming (OOP) in Java is a programming paradigm


that uses "objects" to design and develop applications. It organizes
software around data, or objects, rather than functions and logic. OOP
makes it easier to structure complex programs by dividing them into
smaller, manageable parts. Java is known for its strong OOP principles.

Key Concepts of OOP in Java

Java supports the following four fundamental concepts of OOP:

1. Encapsulation: It is the mechanism of restricting access to the internal


state of an object and allowing access through methods. It combines data
(fields) and code (methods) into a single unit, the class, and hides the
internal state from direct outside access. This ensures better control over
the data and can prevent accidental or malicious modification of data.
Example:
class BankAccount {
private double balance;

public void deposit (double amount) {


if (amount > 0) {
balance += amount; }
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount; }
}
public double getBalance() {
return balance; }
}
public class Main {
public static void main(String[] args) {
BankAccount account = new BankAccount();
account.deposit(1000);
account.withdraw(500);
System.out.println("Balance: " + account.getBalance()) }
}
Here, the balance variable is private, so it cannot be accessed or modified
directly.
Methods (deposit, withdraw, getBalance) provide controlled access to the
balance.
2. Inheritance: Inheritance allows one class (called the child or subclass)
to inherit the properties (fields) and behaviors (methods) of another class
(called the parent or superclass). This promotes code reusability and
establishes a relationship between classes.
Key Terms:
1. Superclass: The class being inherited from (also called the parent
class).
2. Subclass: The class that inherits from the superclass (also called the
child class).
3. Extends Keyword: Used to indicate that one class is inheriting from
another.
Example:
class Animal {
void sound() {
System.out.println("This animal makes a sound"); }
}
class Dog extends Animal {
void sound() {
System.out.println("The dog barks"); }
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound(); // Outputs: The dog barks
}
}
Here, the Dog class inherits the sound () method from the Animal class
but overrides it to provide its specific behavior.

Types of Inheritance in Java:


1. Single Inheritance: A subclass inherits from one superclass.
2. Multilevel Inheritance: A class is derived from a class that is also
derived from another class.

3. Polymorphism: Polymorphism allows methods to perform different


tasks based on the object that is calling them, even though they share the
same name. Java supports two types of polymorphism:

1. Compile-time polymorphism (Method Overloading)


2. Runtime polymorphism (Method Overriding)
1. Method Overloading (Compile-time Polymorphism)
Method overloading allows multiple methods with the same name but
different parameter lists (either different types or different numbers of
parameters) within the same class.
Example:
class Calculator {
public int add(int a, int b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
public double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(10, 20)); // Outputs: 30
System.out.println(calc.add(10, 20, 30)); // Outputs: 60
System.out.println(calc.add(10.5, 20.5)); // Outputs: 31.0
}
}
In this example, the add method is overloaded with different types and
numbers of parameters.

2. Method Overriding (Runtime Polymorphism)


Method overriding allows a subclass to provide a specific implementation
of a method that is already defined in its superclass.
Example:
class Vehicle {
void start() {
System.out.println("The vehicle starts");
}
}
class Car extends Vehicle {
@Override
void start() {
System.out.println("The car starts");
}
}
public class Main {
public static void main(String[] args) {
Vehicle myVehicle = new Car();
myVehicle.start(); // Outputs: The car starts (polymorphic behavior)
}
}

In this example, the Car class overrides the start() method of the Vehicle
class.

4. Abstraction: Abstraction is the process of hiding implementation


details and showing only essential information. It allows you to focus on
what an object does rather than how it does it. In Java, abstraction can be
achieved through:
1. Abstract Classes: An abstract class cannot be instantiated and can
contain both abstract methods (without implementation) and concrete
methods (with implementation).
Example:
abstract class Animal {
abstract void sound(); // Abstract method (no implementation)

void sleep() {
System.out.println("This animal is sleeping");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("The cat meows");
}
}
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
cat.sound(); // Outputs: The cat meows
cat.sleep(); // Outputs: This animal is sleeping
}
}

Here, Animal is an abstract class that has an abstract method sound(). The
Cat class provides an implementation for this abstract method.
2. Interfaces: An interface in Java is a reference type, similar to a class,
but it can only contain abstract methods (before Java 8). From Java 8
onwards, interfaces can also have default and static methods with
implementations.
Example:
interface Animal {
void sound(); // Interface method (implicitly public and abstract)
}
class Dog implements Animal {
@Override
public void sound() {
System.out.println("The dog barks");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound(); // Outputs: The dog barks
}
}

In this example, the Dog class implements the Animal interface and
provides a concrete implementation for the sound() method.

Benefits of OOP in Java


1. Modularity: The source code for an object can be written and
maintained independently.
2. Reusability: Objects and classes can be reused across different
programs.
3. Extensibility: New features and functionality can be added to an
existing class via inheritance.
4. Maintenance: Easier to maintain and modify existing code without
affecting other parts of the program.

Conclusion
OOP in Java provides a flexible, modular, and reusable structure for
building complex and scalable applications. By using encapsulation,
inheritance, polymorphism, and abstraction, developers can write code
that is maintainable, extensible, and easier to understand.
2. JDK
The Java Development Kit (JDK) is a software development
environment used for developing Java applications and applets. It is the
core component of the Java platform and provides all the necessary tools,
libraries, and utilities required to develop, compile, debug, and run Java
applications. The JDK is essential for Java developers, as it contains
everything needed to write and execute Java programs.
Here's a comprehensive overview of the JDK:

 Components of the JDK


The JDK includes a wide array of tools, libraries, and utilities that help in
the development and deployment of Java applications. These components
are essential for different stages of application development, from writing
and compiling code to debugging and deploying Java programs.

1. Java Runtime Environment (JRE)


 The JRE is a crucial part of the JDK and is required to run Java
applications. It contains the Java Virtual Machine (JVM), core
libraries, and other files necessary to execute Java programs.
 The JRE is the runtime portion of Java software, meaning that it
runs the Java program, but it doesn’t include development tools
like compilers or debuggers.

2. Java Virtual Machine (JVM)


 The JVM is responsible for running Java bytecode. It is an abstract
machine that allows Java applications to be executed on any device
or operating system that has the JVM installed.
 The JVM takes the compiled bytecode (produced by the Java
compiler) and translates it into machine code that can be executed
by the specific operating system (Windows, macOS, Linux, etc.).

3. Java Compiler (javac)


 The Java compiler (javac) is one of the most critical tools in the
JDK. It compiles Java source code files (with the .java extension)
into Java bytecode files (with the .class extension).
 Bytecode is platform-independent code that can run on any
machine with a JVM. The compiler checks the code for syntax
errors and other issues before converting it into bytecode.

4. Development Tools
The JDK comes with several command-line tools for different stages of
Java application development. Here are some of the most widely used
ones:
 javac: The Java compiler, used to compile Java source code into
bytecode.
 java: The Java launcher, used to start the JVM and run Java
applications.
 javadoc: A documentation generator that extracts comments from
the Java source code and generates API documentation in HTML
format.
 jar: The Java Archive tool, used to package compiled Java classes
into a single file (typically .jar files) for easier distribution and
execution.
 jdb: A command-line debugger for Java, allowing developers to
step through code, set breakpoints, and inspect variables at runtime.
 javap: A Java class file disassembler that shows the bytecode and
other low-level details of compiled classes.
 jshell: A Read-Eval-Print-Loop (REPL) tool introduced in JDK 9,
allowing developers to test code snippets interactively without
creating a full class or method.
 jps, jstack, jmap, jstat: Performance monitoring and diagnostic
tools to help analyze and troubleshoot memory leaks, thread
deadlocks, and other performance issues.

5. Java Standard Library


The JDK includes a massive collection of pre-built libraries, which are
essentially classes and methods that help in performing a variety of tasks
like file input/output, networking, collections (data structures like lists,
sets, and maps), and multithreading.
Important libraries include:
 java.lang: Core classes (e.g., String, Math, Thread, System).
 java.util: Utility classes (e.g., collections framework, date/time
utilities).
 java.io: Input/output classes (e.g., file reading and writing, stream
handling).
 java.net: Networking classes (e.g., sockets, HTTP communication).
 java.nio: Non-blocking I/O for high-performance I/O operations.
 java.sql: Classes for working with databases using SQL.

 JDK Version History and Evolution


The JDK has evolved significantly since its initial release. Here's a look
at the important versions and their key features:
a. JDK 1.0 (1996)
1. The very first release of the JDK. It included basic tools for developing
Java applications, such as the compiler, interpreter, and debugger.
2. Supported applets, which were embedded into web browsers using
Java technology.
b. JDK 1.1 (1997)
1. Introduced inner classes, JavaBeans, reflection, JDBC (Java Database
Connectivity), and the concept of event handling via listeners, which
improved GUI programming.
c. JDK 5.0 (2004)
1. Introduced major language enhancements like Generics, Annotations,
Enums, and Varargs.
2. Enhanced the collections framework and provided a new
java.util.concurrent package for better multithreading support.
d. JDK 6 (2006)
1. Focused on performance improvements and included scripting
language support (JSR 223).
2. Introduced enhancements to Web Services and the Java Compiler API.
e. JDK 7 (2011)
1. Introduced features like try-with-resources, the diamond operator,
and NIO2 for better file handling.
f. JDK 8 (2014)
1. One of the most popular versions, it introduced Lambda Expressions
and the Stream API, allowing developers to write more functional-code.
2. Introduced the new java.time package for better handling of dates and
times, replacing the old java.util.Date and java.util.Calendar classes.
g. JDK 9 (2017)
1. Introduced the module system (Project Jigsaw) that allows better
modularization of applications, particularly for large systems.
2. Added jshell, the REPL tool for interactive Java programming.
h. JDK 11 (2018)
1. A Long-Term Support (LTS) release.
2. Added features like var for local variables, new HTTP client API, and
enhancements to the garbage collection mechanism.
i. JDK 17 (2021)
1. Another LTS release, adding features like sealed classes, records, and
pattern matching for instance checks.
2. Improved performance, security, and the introduction of new language.
j. JDK 21 (2023)
1. Introduced features such as virtual threads (Project Loom) for
scalable concurrency, string templates, and structured concurrency to
handle parallel operations more effectively.
3. Distributions of JDK
Several organizations provide JDK distributions, each with its own set of
tools and support. These are the most widely used distributions:
a. Oracle JDK
1. Developed and maintained by Oracle. Oracle JDK provides long-term
support for enterprise applications, including regular security updates.
2. Oracle JDK is free for development and testing, but requires a
commercial license for production use.
b. OpenJDK
1. The official open-source reference implementation of the Java platform.
2. OpenJDK is free and maintained by a large community of developers,
including contributions from Oracle and other companies.
c. Amazon Corretto
1. A free, production-ready distribution of OpenJDK by Amazon.
2. Corretto offers long-term support and is used internally at Amazon
across a variety of services.
d. Eclipse Temurin (AdoptOpenJDK)
1. A community effort to provide prebuilt OpenJDK binaries for various
platforms.
2. Eclipse Temurin is a popular choice for developers seeking a free,
open-source JDK distribution.
e. Azul Zulu
1. A commercially supported build of OpenJDK by Azul Systems.
2. Offers Zulu Community Edition (free) and Zulu Enterprise (paid) for
enterprise applications.

4. JDK Installation and Setup


To develop Java applications, the JDK must be installed on your system.
Here’s a general guide on how to install and set up the JDK:
a. Download the JDK: Visit the official website of your preferred JDK
distribution and download the latest version.
b. Install the JDK
1. Follow the installation instructions provided for your operating system.
2. On Windows, the installation is usually done through an installer. On
Linux/macOS, it can be installed via package managers (e.g., apt, brew).
c. Set the JAVA_HOME Environment Variable
1. After installation, you should set the JAVA_HOME environment
variable to point to the JDK installation directory.
2. On Windows: Go to System Properties → Environment Variables →
New, and set JAVA_HOME to the JDK installation path.
3. On Linux/macOS: Add export JAVA_HOME=/path/to/jdk to your
shell profile (e.g., .bashrc or .zshrc).
3. DATA TYPES

In Java, data types are the foundation for defining variables and constants.
They determine the type of data that can be stored and the operations that
can be performed on that data. Java has two main categories of data types:

1. Primitive Data Types


Primitive data types in Java are the most basic types of data. They are
predefined by the language and represent simple values like integers,
floating-point numbers, characters, and booleans. There are 8 primitive
data types in Java:

1.1. Byte
Size: 8 bits (1 byte)
Default value: 0
Range: -128 to 127
Use case: Useful for saving memory in large arrays where memory
savings matter.
Example: bytebyteValue=100;

1.2. Short
Size: 16 bits (2 bytes)
Default value: 0
Range: -32,768 to 32,767
Use case: Short can save memory in large arrays, but it is rarely used as
int is generally preferred.
Example: shortshortValue=10000;

1.3. Int
Size: 32 bits (4 bytes)
Default value: 0
Range: -2^31 to 2^31-1 (approximately -2.14 billion to 2.14 billion)
Use case: The most commonly used integer data type in Java for numeric
calculations.
Example: intintValue=100000;

1.4. Long
Size: 64 bits (8 bytes)
Default value: 0L
Range: -2^63 to 2^63-1 (approx -9.22 quintillion to 9.22 quintillion)
Use case: When you need a larger range than int can provide, such as for
large computations or representing large values.
Example: longlongValue=10000000000L;
1.5. Float
Size: 32 bits (4 bytes)
Default value: 0.0f
Range: Approximately ±3.4e38 (7 digits of precision)
Use case: Used when you need to save memory and don't need a very
high degree of precision.
Example: floatfloatValue=3.14f;

1.6. Double
Size: 64 bits (8 bytes)
Default value: 0.0d
Range: Approximately ±1.7e308 (15 digits of precision)
Use case: The default data type for decimal values in Java and should be
used when precision matters.
Example: doubledoubleValue=3.14159;

1.7. Boolean
Size: 1 bit (though its precise size is JVM-dependent)
Default value: false
Values: true or false
Use case: Represents one of two values, true or false. Commonly used in
conditional statements, loops, and flags for control flow.
Example: booleanisJavaFun=true;

1.8. Char
Size: 16 bits (2 bytes)
Default value: '\u0000' (the null character)
Range: 0 to 65,535 (since it stores Unicode values)
Use case: Used for storing a single character.
Example: charletter='A';

2. Reference (or Object) Data Types


Reference types in Java store references (addresses) to objects. These
types are created using classes and are used to access objects. Unlike
primitive types, which store their values directly, reference types store
addresses that point to where the objects are stored in memory.
Key Characteristics:
1. Default value: null (for uninitialized reference types).
2. These types do not store actual data values directly but store a
reference to the object that contains the data.
3. They can be used to call methods on objects.
Reference types include:
2.1 Class Types
A class is a blueprint for creating objects, and a class type is a reference
to an object of a class. When you create an object using the new keyword,
you're creating an instance of a class.
Example:
classDog {
String name;
int age;
voidbark() {
System.out.println("Woof!"); }
}
publicclassMain {
publicstaticvoidmain(String[] args) {
DogmyDog=newDog();
myDog.name = "Buddy";
myDog.age = 5;
myDog.bark();
}
}
In this example, myDog is a reference to an object of type Dog. The
actual data (name and age) and methods (like bark()) are stored in the
Dog object, and myDog points to that object.

2.2 Array Types


Arrays are objects in Java that hold multiple values of a specific data
type. The type of an array is defined by the type of its elements followed
by square brackets ([]).
Example:
int[] numbers = {1, 2, 3, 4, 5};
String[] names = {"Alice", "Bob", "Charlie"};
(reference type)
The numbers array holds integers, and the names array holds references
to String objects.

2.3 Interface Types


An interface is a reference type in Java, similar to a class, that can
contain only constants, method signatures, default methods, static
methods, and nested types. Interfaces cannot contain instance fields,
constructors, or methods with implementation.
Example:
interfaceAnimal {
voidsound(); }
classDogimplementsAnimal {
publicvoidsound() {
System.out.println("Bark"); }
}
publicclassMain {
publicstaticvoidmain(String[] args) {
Animalanimal=newDog(); // Reference type to Dog object
animal.sound(); // Outputs: Bark }
}
Here, Animal is an interface, and the Dog class implements it. The
variable animal is of the reference type Animal, but it holds a reference to
a Dog object.

2.4 String Type


The String type in Java is a special class for handling sequences of
characters. Even though String is an object, it behaves like a primitive
type in many situations because it is immutable (its value cannot be
changed once created).
Example: Stringmessage="Hello, World!";
Here, message is a reference to a String object that holds the text "Hello,
World!"

3. Type Casting in Java


Type casting allows you to convert one data type into another. There are
two types of type casting in Java:
1 Widening (Implicit) Type Casting
This happens automatically when you assign a smaller type to a larger
type, as the conversion is guaranteed to be safe.
For example: intmyInt=10;doublemyDouble= myInt; // Automatic
casting: int to double

3.2 Narrowing (Explicit) Type Casting


This must be done manually and is used when assigning a larger type to a
smaller type, which might result in data loss.
For example: doublemyDouble=9.78;intmyInt= (int) myDouble; //
Manual casting: double to int

4. Wrapper Classes for Primitive Types


For every primitive data type, Java provides a corresponding wrapper
class that allows primitive values to be treated as objects. These wrapper
classes are useful when you need
4. INHERITANCE
Inheritance is one of the key features of Object-Oriented Programming
(OOP) in Java. It allows one class to acquire the properties (fields) and
behaviors (methods) of another class. The class that is inherited from is
called the superclass or parent class, and the class that inherits is called
the subclass or child class. Inheritance promotes code reusability and
establishes a natural hierarchy between classes.

Key Concepts of Inheritance


1. Superclass (Parent Class): The class from which another class
inherits properties and methods. It is also referred to as the base class. In
Java, any class can be a superclass (except for final classes, which can't
be extended).
Example:-
classAnimal {
String name;
voideat() {
System.out.println("This animal is eating.");
}
}
2. Subclass (Child Class): The class that inherits from another class is
called the subclass. It can inherit both data members (fields) and methods
of the superclass. In Java, a subclass can have additional fields and
methods of its own, apart from those inherited from the parent class.
Example:-
classDogextendsAnimal { // Dog is a subclass of Animal
voidbark() {
System.out.println("The dog is barking.");
}
}
3. Extends Keyword: The extends keyword is used to create a subclass.
A class can extend only one other class (single inheritance), but it can
have multiple levels of inheritance (multilevel inheritance).
Example:-
classDogextendsAnimal {
}
4. Super Keyword: The super keyword is used to refer to the superclass's
members (fields and methods). It is particularly useful when the subclass
wants to invoke a constructor or method from the parent class.
Example:-
classDogextendsAnimal {
voideat() {
super.eat();
System.out.println("The dog is eating.");
}
}

Types of Inheritance in Java


Java supports several types of inheritance:
1. Single Inheritance: In single inheritance, a subclass inherits from a
single superclass. This is the most basic form of inheritance.
Example:-
classAnimal {
voideat() {
System.out.println("Animal eats.");
}
}
classDogextendsAnimal {
voidbark() {
System.out.println("Dog barks.");
}
}
Here, Dog is the subclass and Animal is the superclass.
2. Multilevel Inheritance: In multilevel inheritance, a class is derived
from a class that is also derived from another class. In other words, there
is a chain of inheritance.
Example:-
classAnimal {
voideat() {
System.out.println("Animal eats.");
}
}
classMammalextendsAnimal {
voidwalk() {
System.out.println("Mammal walks.");
}
}
classDogextendsMammal {
voidbark() {
System.out.println("Dog barks.");
}
}
In this case, Dog inherits from Mammal, and Mammal inherits from
Animal. The Dog class has access to all methods of Mammal and Animal.
3. Hierarchical Inheritance: In hierarchical inheritance, multiple
subclasses inherit from a single superclass.
Example:-
classAnimal {
voideat() {
System.out.println("Animal eats.");
}
}
classDogextendsAnimal {
voidbark() {
System.out.println("Dog barks.");
}
}
classCatextendsAnimal {
voidmeow() {
System.out.println("Cat meows.");
}
}
In this example, both Dog and Cat are subclasses of Animal. They inherit
the eat() method from the Animal class.

4. Hybrid Inheritance (Not supported directly in Java): Hybrid


inheritance is a combination of more than one tpe of inheritance. It can be
achieved in Java using interfaces, as multiple inheritance via classes is
not allowed.

Key Features of Inheritance


1. Code Reusability: Inheritance allows for the reuse of existing code.
You can write common methods in the superclass and inherit them in
subclasses instead of writing them again.
2. Method Overriding: Inheritance allows subclasses to provide specific
implementations for methods that are defined in the superclass. This is
called method overriding. Method overriding allows for runtime
polymorphism.
Example:-
classAnimal {
voidsound() {
System.out.println("Animal makes a sound.");
}
}
classDogextendsAnimal {
@Override
voidsound() {
System.out.println("Dog barks.");
}
}
3. super() Constructor Call: A subclass can use super() to call the
superclass’s constructor explicitly. If no super() is called, Java implicitly
calls the no-argument constructor of the superclass. The super()
constructor call must be the first line in the subclass's constructor.
Example:-
classAnimal {
Animal() {
System.out.println("Animal constructor.");
}
}
classDogextendsAnimal {
Dog() {
super(); // Calls the constructor of Animal class
System.out.println("Dog constructor.");
}
}

1. Inheritance of Constructors: While a subclass can inheri the


properties and methods of its superclass, constructors are not inherited.
However, the subclass can call the constructor of the superclass using
super().
5. Protected Members: Fields and methods declared with the protected
access modifier in the superclass are accessible within the same package
and by subclasses. This is useful when you want to allow subclasses to
access certain members but not allow access to other classes.

Example of Inheritance
Let's consider a more detailed example to illustrate the concept of
inheritance in Java.
Example:-
classVehicle {
int speed;
voidmove() {
System.out.println("Vehicle is moving at speed: " + speed);
}
}
classCarextendsVehicle {
int numDoors;
voiddisplay() {
System.out.println("Car has " + numDoors + " doors and is moving
at speed: " + speed);
}
}
publicclassMain {
publicstaticvoidmain(String[] args) {
CarmyCar=newCar();
myCar.speed = 60; // Inherited from Vehicle
myCar.numDoors = 4; // Specific to Car
myCar.move(); // Inherited method
myCar.display(); // Specific to Car
}
}
Explanation:
Vehicle is the superclass that has a speed attribute and a move() method.
Car is the subclass that inherits speed and move() from Vehicle and adds
a numDoors attribute and a display() method. The myCar object of class
Car has access to both the Vehicle and Car methods.

Advantages of Inheritance
1. Code Reusability: You can reuse existing code by inheriting it into the
subclass rather than writing the code again. This reduces redundancy.
2. Polymorphism: Inheritance allows the subclass to define specific
implementations of methods, which enables polymorphism (method
overriding). This allows for dynamic method dispatch, where the type of
the object determines which method is executed at runtime.
3. Extensibility: New features can be added to an existing class without
modifying it, by sub classing and extending the original class.
4. Data Hiding: The parent class can protect certain fields and methods
using access modifiers like private and protected, allowing controlled
access from subclasses.
Disadvantages of Inheritance
1. Tight Coupling: Inheritance creates a tightly coupled relationship
between the superclass and subclass. Changes in the superclass can affect
the subclasses, which can lead to maintenance challenges.
2. Complexity: Overusing inheritance or creating deep inheritance
hierarchies can make the code complex, difficult to understand, and hard
to maintain.
3. Limited Flexibility: Java only supports single inheritance through
classes. A class can only inherit from one superclass, which can limit the
flexibility compared to languages that support multiple inheritance.
5. POLYMORPHISM
Polymorphism is a core concept of OOP’s that allows objects of
different types to be treated as objects of a common super type. It enables
a single method, interface, or class to represent different behaviors in
different contexts. The term "polymorphism" comes from Greek,
meaning "many forms," and in Java, it refers to the ability of a single
method or object to take on different forms depending on the situation.
Polymorphism in Java can be categorized into two main types:
1. Compile-time (Static) Polymorphism
Compile-time polymorphism, also known as static polymorphism, is
resolved during the compilation of the program. In Java, it is achieved
through method overloading and operator overloading.
a. Method Overloading
Method overloading allows multiple methods in the same class to have
the same name but with different parameter lists. The method to be called
is resolved at compile time based on the method signature.
Example:
classCalculator {
intadd(int a, int b) {
return a + b;
}
intadd(int a, int b, int c) {
return a + b + c;
}
doubleadd(double a, double b) {
return a + b;
}
}
publicclassMain {
publicstaticvoidmain(String[] args) {
Calculatorcalc=newCalculator();
System.out.println(calc.add(10, 20));
System.out.println(calc.add(10, 20, 30));
System.out.println(calc.add(10.5, 20.5));
}
}

In this example, the add() method is overloaded to handle different


numbers and types of parameters. The compiler determines which version
of add() to call based on the arguments passed.
b. Operator Overloading in Java
Java does not support operator overloading directly (unlike languages like
C++). The only exception is the + operator, which is overloaded to
perform both addition and string concatenation.
Example:
intsum=10 + 20;
integersStringmessage="Hello " + "World!";
Here, + acts as both an arithmetic operator for numbers and a
concatenation operator for strings.

2. Runtime (Dynamic) Polymorphism


Runtime polymorphism, also known as dynamic polymorphism,
occurs when the method that will be executed is determined at runtime,
rather than compile-time. In Java, runtime polymorphism is achieved
through method overriding and the use of upcasting.
a. Method Overriding
Method overriding occurs when a subclass provides a specific
implementation of a method that is already defined in its superclass. The
overridden method in the subclass has the same name, return type, and
parameters as the method in the superclass. The decision of which
method to invoke is made at runtime based on the object.
Example:
classAnimal {
voidsound() {
System.out.println("Animal makes a sound");
}
}
classDogextendsAnimal {
@Override
voidsound() {
System.out.println("Dog barks");
}
}
classCatextendsAnimal {
@Override
voidsound() {
System.out.println("Cat meows");
}
}
publicclassMain {
publicstaticvoidmain(String[] args) {
Animalanimal1=newDog(); // Upcasting
Animalanimal2=newCat(); // Upcasting
animal1.sound(); // Outputs: Dog barks
animal2.sound(); // Outputs: Cat meows
}
}
In this example, even though animal1 and animal2 are declared as Animal,
the actual objects they refer to are Dog and Cat. The decision of which
sound() method to call is made at runtime based on the actual object the
reference is pointing to.

b.Upcasting
Upcasting refers to treating a subclass object as if it were an instance of
its superclass. This allows Java to achieve runtime polymorphism. In
upcasting, the subclass object can still call overridden methods, but not
methods specific to the subclass unless explicitly cast back to the subclass.
Example: AnimalmyDog=newDog(); // Upcasting
myDog.sound(); // Calls the Dog class's overridden method
Here, myDog is treated as an Animal reference, but it still calls the
sound() method from the Dog class because of polymorphism.

Polymorphism through Interfaces


Interfaces in Java provide another way to achieve polymorphism. When
a class implements an interface, it can provide different implementations
of the methods defined by the interface, and this can be used to achieve
dynamic method dispatch.
Example:
interfaceAnimal {
voidsound();
}
classDogimplementsAnimal {
publicvoidsound() {
System.out.println("Dog barks"); }
}
classCatimplementsAnimal {
publicvoidsound() {
System.out.println("Cat meows"); }
}
publicclassMain {
publicstaticvoidmain(String[] args) {
Animalanimal1=newDog();
Animalanimal2=newCat();
animal1.sound(); // Outputs: Dog barks
animal2.sound(); // Outputs: Cat meows }
}
Here, Dog and Cat implement the Animal interface. Even though animal1
and animal2 are references of type Animal, the correct implementation of
the sound() method is chosen at runtime based on the actual type of the
object.

Advantages of Polymorphism
1. Code Reusability: Polymorphism allows you to write code that works
with multiple types of objects, reducing redundancy.
2. Flexibility and Maintainability: It allows one method to work with
objects of different types, which makes code more flexible and easier to
extend or maintain.
3. Dynamic Method Invocation: Runtime polymorphism allows
dynamic method invocation, which means that method calls are resolved
at runtime based on the actual object being referred to.
4. Simplifies Code: Through polymorphism, the same piece of code can
work for objects of different types, reducing the complexity of the overall
program.
Disadvantages of Polymorphism
1. Slower Execution: Runtime polymorphism incurs a slight
performance overhead because method calls are resolved at runtime
rather than compile-time.
2. Debugging Complexity: Because method invocations are determined
at runtime, tracking down bugs can be more challenging, especially in
larger applications.
3. Increased Complexity in Understanding: New developers may find
it harder to understand the code since method invocation depends on the
actual object at runtime, not the reference type.
4. Reduced Type Safety: Polymorphism sometimes leads to reduced
compile-time type safety, which may result in runtime errors (though
Java mitigates this to a large extent with its strong typing system).

Summary
Polymorphism in Java provides flexibility in code design by allowing
objects of different classes to be treated as objects of a common
superclass or interface. It is mainly achieved through:
1. Compile-time (static): Via method overloading.
2. Runtime (dynamic): Via method overriding and up casting.
It enables Java applications to have cleaner, more modular, and extensible
designs by supporting object-oriented principles like abstraction,
encapsulation, and inheritance.

You might also like