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

JAVA PROGRAMMING FULL NOTES

The document provides comprehensive notes on Java programming, covering its architecture, features, evolution, and comparisons with C++. It details the Java Virtual Machine (JVM), Java Runtime Environment (JRE), basic syntax, data types, control flow statements, arrays, and object-oriented principles like classes and methods. Additionally, it discusses mutator and accessor methods, emphasizing encapsulation and data validation.

Uploaded by

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

JAVA PROGRAMMING FULL NOTES

The document provides comprehensive notes on Java programming, covering its architecture, features, evolution, and comparisons with C++. It details the Java Virtual Machine (JVM), Java Runtime Environment (JRE), basic syntax, data types, control flow statements, arrays, and object-oriented principles like classes and methods. Additionally, it discusses mutator and accessor methods, emphasizing encapsulation and data validation.

Uploaded by

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

1|Page

JAVA PROGRAMMING
NOTES
PREPARED BY click to know

Do not click here

Neither here

Nor here
2|Page

UNIT I:
3|Page

The Java Platform: Architecture


The Java Platform is a suite of programs that facilitate developing and
running programs written in the Java programming language. It
includes an execution engine (Java Virtual Machine), a compiler, and a
set of libraries. The JVM executes Java bytecode, enabling platform
independence. Java's architecture ensures that compiled code can run
on any device equipped with a JVM, adhering to the "Write Once, Run
Anywhere" philosophy.

Java Features
Java boasts several key features:

• Object-Oriented: Encourages modular and reusable code.

• Platform-Independent: Java bytecode runs on any platform with


a JVM.

• Robust: Emphasizes early error checking and runtime checking.

• Multithreaded: Supports concurrent execution of code.

• Secure: Provides a secure environment by restricting certain


operations.

• High Performance: Just-In-Time compilers enhance performance.

• Dynamic: Supports dynamic loading of classes.


4|Page

Java Evolution
Java was developed by James Gosling and his team at Sun
Microsystems in 1991 as part of the "Green Project." Initially named
Oak, it was designed for interactive consumer electronics like
televisions. However, the team realized its potential for web
development, leading to its rebranding as Java in 1995. The name
"Java" was inspired by coffee, reflecting its creators’ love for coffee
from Java Island.

Java gained prominence due to its platform independence, achieved


through the Java Virtual Machine (JVM). Its "Write Once, Run
Anywhere" principle made it popular for web applications, applets, and
enterprise solutions.

Over the years, Java has undergone significant updates to improve its
performance, security, and developer experience:

1. Java 1.0 (1996): Introduced core features like applets, AWT, and
platform independence.

2. Java 2 (1998): Brought in Swing, Collections Framework, and the


division into J2SE, J2EE, and J2ME.

3. Java 5 (2004): Introduced generics, annotations, and the


enhanced for loop.

4. Java 8 (2014): A major milestone introducing lambda expressions,


the Stream API, and the new Date-Time API.
5|Page

5. Java 9 (2017): Introduced the module system (Project Jigsaw) and


a REPL tool (JShell).

6. Java 11 (2018): Brought features like the HTTP client and


standardized the long-term support (LTS) model.

7. Java 17 (2021): Included pattern matching, sealed classes, and the


latest performance enhancements.

8. Java 23 (2024): Introduced features like scoped values, Stream


gatherers, and Class-File API etc.

Today, Java is widely used in fields such as web development,


enterprise applications, Android app development, and big data. Its
consistent updates, robust libraries, and active community have
ensured its relevance as one of the most popular programming
languages globally.
6|Page

Java vs. C++


Java and C++ are both object-oriented programming languages, but
they cater to different use cases and have distinct characteristics.
Below is a comparison:

1. Platform Dependency

• Java: Platform-independent due to its "Write Once, Run


Anywhere" philosophy. Java code is compiled into bytecode,
which runs on any device with a Java Virtual Machine (JVM).

• C++: Platform-dependent. Code needs to be compiled separately


for each operating system and hardware.

2. Memory Management

• Java: Features automatic garbage collection, where unused


memory is freed up automatically.

• C++: Requires manual memory management using malloc, free,


new, and delete, increasing the chances of memory leaks.

3. Performance

• C++: Generally faster due to its closer interaction with hardware


and absence of an intermediate layer like JVM.

• Java: Slower in comparison due to JVM overhead, but modern JIT


(Just-In-Time) compilers have significantly improved performance.
7|Page

4. Pointers

• C++: Fully supports pointers, giving low-level access to memory.

• Java: Does not support explicit pointers, ensuring more secure


and error-free code.

5. Multiple Inheritance

• C++: Supports multiple inheritance, which can lead to


complexities like the diamond problem.

• Java: Does not allow multiple inheritance directly but provides


interfaces to achieve similar functionality.

6. Syntax and Simplicity

• Java: Simpler syntax with a focus on readability and ease of use.

• C++: More complex due to features like pointers, operator


overloading, and templates.

7. Applications

• Java: Commonly used for web applications, enterprise solutions,


and Android app development.

• C++: Preferred for system-level programming, game development,


and applications requiring high performance.
8|Page

Understanding JVM and JRE


The Java Virtual Machine (JVM) and Java Runtime Environment (JRE)
are integral components of the Java platform that enable Java
applications to run on any system.

• JVM (Java Virtual Machine):


The JVM is a part of the JRE and acts as an interpreter for Java
bytecode. It ensures platform independence by executing
bytecode on different operating systems without modification.
The JVM also manages memory through garbage collection and
provides runtime error checking, ensuring security and stability.

• JRE (Java Runtime Environment):


The JRE includes the JVM and additional libraries and components
required to run Java programs. It provides the environment
necessary for executing Java applications but does not include
development tools like compilers or debuggers.

In essence, the JVM executes the program, while the JRE provides the
essential resources for its execution.
9|Page

Basic Java Syntax:


Data Types
Java provides several data types:

• Primitive Types: byte, short, int, long, float, double, char,


boolean.

• Non-Primitive Types: Strings, arrays, classes, interfaces.

Primitive types are predefined and hold simple values, while non-
primitive types are created by the programmer and can hold multiple
values or methods.

Variables
Variables are containers for storing data values. In Java, you must
declare a variable with a specific type before using it:

int number = 5;

String name = "Alice";

Variables can be local, instance, or class variables, depending on their


scope and where they are declared.
10 | P a g e

Operators
Java operators are special symbols that perform operations on
variables or values. They can be classified into several categories based
on their functionality. These operators play a crucial role in performing
arithmetic, logical, relational, and bitwise operations etc.

Types of Operators in Java

1. Arithmetic Operators (+, -, *, /)

2. Unary Operators (-, +, --, ++, !)

3. Assignment Operator (=)

4. Relational Operators (==, !=, <, <=, >, >=)

5. Logical Operators (&&, ||, !,)

6. Ternary Operator (condition ? if true : if false)

7. Bitwise Operators (&, |, ^, ~)

8. Shift Operators (<<, >>, >>>)

9. instance of operator (object instance of class/subclass/interface)


11 | P a g e

Type Conversions & Casts


Type Casting: In typing casting, a data type is converted into another
data type by the programmer using the casting operator. It is also called
narrowing conversion.

float x;
byte y;
...
...
y=(byte)x;

Type conversion: In type conversion, a data type is automatically


converted into another data type by a compiler at the compiler time.
One more important thing is that it can only be applied to compatible
data types.

int x=30;
float y;
y=x; // y==30.000000.
12 | P a g e

Strings
String is the type of objects that can store the sequence of characters
enclosed by double quotes, defined by the String class. Strings are
immutable, once created their value cannot change.

Common methods:

o .length(): Gets the length.

o .charAt(index): Returns the character at the specified index.

o .equals(): Checks equality.

Example:

String name = "Alice";

System.out.println(name.toUpperCase());

Equality Test
• Primitive types: Use == to compare values.

• Objects (like Strings): Use .equals() for content comparison and


== for reference comparison. For example,

String a = "hello";

String b = "hello";

System.out.println(a.equals(b)); // true
13 | P a g e

Input and Output


Java brings various Streams with its I/O package that helps the user to
perform all the input-output operations.

System.in

The standard input stream(System.in) is used to read characters from


the keyboard or any other standard input device.

System.out

The standard output stream(System.out) is used to produce the result


of a program on an output device like the computer screen.

For example: System.out.print(“Hello”);

File Input and Output


File Input and Output (I/O) refers to reading data from files and writing
data to files using classes provided in the java.io package. The java.io
package contains nearly every class that we need to perform input and
output (I/O) in Java. All these streams represent an input source and an
output destination. The stream in the java.io package supports many
data such as primitives, object, localized characters, etc.

File Input (Reading Files):


Reading data from a file can be achieved using classes like FileReader,
BufferedReader, or Scanner. For example:
14 | P a g e

BufferedReader reader = new BufferedReader(new


FileReader("input.txt"));

File Output (Writing to Files):


Writing data to a file is done using classes like FileWriter or
BufferedWriter. For example:

FileWriter writer = new FileWriter("output.txt");

Control Flow Statements


Java compiler executes the code from top to bottom. The statements in
the code are executed according to the order in which they appear.
However, Java provides statements that can be used to control the flow
of Java code. Such statements are called control flow statements. It is
one of the fundamental features of Java, which provides a smooth flow
of program.

Java provides three types of control flow statements.

1. Decision Making statements

o if statements

o switch statement

2. Loop statements

o do while loop

o while loop
15 | P a g e

o for loop

o for-each loop

3. Jump statements

o break statement

o continue statement

ARRAYS
Arrays are fundamental structures in Java that allow us to store
multiple values of the same type in a single variable. They are useful for
storing and managing collections of data.

int[] arr = { 1, 2, 3, 4, 5 };

There are some basic operations on arrays like:

1. Array Declaration

To declare an array in Java, use the following syntax:

type[] arrayName;

2. Create an Array

To create an array, you need to allocate memory for it using the “new”
keyword
16 | P a g e

// Creating an array of 5 integers


numbers = new int[5];

3. Access an Element of an Array

We can access array elements using their index, which starts from 0:

// Setting the first element of the array


numbers[0] = 10;

// Accessing the first element


int firstElement = numbers[0];

4. Change an Array Element

To change an element, assign a new value to a specific index:

// Changing the first element to 20


numbers[0] = 20;

5. Array Length

We can get the length of an array using the length property:

// Getting the length of the array


int length = numbers.length;

6. Iterating Through Arrays

Using for loop:

for (int i = 0; i < numbers.length; i++) {

System.out.println(numbers[i]);}
17 | P a g e

Command Line Parameters


Java command-line argument is an argument i.e. passed at the time of
running the Java program. In Java, the command line arguments passed
from the console can be received in the Java program and they can be
used as input. The users can pass the arguments during the execution
bypassing the command-line arguments inside the main() method.

Example:

public class CommandLineExample {

public static void main(String[] args) {

System.out.println("Number of arguments: " + args.length);

for (int i = 0; i < args.length; i++) {

System.out.println("Argument " + (i + 1) + ": " + args[i]);

Then we run it by “java CommandLineExample Hello World 123”

//output

Number of arguments: 3

Argument 1: Hello

Argument 2: World

Argument 3: 123
18 | P a g e

Ragged Arrays & Vectors


A ragged array (also known as a jagged array) is an array of arrays
where each sub-array can have a different length. This allows for more
flexible and dynamic data structures, where each row or sub-array can
vary in size.

1. Declaration:

int[][] raggedArray;

2. Initialization:

int[][] raggedArray = {

{1, 2}, // Row 0 has 2 elements

{3, 4, 5}, // Row 1 has 3 elements

{6} // Row 2 has 1 element

};

3. Accessing Elements:

System.out.println(raggedArray[1][2]); // Outputs: 5
19 | P a g e

Vectors
A Vector is a growable array-like data structure provided by Java's
java.util package. Unlike arrays, Vectors can dynamically resize as
elements are added. Vectors are synchronized, making them thread-
safe.

1. Declaration

Vector<Integer> vector = new Vector<>();

2. Adding Elements

vector.add(10);

vector.add(20);

3. Accessing Elements

System.out.println(vector.get(0)); // Outputs: 10
20 | P a g e

UNIT II:
21 | P a g e

Classes in Java
A class is a blueprint for creating objects. It defines fields (variables)
and methods (functions) that describe the behavior of an object.

Example:

class Car {

String model;

int speed;

void accelerate() {

speed += 10;

System.out.println("Speed: " + speed);

Here, Car is a class with attributes (model, speed) and behavior


(accelerate method).
22 | P a g e

Objects in Java
An object is an instance of a class. It has state (values of instance
variables) and behavior (methods).

Creating an Object:

Car myCar = new Car();

myCar.model = "Tesla";

myCar.accelerate();

Each object has its own copy of instance variables.

Relationships in Java
Java supports different types of class relationships:

1. Association – One class uses another.

2. Aggregation ("Has-a") – One class contains another.

class Engine { }

class Car {

Engine engine;

}
23 | P a g e

3. Composition – Strong aggregation where the contained object


cannot exist independently.

4. Inheritance ("Is-a") – One class derives from another.

class Vehicle { }

class Car extends Vehicle { }

Mutator & Accessor Methods


In object-oriented programming, fields of a class are often marked as
private to enforce encapsulation. To access and modify these private
fields, Java provides mutator (setter) and accessor (getter) methods.

1. Accessor Methods (Getters)

These methods return the values of private instance variables.

class Person {

private String name; // Private field

// Accessor method (getter)

public String getName() {

return name;

}
24 | P a g e

• The method getName() provides read access to the private


variable name.

2. Mutator Methods (Setters)

These methods modify the values of private instance variables.

class Person {

private String name;

// Mutator method (setter)

public void setName(String newName) {

name = newName;

• The method setName(String newName) allows controlled


modification of name.

Advantages:

1. Encapsulation – Prevents direct field access.

2. Validation – Ensures valid data is stored.

3. Flexibility – Internal implementation can change without affecting


external code.
25 | P a g e

Defining Our Own Classes in Java


A class in Java is defined using the class keyword. It contains fields,
constructors, and methods.

Example of a User-Defined Class:

class Student {

String name;

int age;

// Constructor

Student(String n, int a) {

name = n;

age = a;

// Method

void display() {

System.out.println("Name: " + name + ", Age: " + age);

}
26 | P a g e

Creating an object of the class:

public class Main {

public static void main(String[] args) {

Student s1 = new Student("John", 20);

s1.display();

Key Points:

1. Instance Variables: Store data for each object.

2. Methods: Define behaviors of the object.

3. Constructors: Initialize objects with default or specific values.


27 | P a g e

Using Multiple Source Files in Java


Java programs can be divided into multiple source files for better
organization and modular programming.

Example of Multiple Source Files:

File: Student.java (Class Definition)

class Student {

String name;

Student(String name) {

this.name = name;

void display() {

System.out.println("Student Name: " + name);

File: Main.java (Main Program)

public class Main {

public static void main(String[] args) {

Student s = new Student("Alice");


28 | P a g e

s.display();

Advantages of Using Multiple Files:

1. Code Organization: Each class has its own file.

2. Reusability: Classes can be reused in different projects.

3. Easy Maintenance: Code is easier to debug and modify.


29 | P a g e

var Keyword
The var keyword was introduced in Java 10 as part of local variable
type inference. It allows the compiler to determine the data type of a
variable at compile-time, reducing redundancy in variable declarations.
However, Java remains a statically-typed language, meaning that once
a variable's type is inferred, it cannot change.

Syntax of var

Instead of explicitly specifying the type, you can use var, and the
compiler will automatically infer the correct type.

Example : Using var in Local Variables

public class VarExample {

public static void main(String[] args) {

var message = "Hello, Java"; // Compiler infers it as String

var number = 100; // Compiler infers it as int

var decimal = 3.14; // Compiler infers it as double

System.out.println(message);

System.out.println(number);

System.out.println(decimal);

}}
30 | P a g e

The compiler analyzes the assigned value and infers its data type.

If var message = "Hello";, the compiler treats message as String.

If var number = 100;, the compiler treats number as int.

Once the type is inferred, it cannot be changed later in the program.

Advantages of var

1. Reduces Redundant Code – No need to explicitly declare types for


obvious assignments.

2. Improves Code Readability – Shorter, cleaner code while


maintaining strong typing.

3. Avoids Repetition – Particularly useful when working with


complex types.
31 | P a g e

Implicit & Explicit Parameters in Java


In Java, parameters are the values passed to a method when it is called.
Parameters can be classified into implicit parameters and explicit
parameters, depending on how they are accessed and used in a
method.

Implicit Parameters

An implicit parameter is an object reference that is automatically


passed to an instance method when it is called. The object that invokes
the method is the implicit parameter. In Java, the keyword this is used
to refer to the implicit parameter.

Example: Implicit Parameter (this keyword)

class Car {

String model;

void display() {

System.out.println("Car model: " + this.model); // 'this' refers to


the calling object

}
32 | P a g e

public class Main {

public static void main(String[] args) {

Car car1 = new Car();

car1.model = "Tesla";

car1.display(); // Here, 'car1' is the implicit parameter

• In display(), this.model refers to the current object calling the


method (car1 in this case).

• The method is automatically aware of which object it belongs to.

Explicit Parameters

An explicit parameter is a parameter explicitly passed to a method


when it is called. These are the values specified inside the method’s
parentheses.

Example: Explicit Parameters

class MathOperations {

int add(int a, int b) { // 'a' and 'b' are explicit parameters

return a + b;

}}
33 | P a g e

public class Main {

public static void main(String[] args) {

MathOperations obj = new MathOperations();

int result = obj.add(5, 10); // Explicitly passing parameters 5 and 10

System.out.println("Sum: " + result);

Explanation:

• a and b are explicitly passed to the add() method.

• The method does not rely on object context (unlike implicit


parameters).
34 | P a g e

Class-Based Access Privileges in Java


Access privileges determine the visibility and accessibility of classes,
methods, and variables. Java provides four access modifiers to enforce
encapsulation:

1. private – Accessible only within the same class.

2. (default) – Accessible within the same package (no modifier).

3. protected – Accessible within the same package and subclasses.

4. public – Accessible from anywhere in the program.

Example:

class Example {

private int privateVar = 10; // Only inside this class

int defaultVar = 20; // Accessible within the package

protected int protectedVar = 30; // Package + subclass access

public int publicVar = 40; // Accessible everywhere

Use private for data hiding (encapsulation). Use protected for


inheritance-based access.

Default (package-private) restricts access within the same package.

Use public for global access.

These access modifiers enhance security, maintainability, and


modularity in Java programs.
35 | P a g e

Private Methods
Private methods are only accessible within the same class.

class Demo {

private void display() {

System.out.println("Private Method");

Final Fields
A final field cannot be changed after initialization.

class Constants {

final int MAX = 100;

}
36 | P a g e

Static Fields and Methods


Static is a keyword used to define class-level members that belong to
the class itself rather than to specific instances (objects).

Static Fields (Class Variables)

• Shared by all objects of the class.

• Memory-efficient (stored once in memory).

• Accessed using the class name (e.g., ClassName.variable).

Example:

class Counter {

static int count = 0; // Shared by all instances

Counter() {

count++;

public class Main {

public static void main(String[] args) {

new Counter();

new Counter();
37 | P a g e

System.out.println(Counter.count); // Output: 2

Static Methods

Static methods can only access static fields and methods and cannot
use ‘this’ or ‘super’. They are called using the class name (e.g.,
ClassName.methodName()).

Example:

class MathUtils {

static int square(int x) {

return x * x;

public class Main {

public static void main(String[] args) {

System.out.println(MathUtils.square(5)); // Output: 25

}
38 | P a g e

The main Method


The main method is the entry point of any Java program. It is where
execution begins.

Syntax:

public class Main {

public static void main(String[] args) {

System.out.println("Hello, Java!");

Here,

• public means it is accessible from anywhere.

• Static means we don’t need to create an object to call it.

• void means it does not return any value.

• main is the method name recognized by the JVM.

• String[] args is Command-line arguments (optional input to the


program).

JVM looks for main(String[] args) to start execution.


static allows execution without object creation.
Can take command-line arguments (e.g., java Main Hello).
39 | P a g e

Method Parameters
Method parameters are inputs passed to a method to perform
operations. They allow methods to work with different values
dynamically.

Syntax:

void display(int num) { // 'num' is a parameter

System.out.println("Number: " + num);

Example:

class Demo {

void greet(String name) { // 'name' is a parameter

System.out.println("Hello, " + name);

public class Main {

public static void main(String[] args) {

Demo obj = new Demo();

obj.greet("Alice"); // Passing "Alice" as an argument

}}
40 | P a g e

Packages
A package in Java is a way to group related classes and interfaces to
organize code and avoid name conflicts.

Types of Packages:

1. Built-in Packages (e.g., java.util, java.io)

2. User-defined Packages (custom packages created by


programmers)

Creating a Package:

package mypackage; // Declaring a package

public class MyClass {

public void show() {

System.out.println("Hello from MyClass!");

}}

Using a Package:

import mypackage.MyClass; // Importing the package

public class Main {

public static void main(String[] args) {

MyClass obj = new MyClass();

obj.show();

}}
41 | P a g e

Object Construction
Object construction refers to the process of creating objects from a
class using a constructor. A constructor is a special method that
initializes an object when it is instantiated using the new keyword.

1. Default Constructor

If no constructor is defined, Java provides a default constructor that


initializes instance variables with default values (0 for integers, null for
objects, false for booleans).

Example:

class Car {

String model; // Default value is null

int year; // Default value is 0

void display() {

System.out.println("Model: " + model + ", Year: " + year);

public class Main {

public static void main(String[] args) {

Car c = new Car(); // Default constructor is called


42 | P a g e

c.display(); // Model: null, Year: 0

2. Parameterized Constructor

A constructor with parameters allows setting custom values during


object creation.

Example:

class Car {

String model;

int year;

// Parameterized Constructor

Car(String m, int y) {

model = m;

year = y;

void display() {

System.out.println("Model: " + model + ", Year: " + year);


43 | P a g e

public class Main {

public static void main(String[] args) {

Car c = new Car("Tesla", 2023); // Passing values to constructor

c.display(); // Model: Tesla, Year: 2023

3. Constructor Overloading

Java allows multiple constructors in the same class with different


parameter lists (overloading).

Example:

class Car {

String model;

int year;

// Default Constructor

Car() {
44 | P a g e

model = "Unknown";

year = 2000;

// Parameterized Constructor

Car(String m, int y) {

model = m;

year = y;

void display() {

System.out.println("Model: " + model + ", Year: " + year);

public class Main {

public static void main(String[] args) {

Car car1 = new Car(); // Calls default constructor

Car car2 = new Car("Ford", 2022); // Calls parameterized


constructor
45 | P a g e

car1.display(); // Model: Unknown, Year: 2000

car2.display(); // Model: Ford, Year: 2022

4. Calling Another Constructor (this())

A constructor can call another constructor in the same class using this().

Example:

class Car {

String model;

int year;

// Default Constructor

Car() {

this("Unknown", 2000); // Calls parameterized constructor

}
46 | P a g e

// Parameterized Constructor

Car(String model, int year) {

this.model = model;

this.year = year;

void display() {

System.out.println("Model: " + model + ", Year: " + year);

public class Main {

public static void main(String[] args) {

Car car1 = new Car(); // Calls default constructor

car1.display(); // Model: Unknown, Year: 2000

}
47 | P a g e

Object Destruction and the finalize() Method


Java has automatic garbage collection, meaning it does not require
explicitly destroying objects. However, the finalize() method can be
overridden to define cleanup operations before an object is garbage
collected.

Example:

class Demo {

protected void finalize() {

System.out.println("Object is being destroyed.");

public class Main {

public static void main(String[] args) {

Demo obj = new Demo();

obj = null; // Making object eligible for garbage collection

System.gc(); // Requesting garbage collection

}
48 | P a g e

UNIT III:
49 | P a g e

Classes, Superclasses, and Subclasses


A class in Java is a blueprint defining the properties (fields) and
behaviors (methods) for objects. A superclass is a general class from
which other classes inherit common attributes and methods, promoting
code reuse and logical hierarchy. A subclass extends the superclass
using the extends keyword, allowing it to inherit and, if needed,
override methods to provide specialized functionality. Inheritance
supports polymorphism, where a subclass object can be treated as an
instance of its superclass. This structure enhances modularity, making
programs easier to maintain and expand while adhering to object-
oriented design principles.
50 | P a g e

Defining Subclasses
Defining a subclass involves creating a new class that extends an
existing class (the superclass) using the extends keyword. This
mechanism allows the subclass to inherit fields and methods from the
superclass, promoting code reuse and logical organization. In a
subclass, you can add new methods and variables, or override inherited
methods to tailor behavior for the subclass. Overriding is achieved by
providing a new implementation for an inherited method. For example:

class Animal {

void makeSound() {

System.out.println("Some sound");

class Dog extends Animal {

void makeSound() {

System.out.println("Bark");

In this example, Dog is a subclass of Animal that redefines the


makeSound() method to provide its specific behavior.
51 | P a g e

Overriding Methods
Method overriding allows a subclass to provide a specific
implementation of a method already defined in its superclass. This
enables runtime polymorphism, meaning that the method call is
resolved at runtime based on the object's actual type. To override a
method, the subclass must define a method with the same name,
return type, and parameter list as the superclass method. Overriding is
applicable only to instance methods and does not work with static or
final methods.

Example:

class Animal {

void makeSound() {

System.out.println("Some generic sound");

class Dog extends Animal {

void makeSound() {

System.out.println("Bark");

}
52 | P a g e

Subclass Constructors
When a subclass is instantiated, its constructor is responsible for
initializing the subclass's fields and may also need to initialize fields
inherited from its superclass. To facilitate this, the subclass constructor
can invoke the superclass's constructor using the super() keyword. This
call must be the first statement in the subclass constructor. If the
subclass constructor does not explicitly call a superclass constructor,
Java automatically inserts a call to the superclass's no-argument
constructor. However, if the superclass does not have a no-argument
constructor, the subclass must explicitly call one of the superclass's
constructors using super() with appropriate arguments; otherwise, a
compilation error will occur.

Example:

class Animal {

String name;

// Superclass constructor

Animal(String name) {

this.name = name;

}
53 | P a g e

class Dog extends Animal {

String breed;

// Subclass constructor

Dog(String name, String breed) {

super(name); // Call to superclass constructor

this.breed = breed;

In this example, the Dog class extends the Animal class. The Dog
constructor calls the Animal constructor using super(name) to initialize
the name field inherited from Animal. This ensures that both the
inherited and subclass-specific fields are properly initialized.
54 | P a g e

Inheritance Hierarchies
Inheritance hierarchies represent the structured arrangement of classes
in a parent-child relationship where a general superclass is extended by
more specialized subclasses. This design pattern promotes code reuse,
organization, and clarity by centralizing common attributes and
methods in a superclass. Subclasses inherit these members while
adding their unique behaviors and properties, thus forming a hierarchy.
In hierarchical inheritance, multiple subclasses can extend the same
superclass, allowing them to share common functionality while
diverging in specialized implementations. Such hierarchies support
polymorphism, enabling objects of different subclasses to be treated
uniformly based on their shared superclass, which simplifies method
invocation and enhances maintainability.

Example:

// Superclass

class Vehicle {

void startEngine() {

System.out.println("Engine started.");

}}

// Subclass 1

class Car extends Vehicle {

void openTrunk() {

System.out.println("Trunk opened.");
55 | P a g e

}}

// Subclass 2

class Motorcycle extends Vehicle {

void popWheelie() {

System.out.println("Popping a wheelie!");

}}

public class Main {

public static void main(String[] args) {

Car myCar = new Car();

myCar.startEngine(); // Inherited method

myCar.openTrunk(); // Specific to Car

Motorcycle myBike = new Motorcycle();

myBike.startEngine(); // Inherited method

myBike.popWheelie(); // Specific to Motorcycle

}}
56 | P a g e

Polymorphism
Polymorphism, derived from the Greek for "many forms," is a
fundamental concept in Java and object-oriented programming that
allows objects to be treated as instances of their parent class rather
than their actual class. This capability enables a single interface to
represent different underlying data types, promoting flexibility and
integration in code design.

Types of Polymorphism in Java:

1. Compile-Time Polymorphism (Method Overloading):

o This form of polymorphism is resolved during the


compilation process. It occurs when multiple methods in the
same class share the same name but differ in their
parameter lists (i.e., the number or type of parameters). The
compiler determines which method to invoke based on the
method signature.

o Example:

class MathOperations {

// Method to add two integers

int add(int a, int b) {

return a + b;

// Overloaded method to add three integers


57 | P a g e

int add(int a, int b, int c) {

return a + b + c;

// Overloaded method to add two doubles

double add(double a, double b) {

return a + b;

o In this example, the add method is overloaded with different


parameter lists, allowing it to handle various types and
numbers of arguments.

2. Runtime Polymorphism (Method Overriding):

o This type of polymorphism is resolved during runtime. It


occurs when a subclass provides a specific implementation
for a method that is already defined in its superclass. The
method in the subclass should have the same name, return
type, and parameters as the method in the parent class. The
JVM determines at runtime which method implementation
to execute, based on the object being referenced.
58 | P a g e

o Example:

class Animal {

void makeSound() {

System.out.println("Some generic animal sound");

class Dog extends Animal {

void makeSound() {

System.out.println("Bark");

class Cat extends Animal {

void makeSound() {

System.out.println("Meow");

}
59 | P a g e

public class TestPolymorphism {

public static void main(String[] args) {

Animal myAnimal;

myAnimal = new Dog();

myAnimal.makeSound(); // Outputs: Bark

myAnimal = new Cat();

myAnimal.makeSound(); // Outputs: Meow

o In this scenario, the makeSound method is overridden in


both Dog and Cat subclasses. The actual method invoked is
determined at runtime based on the object type (Dog or
Cat), even though the reference type is Animal.
60 | P a g e

Preventing inheritance with Final


The final keyword is used to restrict the inheritance and modification
capabilities of classes, methods, and variables. When applied to a class,
final prevents other classes from inheriting from it, effectively sealing
the class against extension. This is particularly useful when creating
immutable classes or when you want to ensure that the
implementation of a class remains unchanged.

Declaring a Final Class:

public final class Constants {

// Class implementation

In this example, Constants is a final class, meaning no other class can


extend it. Attempting to do so will result in a compilation error.

Preventing Method Overriding with Final Methods:

The final keyword can also be applied to methods within a class to


prevent subclasses from overriding them.

public class BaseClass {

public final void display() {

System.out.println("This is a final method.");

}
61 | P a g e

public class DerivedClass extends BaseClass {

// Attempting to override the final method will cause a compilation


error

public void display() {

System.out.println("Trying to override.");

In this case, the display method in BaseClass is declared as final, so any


attempt to override it in DerivedClass will result in a compilation error.
62 | P a g e

Casting
Casting refers to converting a variable from one data type to another.
This is essential when working with different data types and classes,
especially in the context of inheritance and polymorphism. Java
supports two primary types of casting:

1. Primitive Type Casting:

o Widening Casting (Implicit): Automatically converts a


smaller primitive type to a larger one, such as int to double.
This process is safe and doesn't lead to data loss.

▪ Example: int myInt = 9; double myDouble = myInt;

o Narrowing Casting (Explicit): Manually converts a larger


primitive type to a smaller one, like double to int. This
requires explicit syntax and may result in data loss due to
truncation.

▪ Example: double myDouble = 9.78; int myInt = (int)


myDouble;

2. Reference Type Casting:

o Upcasting: Converts a subclass type to a superclass type.


This is implicit and safe, allowing a subclass object to be
treated as an instance of its superclass.

▪ Example: Animal animal = new Dog();

o Downcasting: Converts a superclass type to a subclass type.


This requires explicit casting and can lead to a
ClassCastException if not done correctly. It's essential to use
63 | P a g e

the instanceof operator to check the actual object type


before downcasting.

▪ Example: if (animal instanceof Dog) { Dog dog = (Dog)


animal; }

Understanding casting is crucial for effective Java programming, as it


ensures that variables are correctly interpreted and manipulated within
the type system.
64 | P a g e

Abstract Classes
An abstract class serves as a blueprint for other classes, allowing
developers to define methods that must be implemented by
subclasses. Abstract classes cannot be instantiated directly; instead,
they provide a common structure for related classes.

Key Features:

• Abstract Methods: These are methods declared without an


implementation in the abstract class. Subclasses are required to
provide concrete implementations for these methods.

• Concrete Methods: Abstract classes can also include methods


with implementations, which can be inherited by subclasses.

• Constructors: While abstract classes cannot be instantiated, they


can have constructors that are called when a subclass is
instantiated.

• Fields: Abstract classes can contain member variables, which can


be inherited and utilized by subclasses.

Example:

abstract class Vehicle {

abstract void start(); // Abstract method

void stop() {

System.out.println("Vehicle stopped."); // Concrete method


65 | P a g e

class Car extends Vehicle {

void start() {

System.out.println("Car started.");

public class Main {

public static void main(String[] args) {

Vehicle myCar = new Car();

myCar.start(); // Outputs: Car started.

myCar.stop(); // Outputs: Vehicle stopped.

In this example, Vehicle is an abstract class with an abstract method


start() and a concrete method stop(). The Car class extends Vehicle and
provides an implementation for the start() method.
66 | P a g e

The object superclass and its variables


The Object class, located in the java.lang package, is the root of the
class hierarchy. Every class in Java implicitly extends Object, either
directly or indirectly. This means that all classes inherit the methods
defined in Object.

Variables of the Object Class:

• public boolean equals(Object obj): Determines whether another


object is "equal to" this one.

• protected void finalize(): Called by the garbage collector before


the object is reclaimed.

• public final Class<?> getClass(): Returns the runtime class of the


object.

• public int hashCode(): Returns a hash code value for the object.

• public String toString(): Returns a string representation of the


object.

• public final void notify(): Wakes up a single thread waiting on this


object's monitor.

• public final void notifyAll(): Wakes up all threads waiting on this


object's monitor.

• public final void wait(): Causes the current thread to wait until
another thread invokes the notify() method or the notifyAll()
method for this object.
67 | P a g e

equals() Method:

String equals() method in Java compares the content of two


strings. It compares the value's character by character,
irrespective of whether two strings are stored in the same
memory location. The String equals() method overrides the
equals() method of the object class.

• false if any of the characters are not matched.

• true if all characters are matched in the Strings.

class EqualsMethod

public static void main(String[] args)

String str1 = "Learn Java";

String str2 = "Learn Java";

String str3 = "Learn Kotlin";

boolean result;

// Comparing str1 with str2

result = str1.equals(str2);

System.out.println(result);
68 | P a g e

// Comparing str1 with str3

result = str1.equals(str3);

System.out.println(result);

// Comparing str3 with str1

result = str3.equals(str1);

System.out.println(result);

Output

true

false

false
69 | P a g e

hashCode() Method:

Hashcode is a unique code generated by the JVM at time of object


creation. It can be used to perform some operation on hashing
related algorithms like hashtable, hashmap etc. An object can also
be searched with this unique code.

Syntax:

public int hashCode()

Returns: It returns an integer value which represents hashCode


value for this Method.

toString() Method:

The ‘toString()’ method is used to get the string representation of


an object. Whenever we try to print the object reference then
internally toString() method is invoked. If we did not define the
toString() method in your class then the Object class toString()
method is invoked otherwise our implemented or overridden
toString() method will be called.

Syntax:

public String toString() {

return
getClass().getName()+"@"+Integer.toHexString(hashCode());

}
70 | P a g e

Equality Testing and Inheritance:

When dealing with inheritance, it's crucial to override equals(),


hashCode(), and toString() methods in the subclass to ensure they
correctly reflect the subclass's state and behavior. Failure to do so
can lead to unexpected behavior, especially when objects are
stored in collections or compared.
71 | P a g e

Generic Array Lists


ArrayList is a part of the Java Collections Framework and provides a way
to manage a dynamic array that can grow and shrink as needed. Unlike
arrays, ArrayList can dynamically adjust its size as elements are added
or removed. Using generics with ArrayList ensures that only elements
of the specified type can be added, preventing runtime
ClassCastException.

Creating a Generic ArrayList:

To create a generic ArrayList, specify the type of elements it will hold


within angle brackets (<>). This ensures type safety, allowing only
elements of the specified type to be added to the list.

ArrayList<String> stringList = new ArrayList<>();

stringList.add("Hello");

stringList.add("World");

In this example, stringList is an ArrayList that can only contain String


objects. Attempting to add an element of a different type will result in a
compile-time error.

Example:

import java.util.ArrayList;

public class GenericArrayListExample {

public static void main(String[] args) {


72 | P a g e

// Create a generic ArrayList to hold Integer elements

ArrayList<Integer> numbers = new ArrayList<>();

// Add elements to the ArrayList

numbers.add(10);

numbers.add(20);

numbers.add(30);

// Access elements

System.out.println("First number: " + numbers.get(0));

// Iterate over the ArrayList

for (Integer number : numbers) {

System.out.println(number);

}
73 | P a g e

Object Wrappers and Autoboxing


A Wrapper class in Java is one whose object wraps or contains primitive
data types. When we create an object to a wrapper class, it contains a
field, and in this field, we can store primitive data types.

The wrapper classes are:

• Byte for byte

• Short for short

• Integer for int

• Long for long

• Float for float

• Double for double

• Character for char

• Boolean for Boolean

Autoboxing and Unboxing:

Java provides autoboxing and unboxing to automatically convert


between primitive types and their corresponding wrapper classes:

• Autoboxing: The automatic conversion of a primitive type to its


corresponding wrapper class. For example, converting an int to an
Integer.
74 | P a g e

• Unboxing: The automatic conversion of a wrapper class to its


corresponding primitive type. For example, converting an Integer
to an int.

These conversions are handled by the Java compiler, allowing for more
concise and readable code.

Example:

public class AutoboxingExample {

public static void main(String[] args) {

// Autoboxing: converting primitive to wrapper class

int primitiveInt = 10;

Integer wrapperInteger = primitiveInt; // Autoboxing

// Unboxing: converting wrapper class to primitive

Integer anotherWrapperInteger = 20;

int anotherPrimitiveInt = anotherWrapperInteger; // Unboxing

In this example, primitiveInt is automatically converted to


wrapperInteger (autoboxing), and anotherWrapperInteger is
automatically converted to anotherPrimitiveInt (unboxing).
75 | P a g e

Methods with variable number of parameters


Variable Arguments (Varargs) is a method that takes a variable number
of arguments. Variable Arguments in Java simplify the creation of
methods that need to take a variable number of arguments.

Syntax:

To declare a method with varargs, use an ellipsis (...) followed by the


type of the parameters:

public void methodName(Type... parameters) {

// method body

Here, “Type” is the data type of the parameters, and “parameters” is


treated as an array within the method.

Example:

class VarargsExample {

// Method that accepts variable number

// of String arguments using varargs

public static void Names(String... n) {

// Iterate through the array

// and print each name


76 | P a g e

for (String i : n) {

System.out.print(i + " ");

System.out.println();

public static void main(String[] args) {

// Calling the 'Names' method with

// different number of arguments

Names("name1", "name2");

Names("name1", "name2", "name3");

Output

name1 name2

name1 name2 name3


77 | P a g e

UNIT IV:
78 | P a g e

Interfaces: Defining
An interface is a blueprint of a class. It has static constants and abstract
methods.

The interface is a mechanism to achieve abstraction. There can be only


abstract methods in the Java interface, not method body. It is used to
achieve abstraction and multiple inheritance in Java.

In other words, we can say that interfaces can have abstract methods
and variables. It cannot have a method body.

Java Interface also represents the IS-A relationship, and it cannot be


instantiated just like the abstract class.

Syntax:

interface <interface_name>{

// declare constant fields

// declare methods that abstract

// by default.

Example:

interface Animal {

void eat();

void sleep();

}
79 | P a g e

In this example, the Animal interface declares two method signatures:


eat() and sleep(). Any class implementing the Animal interface must
provide concrete implementations for these methods.

Difference with abstract classes


In object-oriented programming (OOP), both abstract classes and
interfaces serve as fundamental constructs for defining contracts. They
establish a blueprint for other classes, ensuring consistent
implementation of methods and behaviors. However, they each come
with distinct characteristics and use cases.

Abstract Class Interface

Cannot be instantiated;
Specifies a set of
contains both abstract
methods a class must
(without implementation)
80 | P a g e

Abstract Class Interface

and concrete methods implement; methods are


(with implementation) abstract by default.

Methods are abstract by


Can have both
default; Java 8, can have
implemented and abstract
default and static
methods.
methods.

class can inherit from only A class can implement


one abstract class. multiple interfaces.

Methods and properties


can have any access Methods and properties
modifier (public, are implicitly public.
protected, private).

Can have member Variables are implicitly


variables (final, non-final, public, static, and final
static, non-static). (constants).
81 | P a g e

Static and private methods


Static and private methods in interfaces were introduced in Java 8 and
Java 9 respectively.

Static Methods:

• Static methods in interfaces are methods that belong to the


interface itself, not to any instance of the interface.

• They are defined using the static keyword.

• We can call them directly on the interface, without the need to


create an object of a class that implements the interface.

• They are useful for providing utility methods that are related to
the interface.

Example:

interface Calculator {
static int add(int a, int b) {
return a + b;
}
}

public class Main {


public static void main(String[] args) {
int result = Calculator.add(2, 3); // Call static method directly on the
interface
System.out.println(result); // Output: 5
}
}
82 | P a g e

Private Methods:

• Private methods in interfaces were introduced in Java 9 to provide


a way to encapsulate helper code that is not part of the public API
of the interface.

• They are defined using the private keyword.

• They can only be accessed from within the interface, not from
implementing classes.

• They are useful for breaking down complex default methods into
smaller, more manageable methods.

Example:

interface MyInterface {
default void doSomething() {
stepOne();
stepTwo();
}

private void stepOne() {


System.out.println("Performing step one");
}

private void stepTwo() {


System.out.println("Performing step two");
}
}
83 | P a g e

Default methods
Before Java 8, interfaces could only have abstract methods. The
implementation of these methods has to be provided in a separate
class. So, if a new method is to be added in an interface, then its
implementation code has to be provided in the class implementing the
same interface. To overcome this issue, Java 8 has introduced the
concept of default methods which allow the interfaces to have
methods with implementation without affecting the classes that
implement the interface.

Example:

interface TestInterface

// abstract method

public void square(int a);

// default method

default void show()

System.out.println("Default Method Executed");

}
84 | P a g e

class TestClass implements TestInterface

// implementation of square abstract method

public void square(int a)

System.out.println(a*a);

public static void main(String args[])

TestClass d = new TestClass();

d.square(4);

// default method executed

d.show();

Output:

16

Default Method Executed


85 | P a g e

Default method conflicts


In Java, default method conflicts occur when a class implements
multiple interfaces that contain default methods with the same
signature. This can lead to a compile-time error.

Causes:

• Multiple inheritance

Java doesn't support multiple inheritance, so when a class implements


multiple interfaces, it can lead to conflicts.

• Ambiguous default methods

When a class implements multiple interfaces with default methods that


have the same name and parameter types, the compiler can't decide
which method to inherit.

Solutions:

• Override the default method

• Use the super keyword

• Define a new method


86 | P a g e

The Comparator Interface


The `Comparator` interface in Java is used to define custom sorting
logic for objects. It is part of the `java.util` package and contains the
`compare(T o1, T o2)` method, which returns a negative, zero, or
positive value based on the comparison. Unlike `Comparable`, which
defines natural ordering, `Comparator` allows multiple sorting criteria
without modifying the class. It is commonly used with collections like
`List` and `TreeSet`. From Java 8, it supports lambda expressions and
utility methods like `Comparator.comparing()` for easier
implementation.

Example:

import java.util.*;

public class ComparatorExample {

public static void main(String[] args) {

List<Integer> numbers = Arrays.asList(5, 2, 8, 1, 9);

// Using Comparator to sort in descending order

Comparator<Integer> descendingComparator = (a, b) -> b - a;

// Sorting the list

numbers.sort(descendingComparator);

System.out.println(numbers); // Output: [9, 8, 5, 2, 1]

}}
87 | P a g e

Object Cloning in Java


Object cloning is the process of creating an exact copy of an object. It is
achieved using the clone() method from the Object class. For a class to
support cloning, it must implement the Cloneable interface; otherwise,
a CloneNotSupportedException is thrown. By default, clone() performs
a shallow copy , copying field values but not creating new instances of
referenced objects. For a deep copy , the referenced objects must also
be cloned explicitly. Cloning is useful for creating duplicates without
manually copying each field. However, it should be used cautiously as it
can lead to unexpected behavior if not implemented properly.

Example:

class Student implements Cloneable {

String name;

int age;

public Student(String name, int age) {

this.name = name;

this.age = age;

@Override

protected Object clone() throws CloneNotSupportedException {


88 | P a g e

return super.clone();

public class Test {

public static void main(String[] args) throws


CloneNotSupportedException {

Student s1 = new Student("Alice", 20);

Student s2 = (Student) s1.clone();

System.out.println(s2.name); // Output: Alice

}
89 | P a g e

Lambda expressions
Lambda expressions, introduced in Java 8, provide a concise way to
represent anonymous functions (methods without a name). They are
used to implement functional interfaces —interfaces with a single
abstract method (SAM). Lambda expressions improve code readability
and reduce boilerplate code by eliminating the need for anonymous
inner classes.

Key Features:

1. Syntax :
(parameters) -> expression or
(parameters) -> { statements; }

2. No need to declare parameter types if they can be inferred.

3. Can access final or effectively final variables from the enclosing


scope.

4. Used with functional interfaces like Runnable, Comparator, etc.

Example:

// Using a lambda expression to calculate the square of a number

interface MathOperation {

int operate(int a);

}
90 | P a g e

public class LambdaExample {

public static void main(String[] args) {

// Lambda expression to define the behavior of the 'operate'


method

MathOperation square = (int a) -> a * a;

// Calling the lambda function

System.out.println("Square of 5: " + square.operate(5)); // Output:


Square of 5: 25

Explanation

• The MathOperation interface has a single abstract method


operate(int a).

• Instead of creating a class or anonymous inner class, we use a


lambda expression (int a) -> a * a to implement the method.

• The lambda expression takes an integer a and returns its square (a


* a).

• The result is printed using the operate() method.


91 | P a g e

Exception Handling:
Exception handling is a mechanism to handle runtime errors, ensuring
normal program flow. Exceptions are classified into Checked Exceptions
(compile-time), Unchecked Exceptions (runtime, e.g.,
`NullPointerException`), and Errors (serious issues like
`OutOfMemoryError`). It uses `try-catch`, `throw`, and `finally` for
effective error management.

Classification of Exceptions

Exceptions in Java are classified into three main categories:

a. Checked Exceptions

• These are exceptions that are checked at compile-time.

• They must either be handled using a try-catch block or declared


using the throws keyword.

• Examples: IOException, SQLException.

b. Unchecked Exceptions

• These are exceptions that occur at runtime and are not checked at
compile-time.

• They include RuntimeException and its subclasses.

• Examples: NullPointerException,
ArrayIndexOutOfBoundsException.
92 | P a g e

c. Errors

• These represent serious problems that applications should not try


to handle.

• Examples: OutOfMemoryError, StackOverflowError.


93 | P a g e

Declaring Checked Exceptions


When a method can throw a checked exception, it must declare it using
the throws keyword in its method signature. This informs the caller
that the method might throw an exception, and they must handle it.
For example, if a method reads a file, it may throw an IOException, so it
must declare it:

public void readFile(String fileName) throws IOException {

FileReader file = new FileReader(fileName); // May throw


IOException

}public void readFile(String fileName) throws IOException {

FileReader file = new FileReader(fileName); // May throw


IOException

If the caller doesn’t handle the exception, the compiler will throw an
error. Declaring checked exceptions ensures that potential issues are
acknowledged and managed. It forces developers to think about error
scenarios and handle them appropriately, improving code reliability.
94 | P a g e

Throwing an Exception
Throwing an exception means explicitly raising an exception in the
program using the throw keyword. This is useful when you detect an
error condition and want to signal it to the caller. For example:

if (age < 18) {

throw new ArithmeticException("Not eligible for voting");

if (age < 18) {

throw new ArithmeticException("Not eligible for voting");

Here, if the age is less than 18, an ArithmeticException is thrown with a


custom message. The throw statement interrupts the normal flow of
execution and transfers control to the nearest catch block. You can
throw predefined exceptions (like NullPointerException) or create
custom exceptions. Throwing exceptions allows developers to handle
unexpected conditions gracefully.
95 | P a g e

Creating Exception Classes


We can create custom exception classes by extending the Exception
class (for checked exceptions) or RuntimeException (for unchecked
exceptions). Custom exceptions allow you to handle application-specific
errors. Here’s how to create one:

class InvalidAgeException extends Exception {

public InvalidAgeException(String message) {

super(message);

}}

public class TestCustomException {

public static void main(String[] args) {

try {

validateAge(15);

} catch (InvalidAgeException e) {

System.out.println(e.getMessage());

}}

static void validateAge(int age) throws InvalidAgeException {

if (age < 18) {

throw new InvalidAgeException("Invalid Age: " + age);

}}}
96 | P a g e

Catching Exceptions
Catching exceptions involves using a try-catch block to handle runtime
errors gracefully. The try block contains code that may throw an
exception, and the catch block handles the exception if it occurs. For
example:

try {

int result = 10 / 0; // May throw ArithmeticException

} catch (ArithmeticException e) {

System.out.println("Cannot divide by zero: " + e.getMessage());

We can also use multiple catch blocks to handle different exceptions:

try {

int[] arr = new int[5];

arr[10] = 50; // May throw ArrayIndexOutOfBoundsException

} catch (ArrayIndexOutOfBoundsException e) {

System.out.println("Array index out of bounds");

} catch (Exception e) {

System.out.println("Some other exception occurred");

}
97 | P a g e

Rethrowing Exceptions
Rethrowing an exception means catching an exception and then
throwing it again to propagate it further up the call stack. This is useful
when you want to log or process an exception but still allow higher-
level methods to handle it. Example:

try {

throw new IOException("File not found");

} catch (IOException e) {

System.out.println("Caught exception: " + e.getMessage());

throw e; // Rethrow the same exception

}
98 | P a g e

Finally Block
The finally block is used to execute important cleanup code, such as
closing files or releasing resources, regardless of whether an exception
occurs or not. It is always executed after the try block and any
associated catch blocks. Example:

try {

int result = 10 / 0;

} catch (ArithmeticException e) {

System.out.println("Exception caught");

} finally {

System.out.println("Finally block executed");

}
99 | P a g e

Try-With-Resources
Introduced in Java 7, try-with-resources ensures that resources (like
files, sockets, etc.) are closed automatically after use. Resources must
implement the AutoCloseable interface. Example:

try (FileReader file = new FileReader("test.txt")) {

int i;

while ((i = file.read()) != -1) {

System.out.print((char) i);

} catch (IOException e) {

System.out.println("Error reading file: " + e.getMessage());

}
100 | P a g e

Analyzing Stack Trace


A stack trace provides detailed information about the sequence of
method calls that led to an exception. It helps developers debug and
identify the root cause of errors. You can print the stack trace using the
printStackTrace() method:

try {

int result = 10 / 0;

} catch (ArithmeticException e) {

e.printStackTrace();

Output:

java.lang.ArithmeticException: / by zero

at Example.main(Example.java:5)
101 | P a g e

Introduction to Multithreading
Multithreading is a programming concept that allows a single process
to execute multiple threads concurrently. It allows concurrent
execution of tasks within a single process, improving performance and
responsiveness. In Java, threads can be created by extending the
Thread class or implementing the Runnable interface. Proper
synchronization is essential to avoid race conditions and ensure thread
safety. While multithreading offers significant benefits, it also
introduces challenges like deadlocks and debugging complexity.

A process is an independent program with its own memory space.

A thread is a lightweight sub-process that shares the same memory


space as other threads within the same process.

Creating Threads in Java


In Java, threads can be created in two ways:

1. Extending the Thread Class

class MyThread extends Thread {

public void run() {

System.out.println("Thread is running");

}
102 | P a g e

public class Main {

public static void main(String[] args) {

MyThread t1 = new MyThread();

t1.start(); // Starts the thread

2. Implementing the Runnable Interface

class MyRunnable implements Runnable {

public void run() {

System.out.println("Thread is running");

}}

public class Main {

public static void main(String[] args) {

Thread t1 = new Thread(new MyRunnable());

t1.start(); // Starts the thread

}
103 | P a g e

Advantages of Multithreading

• Improves application performance by utilizing multiple CPU cores.

• Enhances responsiveness in GUI-based applications.

• Simplifies task division and execution.


104 | P a g e

Basics of File I/O


File Input/Output (I/O) in Java refers to reading data from and writing
data to files. It is essential for handling persistent data storage and
retrieval. Java provides the java.io package, which includes classes and
interfaces to perform file operations efficiently.

Key Concepts:

1. Streams:

• A stream is a flow of data between a source (e.g., file,


keyboard) and a destination (e.g., file, console).

• Input Stream : Reads data from a source.

• Output Stream : Writes data to a destination.

2. Types of Streams :

• Byte Streams : Handle binary data (InputStream,


OutputStream).

• Example: Reading/writing images, audio files.

• Character Streams : Handle text data (Reader, Writer).

• Example: Reading/writing plain text files.

3. Common Classes :

• FileReader/FileWriter : For reading/writing character data.


105 | P a g e

• BufferedReader/BufferedWriter : Adds buffering for


efficient reading/writing.

• FileInputStream/FileOutputStream : For reading/writing


binary data.

• PrintWriter : For writing formatted text.

4. File Operations :

• Reading : Use FileReader or BufferedReader to read text


files line by line.

• Writing : Use FileWriter or BufferedWriter to write text data


to files.

• Appending : Open a file in append mode using


FileWriter("filename", true) to add data without
overwriting existing content.

• Binary Data : Use FileInputStream and FileOutputStream


for binary file operations.

5. Try-With-Resources :

• Introduced in Java 7, this ensures automatic closing of


resources like files after use, reducing the risk of resource
leaks.

6. Error Handling :

File I/O operations may throw IOException, which must be


handled using try-catch blocks.
106 | P a g e

Reading and writing to Files

Reading from a file


import java.io.*;

public class ReadFileExample {

public static void main(String[] args) {

try (BufferedReader br = new BufferedReader(new


FileReader("input.txt"))) {

String line;

while ((line = br.readLine()) != null) { // Reads line by line

System.out.println(line);

} catch (IOException e) {

System.out.println("Error reading file: " + e.getMessage());

}
107 | P a g e

Writing to a file
import java.io.*;

public class WriteFileExample {

public static void main(String[] args) {

try (BufferedWriter bw = new BufferedWriter(new


FileWriter("output.txt"))) {

bw.write("Hello, World!"); // Writes text to the file

bw.newLine(); // Adds a new line

bw.write("This is a test.");

} catch (IOException e) {

System.out.println("Error writing to file: " + e.getMessage());

}
108 | P a g e

This is the end


Baaki exam mai jo mere pass bethe ga/ bethe gi wo mujhe dikhana kue ki sara
time notes banane mai lag gya, padhne ka time he nhi mila
See you in 6th semester

Do not click here

Neither here

Nor here

You might also like