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

JAVA ASS11

Object-Oriented Programming (OOP) in Java is a paradigm that organizes software around data, utilizing key concepts such as encapsulation, inheritance, polymorphism, and abstraction. The Java Development Kit (JDK) is essential for developing Java applications, containing tools like the Java compiler, Java Runtime Environment, and various libraries. The JDK has evolved through various versions, introducing significant features and improvements to support modern application development.

Uploaded by

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

JAVA ASS11

Object-Oriented Programming (OOP) in Java is a paradigm that organizes software around data, utilizing key concepts such as encapsulation, inheritance, polymorphism, and abstraction. The Java Development Kit (JDK) is essential for developing Java applications, containing tools like the Java compiler, Java Runtime Environment, and various libraries. The JDK has evolved through various versions, introducing significant features and improvements to support modern application development.

Uploaded by

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

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
2. Inheritance
3. Polymorphism
4. Abstraction

1. Encapsulation: Encapsulation 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; // Private field, cannot be accessed directly
from outside

// Public method to deposit money


public void deposit(double amount) {
if (amount > 0) {
balance += amount;
}
}

// Public method to withdraw money


public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
}
}
// Public method to view balance
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:

 Superclass: The class being inherited from (also called the parent
class).
 Subclass: The class that inherits from the superclass (also called
the child class).
 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");
}
}
// Dog class inherits from Animal class
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:

 Single Inheritance: A subclass inherits from one superclass.


 Multilevel Inheritance: A class is derived from a class that is also
derived from another class.

Note: Multiple inheritance (where a class inherits from more than one
class) is not supported in Java to avoid ambiguity (known as the
"diamond problem"). However, it can be achieved through interfaces.

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)

3.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 {
// Method with two integer parameters
public int add(int a, int b) {
return a + b;
}

// Overloaded method with three integer parameters


public int add(int a, int b, int c) {
return a + b + c;
}

// Overloaded method with double parameters


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.

3.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
2. Interfaces

4.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.

4.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.

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:

1. 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.

a. 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.
b. 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.).

c. 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.

d. 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.
e. 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.

2. 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)

 The very first release of the JDK. It included basic tools for
developing Java applications, such as the compiler, interpreter, and
debugger.
 Supported applets, which were embedded into web browsers using
Java technology.

b. JDK 1.1 (1997)

 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)

 Introduced major language enhancements like Generics,


Annotations, Enums, and Varargs.
 Enhanced the collections framework and provided a new
java.util.concurrent package for better multithreading support.
d. JDK 6 (2006)

 Focused on performance improvements and included scripting


language support (JSR 223).
 Introduced enhancements to Web Services and the Java Compiler
API.

e. JDK 7 (2011)

 Introduced features like try-with-resources (automatic resource


management), the diamond operator (<> for generic instantiation),
and NIO2 for better file handling.

f. JDK 8 (2014)

 One of the most popular versions, it introduced Lambda


Expressions and the Stream API, allowing developers to write
more functional-style code.
 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)

 Introduced the module system (Project Jigsaw) that allows better


modularization of applications, particularly for large systems.
 Added jshell, the REPL tool for interactive Java programming.

h. JDK 11 (2018)

 A Long-Term Support (LTS) release.


 Added features like var for local variables, new HTTP client API,
and enhancements to the garbage collection mechanism.

i. JDK 17 (2021)

 Another LTS release, adding features like sealed classes, records,


and pattern matching for instance checks.
 Improved performance, security, and the introduction of new
language features.

j. JDK 21 (2023)
 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

 Developed and maintained by Oracle. Oracle JDK provides long-


term support for enterprise applications, including regular security
updates.
 Oracle JDK is free for development and testing, but requires a
commercial license for production use.

b. OpenJDK

 The official open-source reference implementation of the Java


platform.
 OpenJDK is free and maintained by a large community of
developers, including contributions from Oracle and other
companies.

c. Amazon Corretto

 A free, production-ready distribution of OpenJDK provided by


Amazon.
 Corretto offers long-term support and is used internally at Amazon
across a variety of services.

d. Eclipse Temurin (AdoptOpenJDK)

 A community effort to provide prebuilt OpenJDK binaries for


various platforms.
 Eclipse Temurin is a popular choice for developers seeking a free,
open-source JDK distribution.

e. Azul Zulu

 A commercially supported build of OpenJDK by Azul Systems.


 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


(Oracle, OpenJDK, Amazon Corretto, etc.) and download the latest
version.

b. Install the JDK

 Follow the installation instructions provided for your operating


system (Windows, macOS, Linux).
 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

 After installation, you should set the JAVA_HOME environment


variable to point to the JDK installation directory.
 On Windows:

o Go to System Properties → Environment Variables → New,


and set JAVA_HOME to the JDK installation path.
 On Linux/macOS:

o Add export JAVA_HOME=/path/to/jdk to your shell profile


(e.g., .bashrc or .zshrc).

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


2. Reference/Object 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. It can also be used in file handling operations
where binary data is managed.

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 (approximately -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 (e.g., for
banking or big data calculations).

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. Often used in large arrays of
floating-point numbers in performance-critical applications (e.g.,
graphics or scientific computations).

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. Used in precise
calculations like those involving currency, physics, or complex
mathematical calculations.

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. Java uses Unicode,
which makes char suitable for internationalization and working
with a wide range of characters.

Example:

charletter='A';

Memory Efficiency of Primitive Types:

Java ensures efficient memory allocation with its primitive types. For
example, int is more memory-efficient than long, and float consumes less
memory than double.
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:

 Default value: null (for uninitialized reference types).


 These types do not store actual data values directly but store a
reference to the object that contains the data.
 They can be used to call methods on objects.

Reference types include:

1. Objects (instances of classes)


2. Arrays
3. Enums
4. Interfaces

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(); // Reference type to the Dog object
myDog.name = "Buddy";
myDog.age = 5;
myDog.bark(); // Outputs: Woof!
}
}

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}; // Array of int


String[] names = {"Alice", "Bob", "Charlie"}; // Array of String
(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 (except default methods in
Java 8 and later).

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:

3.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

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 {
// Dog class inherits all fields and methods from Animal class.
}

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(); // Calls the eat method from the Animal class
System.out.println("The dog is eating.");
}
}
Types of Inheritance in Java

Java supports several types of inheritance, though multiple inheritance


through classes is not allowed directly (only through interfaces).

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.");
}
}

4. 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.
Restrictions of Inheritance in Java

1. Multiple Inheritance: Java does not support multiple


inheritance via classes to avoid the diamond problem. This
problem arises when a class can inherit from two classes that
both define the same method. Java resolves this issue by
allowing multiple inheritance through interfaces only.
2. Final Keyword: A class declared as final cannot be
extended (inherited). A method declared as final cannot be
overridden by a subclass.

Example:-

finalclassAnimal {
// Cannot be inherited
}
classDogextendsAnimal { // This will result in a compilation error
}

POLYMORPHISM

Polymorphism is a core concept of Object-Oriented Programming (OOP)


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


2. Runtime (Dynamic) Polymorphism

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.

1.1 Method Overloading

Method overloading allows multiple methods in the same class to have


the same name but with different parameter lists (i.e., the number or type
of parameters). The method to be called is resolved at compile time based
on the method signature (method name, number, and type of parameters).

Example:

classCalculator {
// Method for adding two integers
intadd(int a, int b) {
return a + b;
}

// Method for adding three integers (overloaded method)


intadd(int a, int b, int c) {
return a + b + c;
}

// Method for adding two doubles (overloaded method)


doubleadd(double a, double b) {
return a + b;
}
}
publicclassMain {
publicstaticvoidmain(String[] args) {
Calculatorcalc=newCalculator();
System.out.println(calc.add(10, 20)); // Calls add(int, int)
System.out.println(calc.add(10, 20, 30)); // Calls add(int, int, int)
System.out.println(calc.add(10.5, 20.5)); // Calls add(double,
double)
}
}

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.
1.2 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;
// Addition of integersStringmessage="Hello " + "World!"; // String
concatenation

 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 (i.e., treating a
subclass object as an instance of its superclass).

2.1 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 (superclass or subclass) 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.

2.2 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.

Differences Between Method Overloading and Method Overriding

Feature Method Overloading Method Overriding


Feature Method Overloading Method Overriding
Same method name and
Same method name with
Definition parameters in superclass and
different parameter lists
subclass
Time of Compile-time (static Runtime (dynamic
Resolution polymorphism) polymorphism)
Must be the same as the
Return Type Can be different
superclass's method
Happens within the same Happens in a subclass
Relationship
class (inheritance)
Must be different (number
Signature Must be exactly the same
or type of parameters)
Access Can have any access Cannot reduce the visibility of
Modifier modifier the superclass method

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. Reduces Coupling: Polymorphism reduces the coupling
between classes. You can change or add new
implementations without modifying existing code, as long as
the interface remains the same.
5. 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:

 Compile-time (static) polymorphism: Via method overloading.


 Runtime (dynamic) polymorphism: 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