KEMBAR78
OOPS Through JAVA - Unit3 | PDF | Integer (Computer Science) | Variable (Computer Science)
0% found this document useful (0 votes)
41 views172 pages

OOPS Through JAVA - Unit3

Uploaded by

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

OOPS Through JAVA - Unit3

Uploaded by

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

Unit 3

Arrays, Inheritance & Interfaces

BYTEXL
1. Introduction to Arrays
Definition:

✓ Arrays in Java are a fundamental data structure that allow you to store multiple values of the same
type in a single variable.
✓ They are particularly useful when you need to manage collections of data, such as a list of numbers,
names, or objects, without having to declare separate variables for each individual element.

Key Characteristics of Arrays:

1. Fixed Size: Once an array is created, its size is fixed and cannot be changed. This means you must know
the number of elements you need in advance.
2. Homogeneous Elements: All elements in an array must be of the same data type (e.g., int[] for integers,
String[] for strings).
3. Zero-based Indexing: In Java, array indexing starts at 0. The first element of an array is accessed via index
0, the second element via index 1, and so on.
4. Direct Memory Access: Arrays provide fast access to elements since each element can be directly
accessed using its index.

Real-time examples of Arrays:

A row of books: Books are arranged in an order and can be accessible with the position.
Display of items in shopping sites: Shows products in grid can be an example of 2D arrays.
PU Gamer/Chess board: The board can be represented by a 2D array, where each index pair corresponds
to a specific position on the board for game pieces.
A shopping list: A list of items in a single column can be referred with the serial numbers is an example of
1D array

Why Use Arrays?


• Efficient Data Storage: Arrays allow storing multiple values using a single variable, making your code more
organized.
• Efficient Access: Indexes make it easy to access, update, or manipulate any element within an array.
• Memory Management: Arrays are stored in contiguous memory locations, making them efficient in terms
of memory usage.

If you need to store 50 integer values, you can create an array that can hold all 50 integers at once. Instead of
declaring separate variables like a1, a2, …, a49, you can declare a single array that contains all 50 values. The
values in the array can then be accessed using indices such as a[0], a[1], …, a[49].
For example, if you need to store marks of 10 students, we don’t need to declare 10 variables. Instead you can
declare an array that can hold int-type values.
Programming Example:
Suppose you are developing an attendance tracking system. Instead of declaring individual variables for
each student’s attendance, you can use an array to store attendance data for all students.

For example:
int[] marks = new int[10]; // Array to store marks of 10 students

In this case, you have declared an array that can store marks for 10 students. Each student's marks can be
accessed or updated using their index in the array.

Types of Arrays in Java :


There are three main types of arrays in Java, which are used according to the program’s requirements.
These are:

1. One-dimensional Array (1D Array)


A one-dimensional array, also known as a linear array, stores elements in a single row. It is a
simple list of elements stored in adjacent memory locations, where each element can be accessed using a
single index.

Example: int[] array = {1, 2, 3, 4, 5};

In this example, the array contains five elements: 1, 2, 3, 4, 5. The elements are stored in a single row and
can be accessed using indices like array[0] for the first element, array[1] for the second, and so on.

Visualization:
[1, 2, 3, 4, 5]

In Java, you can use a for loop to iterate through the array and print each element. For example:

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


System.out.println(array[i]);
}
This loop will print:
1
2
3
4
5

2. Two-dimensional Array (2D Array)

A two-dimensional array stores data in rows and columns, similar to a table or matrix. Each element is
accessed using two indices: one for the row and one for the column.

Example: int[][] array = { {1, 2, 3}, {4, 5, 6} };

This array has two rows and three columns. You can access each element using two indices, like
array[0][0] for

the element in the first row and first column (1), or array[1][2] for the element in the second row and
third column (6).

Visualization:
[1, 2, 3]

[4, 5, 6]
To print all the elements of a 2D array, you can use nested for loops:
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + " ");
}
System.out.println(); // Move to the next line after each row
}
The output will be:
123
456

3. Multi-dimensional Array
A multi-dimensional array has more than two dimensions, such as 3D or 4D arrays. It can store data in
multiple layers, accessing each element using multiple indices.
Example: int[][][] array = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};
This is a 3D array with two layers, each containing two rows and two columns. You can access elements
using three indices, like array[0][0][1] for the second element in the first row of the first layer (2), or
array[1][1][0] for the first element in the second row of the second layer (7).
Visualization:
Layer 1:
[1, 2]
[3, 4]
Layer 2:
[5, 6]
[7, 8]
Despite having multiple dimensions, you can still use nested loops to access elements, but the number
of loops typically remains two for rows and columns, regardless of the array's dimensionality.
Summary
• One-dimensional arrays store elements in a single row (linear structure).
• Two-dimensional arrays store elements in rows and columns (table or matrix-like structure).
• Multi-dimensional arrays store elements in more than two dimensions (e.g., 3D structures with layers).
These arrays are used depending on the complexity and structure of the data you need to store and
manipulate.

Single (One-Dimensional) Arrays:

1. Declaration of Arrays
In Java, an array must first be declared before it can be used. The declaration defines the data type of
the elements that the array will hold and the array's name. However, declaring an array does not allocate
memory for its elements; it simply creates a reference to the array.
Syntax:
dataType[] arrayName; (or) dataType arrayName[];
Both syntaxes are valid, but the first is more commonly used.
Example:
int[] num; // Declares an array of integers
String[] names; // Declares an array of strings
At this point, the array is declared but has no memory allocated for its elements.

2. Initialization of Arrays
After declaring an array, you need to allocate memory and assign values to its elements. There are two
common ways to initialize an array in Java:
a. Using new Keyword
You can initialize an array by specifying the size (number of elements) using the new keyword. This
allocates memory for the specified number of elements.
Syntax:
arrayName = new dataType[size];

num = new int[10]; // Allocates memory for 10 integers


Now, memory is allocated for 5 integers, and each element in the array is automatically initialized to the
default value (0 for integers).
You can combine declaration and initialization in one line:
int[] numbers = new int[5]; // Declares and allocates memory for an array of 5 integers

b. Initializing with Values Directly


You can also initialize the array with specific values at the time of declaration without specifying the size, as
the size is inferred from the number of values provided.

Syntax:
dataType[] arrayName = {value1, value2, value3, ...};

int[] numbers = {10, 20, 30, 40, 50}; // Initializes an array with 5 elements

This creates an array of size 5 and assigns the values 10, 20, 30, 40, and 50 to the respective elements.

3. Accessing Array Elements

Once initialized, you can access or modify the elements of an array using their index. Remember,
array indices in Java start from 0.

Example:
numbers[0] = 100; // Changes the first element to 100

int first = numbers[0]; // Retrieves the first element


Summary:

• Declaration: Defines the array’s data type and name.

• This creates an array of size 5 and assigns the values 10, 20, 30, 40, and 50 to the respective elements.

• Initialization: Allocates memory and assigns values to the array.

You can initialize an array using the new keyword or directly with a set of values.
Do It Yourself

1. Write a Java program to declare an array of char with the size of 5. Initialize the array with the characters
'a', 'e', 'i', 'o', 'u'. Then, print out each element in reverse order using a loop.

2. Write a Java program to declare an array of float with a size of 10. Initialize the array with values from
1.1 to 10.1 (inclusive)

3. Declare and initialize a string array named fruits with the values "Apple", "Banana", "Mango", "Orange".

4. What is the difference between declaring an array as int[] arr; and int arr[]; in Java? Which one is
preferred and why?

Quiz

1. What is the correct way to declare a one-dimensional array of integers in Java?

a) int array[10];
b) int[] array = new int(10);

c) int[] array = new int[10];

d) int array[] = 10;

Answer: c) int[] array = new int[10];

2. Consider the following code:


int[] numbers = {10, 20, 30, 40, 50};
System.out.println(numbers[2]);
What will be the output of the program?

a) 10
b) 20
c) 30
d) ArrayIndexOutOfBoundsException

Answer: c) 30
3. Identify the bug in the following code:

int[] arr = new int[5];

arr[5] = 25;

System.out.println(arr[5]);

a) The array is not initialized.

b) The index 5 is out of bounds.

c) The size of the array is wrong.

d) The code is correct.

Answer: b) The index 5 is out of bounds.

4. Complete the following code to initialize the array correctly:

int[] ages = ___ {21, 25, 30, 35, 40};

a) new

b) new int

c) new[]

d) None of the above

Answer: b) new int

5. What is the default value of elements in an uninitialized int array in Java?

a) 1

b) -1

c) 0

d) null

Answer: c) 0

6. What will be the output of the following code?


int[] numbers = new int[3];

numbers[0] = 10;

System.out.println(numbers[1]);
a) 0

b) 10

c) null

d) ArrayIndexOutOfBoundsException

Answer: a) 0

Storage of Array in Computer Memory


Arrays are one of the fundamental data structures used to store collections of elements. In Java, arrays are
stored in a specific way in memory to ensure efficiency and fast access. Let's explore how arrays are stored in
memory, focusing on the following aspects:

1. Contiguous Memory Allocation


When an array is created in Java, the elements are stored in contiguous memory locations. This
means that the array elements are placed one after the other in a continuous block of memory. The
size of the block allocated depends on two factors:

• The number of elements in the array.

• The size of each element, which is determined by the data type (e.g., int, char, double).

For instance, if you declare an array of 5 integers:

int[] arr = new int[5];

Each int element in Java takes up 4 bytes of memory. Therefore, this array will occupy 5 * 4 = 20
bytes of memory in a contiguous block.

Visualization of memory layout for an array like:

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


Each element is placed sequentially, with the next element's address being calculated by adding the
size of one element (in this case, 4 bytes) to the previous address.

2. Heap and Stack Memory Allocation

Java uses heap memory to store objects, and since arrays are considered objects in Java, the array
elements are stored in the heap. However, the reference (or pointer) to the array is stored in stack
memory, which holds local variables and method call references.

• Stack Memory: Contains the reference (or pointer) to the array object.

• Heap Memory: Contains the actual array elements.

For example:

int[] numbers = new int[5];

• The reference to numbers is stored in stack memory.

• The array elements (5 integers in this case) are stored in heap memory.

3. Index-based Access

In Java, arrays are zero-indexed, meaning the first element is at index 0. The contiguous memory
allocation makes it possible to access any element directly using its index. The address of any element
in the array can be calculated using the following formula:

Memory Address of element i = Base Address + (i * Size of each element)

Here:

• Base Address is the memory address of the first element.

• i is the index of the element.

• Size of each element is the size (in bytes) of the data type.

For example, in an integer array:


int[] numbers = {5, 10, 15, 20};

The memory address of numbers[2] would be calculated as:


Base Address + (2 * 4), since each int is 4 bytes.

4. Memory Efficiency and Access Speed

Due to the contiguous layout of arrays in memory, accessing elements is extremely efficient. The time
complexity of accessing an array element by index is O(1), meaning it takes constant time. This is one
of the key reasons why arrays are favored for scenarios requiring fast, direct access to elements.

The contiguous memory layout offers:

• Fast Access: You can quickly access any element in the array using its index.

• Memory Efficiency: Elements are stored compactly, without any extra overhead between them.

5. Default Values in Arrays

When an array is created but not explicitly initialized, Java assigns default values to each element.
These default values depend on the data type of the array:

• int, byte, short, long: 0

• float, double: 0.0

• char: **'\u0000'` (null character)

• boolean: false

• Object references: null

For example:
int[] arr = new int[3];

The above code will create an array of 3 integers, all initialized to 0 by default.

6. Memory Limitation and Array Size

Although arrays are memory-efficient, they come with certain limitations:

• Fixed Size: Once an array is created, its size is fixed and cannot be changed. This means you must
know the size of the array in advance.

• Contiguous Memory Requirement: Since arrays require a contiguous block of memory, large arrays
may cause memory allocation issues if the system cannot find a large enough block of free memory.

7. Garbage Collection

Java has an automatic Garbage Collector (GC) that deallocates unused memory. When an array is no
longer referenced, the garbage collector will eventually free the memory occupied by the array in the
heap. This helps avoid memory leaks, though it's important to ensure that arrays that are no longer
needed are dereferenced properly.
Arrays in Java are stored in contiguous memory blocks, with the actual elements stored in the heap
and the reference in the stack. This allows for efficient access to elements through indexing, which is
both time-efficient and memory-efficient. While arrays are highly optimized for fixed-size collections,
they are constrained by their fixed size and the need for contiguous memory blocks. Understanding
how arrays are stored helps developers make better decisions when dealing with large collections of
data in Java.

Do It Yourself

1. Write a Java program that declares and initializes an array of 10 integers. Print the memory address
(hashcode) of the array and discuss how Java manages memory for the array and its elements.

2. Analyze the following code and find the bug related to memory usage or array storage. Explain the issue
and how to fix it.

int[] myArray = new int[5];

for (int i = 0; i <= 5; i++) {

myArray[i] = i * 10;

3. Given that Java arrays start indexing from 0, explain why attempting to access an element outside the
declared size (for example, array[5] in a 5-element array) causes an ArrayIndexOutOfBoundsException.
Provide a code snippet demonstrating this behavior and explain how memory is affected by improper
indexing.

4. Create two arrays in Java, one storing int values and another storing double values. Write a program to
display the size of each array in memory. Explain why the memory required for each array differs even
if both arrays have the same number of elements.

Accessing Elements 1D Arrays


Introduction

In Java, arrays are a collection of elements of the same data type stored in contiguous memory
locations. Once an array is declared and initialized, each element can be accessed individually using
an index. The index starts at 0, meaning the first element is accessed using index 0, the second
element with index 1, and so on.

Syntax for Accessing Array Elements

To access an element from an array, you use the following syntax:

arrayName[index];
• arrayName: Name of the array.

• index: The position of the element you want to access (starting from 0).

public class AccessArrayElements {

public static void main(String[] args) {

// Declare and initialize an array

int[] numbers = {10, 20, 30, 40, 50};

// Access elements from the array

System.out.println("First element: " + numbers[0]); // Output: 10

System.out.println("Second element: " + numbers[1]); // Output: 20

System.out.println("Third element: " + numbers[2]); // Output: 30

// Change the value of an element


numbers[3] = 100;

System.out.println("Updated fourth element: " + numbers[3]); // Output: 100

Explanation:

• The array numbers is declared with 5 integer elements.

• The elements are accessed using their index values: numbers[0], numbers[1], etc.

• The value of the fourth element is changed using numbers[3] = 100;.

Important Points:

• The index of the array starts from 0. So, numbers[0] refers to the first element.

• Trying to access an index that is out of bounds (greater than or equal to the array length) will result in
an ArrayIndexOutOfBoundsException.

Practice Program
Here’s a program that accepts input for an array, prints all the elements, and calculates the sum of the
elements.

import java.util.Scanner;

public class ArrayExample {

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);

// Ask user for the number of elements in the array

System.out.print("Enter the number of elements: ");

int n = scanner.nextInt();

// Declare an array of size n

int[] arr = new int[n];

// Take input from the user

System.out.println("Enter " + n + " elements:");

for (int i = 0; i < n; i++) {

arr[i] = scanner.nextInt();

// Display the elements of the array

System.out.println("Array elements are:");

for (int i = 0; i < n; i++) {

System.out.println("Element at index " + i + " is: " + arr[i]);

// Calculate and display the sum of the elements

int sum = 0;

for (int i = 0; i < n; i++) {

sum += arr[i];

System.out.println("Sum of array elements: " + sum);

}
Explanation:

• This program demonstrates how to access and display array elements.

• It also calculates the sum of all elements in the array using a for loop.

Summary

• Accessing Array Elements: You can access array elements using their index, which starts from 0.

• Array Index Out of Bounds: Trying to access an index greater than or equal to the array size results in
an ArrayIndexOutOfBoundsException.

• Array Access in Loops: Arrays are often accessed using loops to perform operations like summing
elements or printing values.

Do It Yourself

1. Write a Java program to declare an array of 5 integers. Ask the user to input 5 values, store them in the
array, and print all elements.

2. Write a program that initializes an array with 10 elements. Swap the values of the first and last elements,
then print the updated array.

3. Create a program to declare an array of 7 floating-point numbers, calculate their sum, and print both
the array and the sum.

4. Declare an array of 6 integers, and then replace the value at index 2 with the value at index 4. Print the
modified array.

5. Write a program that tries to access an element at an index greater than the array size. Observe and
explain the error you get.

Quiz

1. What is the correct way to access the 3rd element of an array named arr?
a) arr(2)
b) arr[3]
c) arr[2]
d) arr[1]
Answer: c) arr[2]

2. What happens if you try to access an array element with an index larger than the array size?
a) The first element will be returned.
b) The program will crash without any message.
c) An ArrayIndexOutOfBoundsException is thrown.
d) The last element of the array will be returned.
Answer: c) An ArrayIndexOutOfBoundsException is thrown.
3. What is the index of the last element in an array of size 10?
a) 10
b) 9
c) 8
d) 11
Answer: b) 9

4. Which of the following is the correct declaration of an array in Java?


a) int arr[] = new int(5);
b) int arr[] = new int[5];
c) int arr() = new int[5];
d) int[] arr = new int(5);
Answer: b) int arr[] = new int[5];

5. How are array elements stored in memory in Java?


a) Random locations
b) Contiguously in memory
c) In reverse order
d) Depends on the operating system
Answer: b) Contiguously in memory

References

Array declaration - #28 Creation of Array in Java

Array initialization - How to Declare and initialise Arrays in different ways | Java Programming Tutorial

Accessing array elements - Accessing Array Elements


Operations on Array Elements:
Introduction

In Java, arrays allow you to store and manipulate a collection of elements of the same data type.
Once the array is initialized, various operations can be performed on its elements, such as accessing,
updating elements. In addition, you can perform arithmetic or logical operations on array elements
using loops.

In Java, deletion and insertion are not directly supported in arrays because arrays have a fixed size
once initialized.

Basic Operations on Array Elements

1. Accessing Elements: Retrieve elements using the array index.

2. Updating Elements: Modify the value at a specific index.

3. Traversing the Array: Visit each element using loops.

4. Searching for an Element: Find an element in the array using linear search or binary search.

5. Sorting Elements: Arrange the array elements in ascending or descending order.

6. Performing Arithmetic Operations: Apply arithmetic operations (e.g., addition, multiplication) on


elements.

Syntax for Accessing, Updating, and Performing Operations

• Accessing Elements:

int element = arrayName[index];

• Updating Elements:

arrayName[index] = newValue;

• Performing Arithmetic Operations:

result = arrayName[index] + 10; // Example: Addition

Example 1: Accessing and Updating Array Elements

public class ArrayOperations {

public static void main(String[] args) {

int[] arr = {5, 10, 15, 20, 25};

// Accessing elements

System.out.println("Element at index 2: " + arr[2]);

// Updating elements

arr[2] = 30;
System.out.println("Updated element at index 2: " + arr[2]);

Explanation:

• The program declares an integer array arr with 5 elements.

• We access the element at index 2 and display it.

• The value at index 2 is updated from 15 to 30, and the updated value is printed.

Example 2: Performing Arithmetic Operations on Array Elements

public class ArraySum {

public static void main(String[] args) {


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

int sum = 0;

int mul = 0;

// Adding elements

// Sum of elements in odd indices

sum = numbers[1] + numbers[3];

System.out.println("Sum of array elements in odd indices: " + sum);

mul = numbers[0] * numbers[2] * numbers[4];

System.out.println("product of array elements in even indices: " + mul);

Explanation:

• This program demonstrates how to traverse an array using a for loop and calculate the sum of all
elements.

• The sum variable accumulates the values of the elements in the array.

Practice Program 1: Find the Maximum Element in an Array

import java.util.Scanner;

public class MaxElement {

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);


// Input: Size of the array

System.out.print("Enter the number of elements: ");

int n = scanner.nextInt();

// Declare and initialize array

int[] arr = new int[n];

// Input: Elements of the array

System.out.println("Enter the elements:");

for (int i = 0; i < n; i++) {

arr[i] = scanner.nextInt();

// Find the maximum element


int max = arr[0];

for (int i = 1; i < arr.length; i++) {

if (arr[i] > max) {

max = arr[i];

System.out.println("Maximum element: " + max);

Explanation:

• The program accepts an array of integers from the user and then iterates through it to find the maximum
element.

Summary

• Arrays allow you to perform operations like accessing, updating, and traversing elements.

• Arithmetic and logical operations can be applied to individual array elements using loops.

• In practice, array operations are commonly used for calculations, sorting, and searching in real-world
applications.

Do It Yourself

1. Write a Java program that calculates and prints the sum and average of an array of 10 integers.
2. Write a program that accepts an array of 5 integers from the user and prints the array in reverse
order.

3. Write a program that finds and prints the minimum element of an array of n elements entered by the
user.

4. Write a program that multiplies each element of an array by a given number (provided by the user).

5. Write a Java program that swaps the first and last elements of an array and prints the result.

Quiz

1. What is the correct way to update the third element of an array arr with a value of 50? a) arr(3) = 50;
b) arr[3] = 50;
c) arr[2] = 50;
d) arr[2] = 50;
Answer: c) arr[2] = 50;

2. What will the following code output?

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

arr[1] = arr[2] * 2;

System.out.println(arr[1]);

a) 4
b) 6
c) 8
d) 3
Answer: b) 6

3. If you want to add 5 to each element in an array of 10 elements, which loop should you use? a) for
(int i = 0; i < 5; i++)
b) for (int i = 0; i < 10; i++)
c) for (int i = 0; i <= 10; i++)
d) for (int i = 1; i < 10; i++)
Answer: b) for (int i = 0; i < 10; i++)

4. Which operation is used to find the sum of all elements in an array? a) Multiplication
b) Addition
c) Division
d) Subtraction
Answer: b) Addition
5. What is the result of the following code?

int[] arr = {5, 10, 15};

arr[1] = arr[1] + 10;

System.out.println(arr[1]);

a) 10
b) 15
c) 20
d) 25
Answer: c) 20

Assigning Array to Another Array:


In Java, arrays are objects stored in heap memory. When you assign one array to another, you're copying the
reference (or memory address) of the array, not the actual data. This can lead to situations where changing one array
affects the other, since both refer to the same memory location. This is essential to understand when working with arrays,
especially when handling large datasets or performing operations like copying arrays.

Direct Assignment of Arrays

When you assign one array to another using the = operator, both arrays refer to the same memory location.
Hence, any changes made to one array will reflect in the other.

Syntax:

array2 = array1;

Example 1: Direct Assignment

public class ArrayAssignment {

public static void main(String[] args) {

int[] array1 = {10, 20, 30, 40};

int[] array2;

// Assigning array1 to array2

array2 = array1;

// Modifying array2

array2[2] = 50;

// Both arrays reflect the change


System.out.println("array1[2]: " + array1[2]); // Output: 50

System.out.println("array2[2]: " + array2[2]); // Output: 50


}

Explanation:

• array2 is assigned to array1. Both now point to the same memory location.

• Modifying the value at index 2 in array2 changes the value in array1 as well, because both are
referencing the same array.

Cloning an Array

If you want to create an actual copy of an array (not just copying the reference), you can use the clone() method.
This creates a new array with the same elements but different memory locations.

Syntax:

array2 = array1.clone();

Example 2: Cloning an Array

public class ArrayCloning {

public static void main(String[] args) {

int[] array1 = {5, 10, 15, 20};

int[] array2;

// Cloning array1 to array2

array2 = array1.clone();

// Modifying array2

array2[1] = 25;

// array1 remains unchanged

System.out.println("array1[1]: " + array1[1]); // Output: 10

System.out.println("array2[1]: " + array2[1]); // Output: 25

Explanation:

• The clone() method creates a separate copy of array1 and assigns it to array2.

• Changes made to array2 do not affect array1, as they point to different memory locations.

Practice Program: Copying Arrays with Loops

You can also manually copy arrays using loops. This method gives you more control over the copying process,
such as copying only certain elements.
public class ManualArrayCopy {

public static void main(String[] args) {

int[] array1 = {3, 6, 9, 12, 15};

int[] array2 = new int[array1.length];

// Copy elements from array1 to array2

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

array2[i] = array1[i];

// Modify array2 and check if array1 remains unchanged

array2[0] = 99;

System.out.println("array1[0]: " + array1[0]); // Output: 3


System.out.println("array2[0]: " + array2[0]); // Output: 99

Explanation:

• We manually copy the elements of array1 to array2 using a for loop.

• Changing array2 does not affect array1, as each array has its own memory allocation.

Shallow Copy vs Deep Copy

• Shallow Copy: When you assign an array to another using =, both arrays refer to the same memory
location. This is a shallow copy.

• Deep Copy: When you copy an array element by element (or using methods like clone()), a new memory
allocation is created. This is a deep copy.

Summary

Assigning arrays in Java using = creates a shallow copy, meaning both arrays share the same memory location.

Cloning or manually copying arrays creates a deep copy, allowing you to modify one array without affecting the
other.

Understanding how Java manages memory for arrays is essential for efficient programming, particularly when
dealing with large datasets.

Do It Yourself

1. Write a Java program that creates two integer arrays a and b. Assign a to b, modify the contents of the
b array, and print both arrays. Why do changes to b affect a in this case?
2. Write a Java program that creates an array of strings and clones it using the clone() method. Modify the
cloned array and print both arrays to verify that the original array remains unchanged. Why does
modifying the cloned array not affect the original array?

3. Write a Java program that manually copies the contents of an integer array into another array using a
for loop. Modify the elements of the copied array and print both arrays to confirm that the original
array is not affected.

Quiz

1. What happens when you assign one array to another using =?

a) Both arrays have the same values but different memory locations.
b) Both arrays refer to the same memory location.
c) A deep copy of the array is created.
d) The second array is automatically initialized to null.
Answer: b) Both arrays refer to the same memory location.

2. How can you create a copy of an array in Java that doesn't affect the original array?

a) Using the clone() method.


b) Assigning using =.
c) Using System.arraycopy().
d) Both a and c.
Answer: d) Both a and c.

3. What will be the output of the following code?

int[] arr1 = {1, 2, 3};

int[] arr2 = arr1;

arr2[0] = 10;

System.out.println(arr1[0]);

a) 1
b) 10
c) Compilation error
d) NullPointerException
Answer: b) 10

4. Which of the following correctly creates a deep copy of a 1D array in Java?


a) int[] arr2 = arr1.clone();
b) int[] arr2 = arr1;
c) System.arraycopy(arr1, 0, arr2, 0, arr1.length);
d) Both a and c.
Answer: d) Both a and c.
5. How does Java handle memory when assigning one array to another?

a) Java creates a copy of the entire array and allocates new memory for the second array.
b) Java only copies the reference (memory address) to the second array.
c) Java does not allocate memory for arrays at all.
d) Java duplicates the array elements in both arrays.
Answer: b) Java only copies the reference (memory address) to the second array.

Dynamic Change of Array Size:


Java arrays have a fixed size once they are created. However, in real-world applications, there may be
situations where we need a flexible data structure that allows us to change the size of the array dynamically as the
program runs. Java doesn’t provide direct support for dynamically resizing an array, but it provides alternatives, such as
using ArrayList and System.arraycopy().

Here, we will see different ways to achieve the dynamic change of array size.

Fixed-Size Limitation of Arrays

In Java, once an array is created, its size cannot be changed. For example:

int[] numbers = new int[5]; // Fixed size array with 5 elements

Here, the array numbers has a fixed size of 5. You cannot add or remove elements from this array after its
creation.

Dynamic Resizing of Arrays

To work around this limitation, Java provides two main techniques:

• Using ArrayList for dynamic resizing.

• Manually resizing arrays using the System.arraycopy() method.

Using ArrayList for Dynamic Arrays

An ArrayList in Java is a resizable array, meaning it automatically grows in size when more elements are added.
Unlike arrays, an ArrayList allows you to dynamically change its size.

Syntax for Using ArrayList:

import java.util.ArrayList;

ArrayList<Type> arrayList = new ArrayList<>();

Example Program:

import java.util.ArrayList;

public class DynamicArrayExample {

public static void main(String[] args) {


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

// Adding elements dynamically

numbers.add(10);

numbers.add(20);

numbers.add(30);

// Printing the ArrayList

System.out.println("Numbers: " + numbers);

// Adding more elements dynamically

numbers.add(40);

numbers.add(50);

// Printing the updated ArrayList


System.out.println("Updated Numbers: " + numbers);

Explanation:

• ArrayList dynamically resizes as elements are added using the add() method.

• The ArrayList grows as needed when more elements are added.

Manually Resizing Arrays Using System.arraycopy()

Another way to resize an array in Java is by creating a new, larger array and copying the elements of the original
array into the new array. Java provides the System.arraycopy() method for this purpose.

Syntax for Using System.arraycopy():

System.arraycopy(sourceArray, sourcePosition, destinationArray, destinationPosition, length);

• sourceArray: The original array.

• sourcePosition: The position in the original array to start copying.

• destinationArray: The new array where elements are copied.

• destinationPosition: The position in the new array where copying starts.

• length: The number of elements to copy.

Example Program:

public class DynamicArrayResize {

public static void main(String[] args) {

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


// Creating a new array with a larger size

int[] newArray = new int[10];

// Copying elements from the original array to the new array

System.arraycopy(originalArray, 0, newArray, 0, originalArray.length);

// Adding new elements to the new array

newArray[5] = 6;

newArray[6] = 7;

// Printing the new array

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

System.out.print(newArray[i] + " ");

}
}

Explanation:

• A new array newArray is created with a larger size.

• The elements of originalArray are copied to newArray using System.arraycopy().

• Additional elements are added to newArray after resizing.

Practice Program:

Here is a Java program that creates an array of integers with 5 elements, resizes the array to hold 10 elements
using the System.arraycopy() method, and prints the array before and after resizing:

public class ArrayResizeExample {

public static void main(String[] args) {

// Step 1: Create an array with 5 elements

int[] originalArray = {10, 20, 30, 40, 50};

// Print the original array

System.out.println("Original array:");

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

System.out.print(originalArray[i] + " ");

System.out.println();
// Step 2: Resize the array to hold 10 elements

int[] resizedArray = new int[10];

// Copy elements from originalArray to resizedArray

System.arraycopy(originalArray, 0, resizedArray, 0, originalArray.length);

// Print the resized array before adding new elements

System.out.println("Resized array before adding new elements:");

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

System.out.print(resizedArray[i] + " ");

System.out.println();

// Step 3: Add new elements to the resized array


resizedArray[5] = 60;

resizedArray[6] = 70;

resizedArray[7] = 80;

resizedArray[8] = 90;

resizedArray[9] = 100;

// Print the resized array after adding new elements

System.out.println("Resized array after adding new elements:");

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

System.out.print(resizedArray[i] + " ");

Explanation:

1. The original array originalArray is created with 5 elements.

2. A new array resizedArray of size 10 is created to accommodate more elements.

3. The System.arraycopy() method copies elements from originalArray to resizedArray.


4. Additional elements are added to the new array after the resizing.

5. The program prints the array before and after resizing.


Output:

Original array:

10 20 30 40 50

Resized array before adding new elements:

10 20 30 40 50 0 0 0 0 0

Resized array after adding new elements:

10 20 30 40 50 60 70 80 90 100

In this way, the array is resized, and new elements are added while maintaining the original array values.

Dynamic Array Resizing:

• ArrayList automatically handles dynamic resizing in Java. It is the most efficient and preferred way of
handling dynamic arrays.

• Using System.arraycopy(), you manually handle resizing by copying the elements to a new array with
larger capacity. This approach can be useful when working with primitive arrays or in performance-
critical applications where ArrayList is not suitable.

Do It Yourself

1. Write a Java program that creates a String array and dynamically resizes it using System.arraycopy().

2. Modify the above program to add new elements to the resized array and print them.

3. Create an integer array and resize it using an ArrayList. Add more elements to the ArrayList and print
them.

4. Explain the advantages of using ArrayList over manually resizing arrays in Java.

5. Write a program to resize a char array manually using System.arraycopy().

Quiz

1. Which of the following is used to dynamically resize an array in Java?

a) ArrayList
b) Vector
c) System.arraycopy()
d) Both a and c

Answer: d) Both a and c


2. What happens when you assign a new reference to an array in Java?

a) The original array is resized.


b) The original array remains unchanged, and the new reference points to a different array.
c) Both arrays point to the same memory location.
d) A compile-time error occurs.

Answer: c) Both arrays point to the same memory location.

3. Which method is used to copy the elements of one array into another array in Java?

a) copyArray()
b) arrayCopy()
c) System.arraycopy()
d) copy()

Answer: c) System.arraycopy()

4. What is the primary advantage of using ArrayList over arrays in Java?

a) It is faster than arrays.


b) It can grow dynamically as elements are added.
c) It uses less memory than arrays.
d) It allows null values.

Answer: b) It can grow dynamically as elements are added.

5. Consider the following code:

int[] a = {1, 2, 3};


int[] b = new int[5];

System.arraycopy(a, 0, b, 0, 3);

What will be the value of b[3] after this code executes?

a) 1
b) 0
c) 3
d) NullPointerException

Answer: b) 0
Sorting of Arrays
In Java, sorting an array means arranging its elements in ascending or descending order. Sorting is a
common task in various real-world applications, such as organizing data, searching efficiently, and
solving complex problems. Java provides multiple ways to sort arrays, including built-in methods and
custom algorithms.

1. Sorting Using Built-in Methods

Java provides the Arrays.sort() method, which is efficient and easy to use. It can sort arrays of primitives (e.g.,
int, char, etc.) and arrays of objects that implement the Comparable interface.

Syntax

Arrays.sort(array);

This sorts the array in ascending order by default.

Example

import java.util.Arrays;

public class SortExample {

public static void main(String[] args) {

int[] numbers = { 4, 2, 9, 1, 5 };

// Before sorting

System.out.println("Before sorting: " + Arrays.toString(numbers));

// Sort the array

Arrays.sort(numbers);

// After sorting

System.out.println("After sorting: " + Arrays.toString(numbers));

Output

Before sorting: [4, 2, 9, 1, 5]

After sorting: [1, 2, 4, 5, 9]


Explanation

The Arrays.sort() method sorts the array in ascending order. The method modifies the array in place, so after
the call to Arrays.sort(), the original array is sorted.
2. Sorting in Descending Order

To sort an array in descending order, Java provides a way to use the Arrays.sort() method along with a
comparator.

Syntax

Arrays.sort(array, Collections.reverseOrder());

Example

import java.util.Arrays;

import java.util.Collections;

public class DescendingSortExample {

public static void main(String[] args) {

Integer[] numbers = { 4, 2, 9, 1, 5 };

// Before sorting

System.out.println("Before sorting: " + Arrays.toString(numbers));

// Sort the array in descending order

Arrays.sort(numbers, Collections.reverseOrder());

// After sorting

System.out.println("After sorting: " + Arrays.toString(numbers));

Output

Before sorting: [4, 2, 9, 1, 5]

After sorting: [9, 5, 4, 2, 1]

Explanation

The Collections.reverseOrder() method is used with Arrays.sort() to sort the array in descending order.

3. Sorting Arrays of Strings

Arrays of strings can also be sorted alphabetically using the Arrays.sort() method.

Example

import java.util.Arrays;

public class StringSortExample {

public static void main(String[] args) {

String[] names = { "John", "Alice", "Bob" };


// Before sorting

System.out.println("Before sorting: " + Arrays.toString(names));

// Sort the array

Arrays.sort(names);

// After sorting

System.out.println("After sorting: " + Arrays.toString(names));

Output

Before sorting: [John, Alice, Bob]

After sorting: [Alice, Bob, John]

Practice Program

Program 1: Sort an array of integers using Arrays.sort().

import java.util.Arrays;

public class SortPractice {

public static void main(String[] args) {

int[] numbers = { 34, 12, 45, 2, 19 };

System.out.println("Original array: " + Arrays.toString(numbers));

// Sort the array

Arrays.sort(numbers);

System.out.println("Sorted array: " + Arrays.toString(numbers));

Program 2: Sort an array of strings in descending order.

import java.util.Arrays;

import java.util.Collections;

public class StringSortPractice {

public static void main(String[] args) {


String[] fruits = { "Apple", "Orange", "Banana", "Grapes" };

System.out.println("Original array: " + Arrays.toString(fruits));

// Sort in descending order

Arrays.sort(fruits, Collections.reverseOrder());

System.out.println("Sorted array in descending order: " + Arrays.toString(fruits));

Do It Yourself

1. Write a program to sort an array of integers in ascending order using Arrays.sort().


2. Modify the above program to sort the array in descending order using Collections.reverseOrder().

3. Write a program to sort an array of strings in alphabetical order.

4. Create a custom class Person with name and age. Write a program to sort an array of Person objects by
age.

5. Write a program to find the smallest and largest elements in an array by sorting it.

Quiz

1. What does the Arrays.sort() method do by default?

A) Sorts in ascending order

B) Sorts in descending order

C) Does nothing

D) Reverses the array

Answer: A) Sorts in ascending order

2. Which method is used to sort arrays in descending order?

A) Arrays.descendingSort()

B) Collections.reverseOrder()

C) Arrays.reverseOrder()

D) Arrays.sortDescending()

Answer: B) Collections.reverseOrder()
3. Which of the following can be sorted using Arrays.sort()?

A) Primitive types only

B) Objects implementing the Comparable interface

C) Arrays of any type

D) Only arrays of numbers

Answer: B) Objects implementing the Comparable interface

4.What is the output of the following code?

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

Arrays.sort(arr);

System.out.println(arr[0]);
A) 1

B) 2

C) 5

D) 3

Answer: A) 1

5.Which of the following is true about the clone() method when used with arrays?

A) It performs a shallow copy.

B) It performs a deep copy.

C) It creates a reference to the original array.

D) It can only be used with primitive types.

Answer: A) It performs a shallow copy

Search for Values in Arrays


Searching for values in arrays is a fundamental concept in programming. In Java, you can perform searches in
arrays using various techniques, including linear search and binary search. These methods help locate a specific
element within an array and are essential for efficiently managing and retrieving data.

1. Linear Search

Linear search, also known as sequential search, is a straightforward method to find an element in an array. It
involves checking each element sequentially until the target value is found or the end of the array is reached.
Syntax

public static int linearSearch(int[] array, int target) {

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

if (array[i] == target) {

return i; // Target found, return its index

return -1; // Target not found, return -1

Example

public class LinearSearchExample {


public static void main(String[] args) {

int[] numbers = {10, 20, 30, 40, 50};

int target = 30;

int index = linearSearch(numbers, target);

if (index != -1) {

System.out.println("Element " + target + " found at index: " + index);

} else {

System.out.println("Element " + target + " not found in the array.");

public static int linearSearch(int[] array, int target) {

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

if (array[i] == target) {

return i;

return -1;
}

Output

Element 30 found at index: 2


Explanation

Linear search iterates through each element of the array until it finds the target. It is simple but not efficient
for large arrays.

2. Binary Search

Binary search is an efficient algorithm used to find an element in a sorted array. It repeatedly divides the search
interval in half until the target value is found or the interval is empty.

Syntax

public static int binarySearch(int[] array, int target) {

int left = 0;

int right = array.length - 1;

while (left <= right) {

int mid = left + (right - left) / 2;

if (array[mid] == target) {

return mid; // Target found, return its index

if (array[mid] < target) {

left = mid + 1; // Search in the right half

} else {

right = mid - 1; // Search in the left half

return -1; // Target not found, return -1

Example

public class BinarySearchExample {

public static void main(String[] args) {

int[] numbers = {10, 20, 30, 40, 50};

int target = 40;

int index = binarySearch(numbers, target);

if (index != -1) {

System.out.println("Element " + target + " found at index: " + index);

} else {
System.out.println("Element " + target + " not found in the array.");

public static int binarySearch(int[] array, int target) {

int left = 0;

int right = array.length - 1;

while (left <= right) {

int mid = left + (right - left) / 2;

if (array[mid] == target) {

return mid;

}
if (array[mid] < target) {

left = mid + 1;

} else {

right = mid - 1;

return -1;

Output

Element 40 found at index: 3

Explanation

Binary search requires the array to be sorted. It works efficiently with a time complexity of O(log n), making it
faster for large datasets compared to linear search.

Practice Programs

Program 1: Implement a linear search to find a specific value in an array of integers and print its index.

public class LinearSearchPractice {

public static void main(String[] args) {

int[] array = {12, 24, 35, 44, 56, 67};

int target = 44;


int result = linearSearch(array, target);

System.out.println("Element " + target + " is at index: " + result);

public static int linearSearch(int[] array, int target) {

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

if (array[i] == target) {

return i;

return -1;

}
}

Program 2: Implement a binary search to find a specific value in a sorted array of integers.

public class BinarySearchPractice {

public static void main(String[] args) {

int[] sortedArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int target = 7;

int result = binarySearch(sortedArray, target);

System.out.println("Element " + target + " is at index: " + result);

public static int binarySearch(int[] array, int target) {

int left = 0;

int right = array.length - 1;

while (left <= right) {

int mid = left + (right - left) / 2;

if (array[mid] == target) {
return mid;

if (array[mid] < target) {

left = mid + 1;
} else {

right = mid - 1;

return -1;

Program 3: Implement a program to find the maximum value in an unsorted array using linear search.

public class FindMaxValue {


public static void main(String[] args) {

int[] array = {12, 45, 23, 89, 34};

int max = findMax(array);

System.out.println("The maximum value is: " + max);

public static int findMax(int[] array) {

int max = array[0];

for (int i = 1; i < array.length; i++) {

if (array[i] > max) {

max = array[i];

return max;

Program 4: Write a program to count the number of occurrences of a specific value in an array using linear
search.

public class CountOccurrences {

public static void main(String[] args) {


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

int target = 2;

int count = countOccurrences(array, target);

System.out.println("Element " + target + " occurs " + count + " times.");

public static int countOccurrences(int[] array, int target) {

int count = 0;

for (int value : array) {

if (value == target) {

count++;

}
}

return count;

Do It Yourself

1. Write a program to search for a value in an array of integers using linear search and return the index
of the element.

2. Implement a binary search algorithm to find a target value in a sorted array of integers and return the
index of the element.

3. Create a program to find the maximum value in an array of integers using linear search.

4. Write a program to count how many times a specific value appears in an array using linear search.

Quiz

1. What is the time complexity of linear search in an unsorted array?

A) O(1)

B) O(n)

C) O(log n)

D) O(n^2)
Answer: B) O(n)

2. What must be true about an array for binary search to work?

A) The array must be sorted.

B) The array must be unsorted.

C) The array must be of integer type.

D) The array must contain unique elements.

Answer: A) The array must be sorted.

3.What is the output of the following code?


int[] array = {3, 6, 9, 12};

int result = binarySearch(array, 9);

System.out.println(result);

A) 2

B) 3

C) 1

D) -1

Answer: A) 2

4.How can you find the number of occurrences of a value in an array?

A) Use binary search

B) Use linear search and count occurrences

C) Use sorting and count duplicates

D) Use binary search and count comparisons

Answer: B) Use linear search and count occurrences

5.What is the key advantage of binary search over linear search?

A) Binary search works on unsorted arrays.

B) Binary search has a time complexity of O(log n).

C) Binary search works on arrays with duplicate values.


D) Binary search can handle large data sets without any issues.

Answer: B) Binary search has a time complexity of O(log n).

Arrays Class:
The Arrays class in Java is a utility class that provides various methods for working with arrays. It is part of the
java.util package and offers methods for sorting, searching, comparing, and manipulating arrays.
Understanding the Arrays class is crucial for efficient array handling and operations in Java.

Introduction to Arrays Class

The Arrays class contains static methods that operate on arrays. These methods provide functionalities such as
sorting, searching, and converting arrays to strings.

Commonly Used Methods:

• sort(): Sorts the elements of an array.

• binarySearch(): Searches for a specified element in a sorted array.

• copyOf(): Copies an array, truncating or padding with default values as necessary.

• copyOfRange(): Copies a range of elements from the original array.

• equals(): Checks if two arrays are equal.

• toString(): Returns a string representation of the array.

Syntax and Examples

a. Sorting Arrays

import java.util.Arrays;

public class ArraySorting {

public static void main(String[] args) {

int[] numbers = {4, 2, 9, 1, 5, 6};

Arrays.sort(numbers);

System.out.println("Sorted array: " + Arrays.toString(numbers));

}
Arrays.sort(array): This method sorts the array in ascending order. It uses a dual-pivot quicksort algorithm for
primitive types and a stable sort for objects.

b. Binary Search

import java.util.Arrays;

public class ArrayBinarySearch {

public static void main(String[] args) {

int[] numbers = {1, 2, 4, 5, 6, 9};

int target = 5;

int index = Arrays.binarySearch(numbers, target);

System.out.println("Index of " + target + ": " + index);

Arrays.binarySearch(array, key): This method performs a binary search on the sorted array to find the specified
key. It returns the index of the key if found; otherwise, it returns a negative value.

c. Copying Arrays

import java.util.Arrays;

public class ArrayCopy {

public static void main(String[] args) {

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

int[] copy = Arrays.copyOf(original, original.length);

System.out.println("Copied array: " + Arrays.toString(copy));

Arrays.copyOf(original, newLength): Creates a new array of the specified length and copies the elements from
the original array into the new array. If the new length is greater than the original array, the new elements are
initialized with default values.
d. Copying a Range of Arrays

import java.util.Arrays;

public class ArrayCopyRange {

public static void main(String[] args) {

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

int[] copy = Arrays.copyOfRange(original, 1, 4);

System.out.println("Copied range array: " + Arrays.toString(copy));

Arrays.copyOfRange(original, from, to): Copies a range of elements from the original array into a new array.
The from index is inclusive, and the to index is exclusive.

e. Comparing Arrays

import java.util.Arrays;

public class ArrayComparison {

public static void main(String[] args) {

int[] array1 = {1, 2, 3};

int[] array2 = {1, 2, 3};

boolean isEqual = Arrays.equals(array1, array2);

System.out.println("Arrays equal: " + isEqual);

Arrays.equals(array1, array2): Compares two arrays for equality. The arrays are considered equal if they have
the same length and contain the same elements in the same order.

f. Converting Array to String

import java.util.Arrays;

public class ArrayToString {

public static void main(String[] args) {

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

String result = Arrays.toString(numbers);


System.out.println("Array as string: " + result);

Arrays.toString(array): Returns a string representation of the array. Useful for debugging and displaying array
contents.

Do It Yourself

1. Write a Java program that sorts an array of integers using Arrays.sort() and prints the sorted array.

2. Implement a program that searches for a specific value in a sorted array using Arrays.binarySearch()
and prints the index of the value.

3. Create a program that copies an array of integers to a new array and prints both arrays to verify the
copy.

4. Write a program that copies a range of elements from an array using Arrays.copyOfRange() and prints
the resulting array.

5. Implement a program that compares two integer arrays using Arrays.equals() and prints whether they
are equal or not.

Quiz

1. What does the Arrays.sort() method do?

A) Copies an array

B) Searches for an element

C) Sorts the elements of an array

D) Converts an array to a string

Answer: C) Sorts the elements of an array

2. What is the result of Arrays.binarySearch(array, key) if the key is not found?

A) The index of the key

B) A positive integer

C) A negative value

D) Zero

Answer: C) A negative value


3. How can you create a copy of an array with a different length using the Arrays class?

A) Arrays.copyOfRange()

B) Arrays.copyOf()

C) Arrays.toString()

D) Arrays.equals()

Answer: B) Arrays.copyOf()

4. Which method is used to compare two arrays for equality in Java?

A) Arrays.copyOf()

B) Arrays.binarySearch()

C) Arrays.equals()
D) Arrays.sort()

Answer: C) Arrays.equals()

5. What does Arrays.toString(array) return?

A) A string representation of the array

B) A new array with the same elements

C) The length of the array

D) The sum of array elements

Answer: A) A string representation of the array

2D Arrays :
2D arrays, also known as arrays of arrays, are a fundamental concept in Java for handling tabular data.

Introduction to 2D Arrays

A 2D array in Java is essentially an array of arrays. It can be visualized as a table with rows and columns. Each
element of a 2D array is accessed by specifying two indices: one for the row and one for the column.

Real-time Examples:

1. The seating arrangement of the hall


2. Budget planning
3. Chessboard
4. Pixel grid
5. Spreadsheet
6. Tic - Tak - Toe game

Syntax:

type[][] arrayName = new type[rows][columns];

• type: The data type of the array elements.

• arrayName: The name of the array.

• rows: The number of rows in the 2D array.

• columns: The number of columns in the 2D array.

a. Declaring and Initializing a 2D Array

public class Array2DExample {

public static void main(String[] args) {

int[][] matrix = new int[3][4]; // 3 rows and 4 columns

// Initializing the array

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

for (int j = 0; j < matrix[i].length; j++) {

matrix[i][j] = i + j; // Assigning values

// Printing the array

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


for (int j = 0; j < matrix[i].length; j++) {

System.out.print(matrix[i][j] + " ");

System.out.println();

Output:

0123

1234
2345

Explanation: This program declares a 2D array with 3 rows and 4 columns. It initializes the array such that each
element is the sum of its row and column indices. The nested loops are used to assign values and print the
array.

Representation of Arrays:

b. Creating a 2D Array with Initial Values

public class Array2DInitialization {

public static void main(String[] args) {

int[][] matrix = {

{1, 2, 3},

{4, 5, 6},

{7, 8, 9}
};

// Printing the array

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

for (int j = 0; j < matrix[i].length; j++) {

System.out.print(matrix[i][j] + " ");

System.out.println();

Output:

123

456

789

Explanation: This program initializes a 2D array with predefined values and prints the matrix. The values are set
directly in the array declaration.

c. Accessing Elements of a 2D Array

public class Array2DAccess {

public static void main(String[] args) {

int[][] matrix = {

{10, 20, 30},

{40, 50, 60},

{70, 80, 90}

};

// Accessing a specific element

int element = matrix[1][2]; // Accesses element in 2nd row and 3rd column

System.out.println("Element at [1][2]: " + element);

}
Output:

Element at [1][2]: 60

Explanation: This program demonstrates how to access a specific element in a 2D array using its row and
column indices.

d. Traversing a 2D Array

public class Array2DTraversal {

public static void main(String[] args) {

int[][] matrix = {

{1, 2},

{3, 4},

{5, 6}

};

// Traversing the array

for (int[] row : matrix) {

for (int element : row) {

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

System.out.println();

Output:

12

34

56

Explanation: This program uses enhanced for loops to traverse and print each element of the 2D array. It
simplifies accessing each element by iterating through rows and columns.
Practice Programs

Program 1: Sum of All Elements in a 2D Array

public class Sum2DArray {

public static void main(String[] args) {

int[][] matrix = {

{1, 2, 3},

{4, 5, 6},

{7, 8, 9}

};

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

for (int j = 0; j < matrix[i].length; j++) {

sum += matrix[i][j];

System.out.println("Sum of all elements: " + sum);

Output:

Sum of all elements: 45

Program 2: Transpose of a 2D Array

public class Transpose2DArray {

public static void main(String[] args) {

int[][] matrix = {

{1, 2, 3},
{4, 5, 6},

{7, 8, 9}

};
int[][] transpose = new int[3][3]; // Transpose of a 3x3 matrix

// Calculating transpose

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

for (int j = 0; j < matrix[i].length; j++) {

transpose[j][i] = matrix[i][j];

// Printing transpose

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

for (int j = 0; j < transpose[i].length; j++) {

System.out.print(transpose[i][j] + " ");


}

System.out.println();

Output:

147

258

369

Program 3: Find the Maximum Element in Each Row

public class MaxElementInRows {

public static void main(String[] args) {

int[][] matrix = {

{10, 20, 30},

{40, 50, 60},

{70, 80, 90}


};

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

int max = matrix[i][0];


for (int j = 1; j < matrix[i].length; j++) {

if (matrix[i][j] > max) {

max = matrix[i][j];

System.out.println("Max in row " + i + ": " + max);

Output:
Max in row 0: 30

Max in row 1: 60

Max in row 2: 90

Program 4: Fill a 2D Array with Multiples of 5

public class Fill2DArray {

public static void main(String[] args) {

int[][] matrix = new int[3][4]; // 3 rows and 4 columns

int value = 5;

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

for (int j = 0; j < matrix[i].length; j++) {

matrix[i][j] = value;

value += 5;

// Printing the array

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


for (int j = 0; j < matrix[i].length; j++) {

System.out.print(matrix[i][j] + " ");

System.out.println();
}

Output:

5 10 15 20

25 30 35 40

45 50 55 60

Program 5: Matrix Multiplication

public class MatrixMultiplication {


public static void main(String[] args) {

int[][] matrix1 = {

{1, 2},

{3, 4}

};

int[][] matrix2 = {

{5, 6},

{7, 8}

};

int[][] result = new int[2][2];

// Multiplying matrices

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

for (int j = 0; j < matrix2[0].length; j++) {

result[i][j] = 0;

for (int k = 0; k < matrix2.length; k++) {

result[i][j] += matrix1[i][k] * matrix2[k][j];

}
}

// Printing result matrix

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

for (int j = 0; j < result[i].length; j++) {

System.out.print(result[i][j] + " ");

System.out.println();

Output:

19 22
43 50

1. Write a Java program to declare a 2D array of size 4x3 and initialize it with values from 1 to 12. Print
the array.

2. Create a program that calculates and prints the sum of each column in a 2D array.

3. Implement a program to find and print the transpose of a given 2D array.

4. Write a Java program to find and print the maximum element in a given 2D array.Create a program
that prints the diagonal elements of a square matrix.

Quiz

1. How do you declare a 2D array in Java?

A) int[] array = new int[3][4];

B) int[][] array = new int[3][4];

C) int[] array = new int[3][4][5];

D) int[][] array = new int[4];

Answer: B) int[][] array = new int[3][4];

2. Which method can be used to access the element in the 2nd row and 3rd column of a 2D array matrix?

A) matrix[2][3]

B) matrix[1][2]
C) matrix[3][2]

D) matrix[2][1]

Answer: B) matrix[1][2]

3. How do you print all elements of a 2D array in Java?

A) Use a single loop

B) Use nested loops

C) Use Arrays.toString()

D) Use System.out.println()

Answer: B) Use nested loops

4. What is the output of matrix[1][2] if matrix is a 2D array initialized as {{10, 20, 30}, {40, 50, 60}, {70, 80,
90}}?

A) 20

B) 30

C) 50

D) 60

Answer: D) 60

5.Which of the following is true about matrix multiplication in Java?

A) The number of columns in the first matrix must be equal to the number of rows in the second matrix.

B) The number of rows in the first matrix must be equal to the number of columns in the second matrix.

C) The matrices must be of the same size.

D) Matrix multiplication is not possible in Java.

Answer: A) The number of columns in the first matrix must be equal to the number of rows in the second matrix.
Arrays of Varying Lengths
Arrays of varying lengths, often referred to as "jagged arrays" or "ragged arrays," are a type of 2D array in Java
where each row can have a different number of columns. This flexibility allows for more dynamic and non-
uniform data storage compared to traditional 2D arrays where every row has the same number of columns.

1. Introduction to Jagged Arrays


A jagged array is an array of arrays where each sub-array can have a different length. This is useful for scenarios
where the data structure is not rectangular and each row might represent a different quantity of elements.

Syntax:

type[][] arrayName = new type[numberOfRows][];

Initialization:
arrayName[0] = new type[lengthOfFirstRow];
arrayName[1] = new type[lengthOfSecondRow];
// and so on

Example:

int[][] jaggedArray = new int[3][]; // Array with 3 rows


jaggedArray[0] = new int[2]; // First row with 2 columns
jaggedArray[1] = new int[4]; // Second row with 4 columns
jaggedArray[2] = new int[3]; // Third row with 3 columns

2. Examples
a. Declaring and Initializing a Jagged Array

public class JaggedArrayExample {


public static void main(String[] args) {
// Creating a jagged array
int[][] jaggedArray = new int[3][];
// Initializing the sub-arrays
jaggedArray[0] = new int[2]; // First row
jaggedArray[1] = new int[4]; // Second row
jaggedArray[2] = new int[3]; // Third row
// Assigning values to the jagged array
jaggedArray[0][0] = 1;
jaggedArray[0][1] = 2;
jaggedArray[1][0] = 3;
jaggedArray[1][1] = 4;
jaggedArray[1][2] = 5;
jaggedArray[1][3] = 6;
jaggedArray[2][0] = 7;
jaggedArray[2][1] = 8;
jaggedArray[2][2] = 9;
// Printing the jagged array
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}

Output:

12
3456
789

Explanation: This program initializes a jagged array with varying lengths for each row. The values are assigned
to each sub-array, and the nested loops are used to print the entire jagged array.

b. Accessing Elements in a Jagged Array

public class JaggedArrayAccess {


public static void main(String[] args) {
int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6, 7, 8, 9}
};

// Accessing a specific element


int element = jaggedArray[1][2]; // Accesses element in 2nd row and 3rd column
System.out.println("Element at [1][2]: " + element);
}
}

Output:

Element at [1][2]: 5

Explanation: This program demonstrates accessing a specific element in a jagged array using its row and column
indices.

c. Iterating Over a Jagged Array

public class JaggedArrayIteration {


public static void main(String[] args) {
int[][] jaggedArray = {
{10, 20},
{30, 40, 50},
{60, 70, 80, 90}
};

// Iterating through the jagged array


for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}

Output:

10 20
30 40 50
60 70 80 90

Explanation: This program uses nested loops to iterate through and print each element of the jagged array.

d. Modifying a Jagged Array

public class ModifyJaggedArray {


public static void main(String[] args) {
int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6, 7, 8}
};
// Modifying the array
jaggedArray[0][1] = 10; // Changing value in the first row
jaggedArray[2][2] = 20; // Changing value in the third row
// Printing the modified jagged array
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}
Output:
1 10
345
6 7 20

Explanation: This program modifies specific elements in the jagged array and prints the updated array.
Practice Programs
Program 1: Jagged Array with User Input

import java.util.Scanner;

public class JaggedArrayUserInput {


public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter number of rows: ");
int rows = sc.nextInt();
int[][] jaggedArray = new int[rows][];

for (int i = 0; i < rows; i++) {


System.out.print("Enter number of columns for row " + i + ": ");
int cols = sc.nextInt();
jaggedArray[i] = new int[cols];

System.out.println("Enter " + cols + " values for row " + i + ":");


for (int j = 0; j < cols; j++) {
jaggedArray[i][j] = sc.nextInt();
}
}
// Printing the jagged array
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
System.out.print(jaggedArray[i][j] + " ");
}
System.out.println();
}
}
}

Output: (Depends on user input)

Explanation: This program creates a jagged array based on user input for the number of rows and columns in
each row. It then populates and prints the array.

Program 2: Sum of Each Row in a Jagged Array

public class SumJaggedArrayRows {


public static void main(String[] args) {
int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6, 7, 8, 9}
};

// Calculating and printing the sum of each row


for (int i = 0; i < jaggedArray.length; i++) {
int sum = 0;
for (int j = 0; j < jaggedArray[i].length; j++) {
sum += jaggedArray[i][j];
}
System.out.println("Sum of row " + i + ": " + sum);
}
}
}

Output:

Sum of row 0: 3
Sum of row 1: 12
Sum of row 2: 30

Explanation: This program calculates and prints the sum of elements in each row of a jagged array.

Program 3: Maximum Value in Each Row

public class MaxInJaggedArrayRows {


public static void main(String[] args) {
int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6, 7, 8, 9}
};

// Finding and printing the maximum value in each row


for (int i = 0; i < jaggedArray.length; i++) {
int max = jaggedArray[i][0];
for (int j = 1; j < jaggedArray[i].length; j++) {
if (jaggedArray[i][j] > max) {
max = jaggedArray[i][j];
}
}
System.out.println("Max in row " + i + ": " + max);
}
}
}

Output:
Max in row 0: 2
Max in row 1: 5
Max in row 2: 9

Explanation: This program finds and prints the maximum value in each row of a jagged array.

Program 4: Jagged Array to Matrix

public class JaggedArrayToMatrix {


public static void main(String[] args) {
int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6, 7, 8, 9}
};
// Converting jagged array to matrix representation
int maxCols = 0;
for (int i = 0; i < jaggedArray.length; i++) {
if (jaggedArray[i].length > maxCols) {
maxCols = jaggedArray[i].length;
}
}
int[][] matrix = new int[jaggedArray.length][maxCols];
for (int i = 0; i < jaggedArray.length; i++) {
for (int j = 0; j < jaggedArray[i].length; j++) {
matrix[i][j] = jaggedArray[i][j];
}
}

// Printing the matrix


for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
}
}

Output:

1200
3450
6789

Explanation: This program converts a jagged array into a matrix with uniform row lengths and prints the
resulting matrix.
Do It Yourself

1. Write a Java program to create a jagged array with 3 rows where the first row has 2 columns, the
second row has 3 columns, and the third row has 4 columns. Initialize and print the array.
2. Implement a Java program that calculates and prints the sum of all elements in a jagged array.
3. Write a program that finds and prints the minimum value in each row of a jagged array.
4. Create a program that converts a jagged array into a matrix form and prints it. Ensure that missing
values are represented by zeros.
5. Write a Java program that allows the user to input the number of rows and columns for each row of a
jagged array. Populate the array with user input and print it.

Quiz

1. How do you declare a jagged array in Java?


A) int[][] array = new int[3][3];
B) int[][] array = new int[3][];
C) int[] array = new int[3][3];
D) int[][] array = new int[3][4];

Answer: B) int[][] array = new int[3][];

2. Which of the following is true about accessing elements in a jagged array?


A) The number of columns must be the same for every row.
B) Each row can have a different number of columns.
C) Elements can only be accessed in a rectangular fashion.
D) Jagged arrays do not support accessing elements.

Answer: B) Each row can have a different number of columns.

3. How can you initialize a jagged array with different lengths for each row?
A) array = new int[rows][columns];
B) array = new int[rows][]; array[row] = new int[columns];
C) array = new int[][];
D) array = new int[columns][rows];

Answer: B) array = new int[rows][]; array[row] = new int[columns];

4. What will be the output of the following code snippet?

int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6, 7}
};
System.out.println(jaggedArray[1][1]);
A) 3
B) 4
C) 5
D) 7

Answer: B) 4

5. Which of the following methods is used to iterate over a jagged array?


A) Single loop
B) Nested loops
C) Arrays.toString()
D) System.out.println()

Answer: B) Nested loops

Three-dimensional Arrays in Java


Three-dimensional arrays in Java are an extension of 2D arrays, adding a third dimension to create a 3D
structure. They are useful for storing data in a matrix-like format with multiple layers, such as for image
processing, simulations, or scientific computations.

Real-time examples
Cubes

Introduction to Three-dimensional Arrays


A three-dimensional array in Java can be thought of as an array of arrays of arrays. It is initialized with three
indices: the first for the depth (or layer), the second for the row, and the third for the column.

Syntax:

type[][][] arrayName = new type[depth][rows][columns];


Initialization:

arrayName[0] = new type[rows][columns];


arrayName[1] = new type[rows][columns];
// and so on

Example:

int[][][] threeDArray = new int[2][3][4];

Here, threeDArray is a 3D array with 2 layers, each containing 3 rows and 4 columns.

Examples
a. Declaring and Initializing a Three-dimensional Array

public class ThreeDArrayExample {


public static void main(String[] args) {
// Creating a 3D array
int[][][] threeDArray = new int[2][3][4];
// Initializing the 3D array
int value = 1;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 4; k++) {
threeDArray[i][j][k] = value++;
}
}
}

// Printing the 3D array


for (int i = 0; i < 2; i++) {
System.out.println("Layer " + i + ":");
for (int j = 0; j < 3; j++) {
for (int k = 0; k < 4; k++) {
System.out.print(threeDArray[i][j][k] + " ");
}
System.out.println();
}
System.out.println();
}
}
}

Output:
Layer 0:
1234
5678
9 10 11 12

Layer 1:
13 14 15 16
17 18 19 20
21 22 23 24

Explanation: This program initializes a 3D array with values from 1 to 24 and prints each layer in a formatted
way.

b. Accessing Elements in a Three-dimensional Array

public class AccessThreeDArray {


public static void main(String[] args) {
int[][][] threeDArray = {
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
},
{
{10, 11, 12},
{13, 14, 15},
{16, 17, 18}
}
};

// Accessing a specific element


int element = threeDArray[1][2][1]; // Element at layer 1, row 2, column 1
System.out.println("Element at [1][2][1]: " + element);
}
}

Output:

Element at [1][2][1]: 17

Explanation: This program demonstrates how to access a specific element in a 3D array using its indices.
c. Iterating Over a Three-dimensional Array

public class IterateThreeDArray {


public static void main(String[] args) {
int[][][] threeDArray = {
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
},
{
{10, 11, 12},
{13, 14, 15},
{16, 17, 18}
}
};

// Iterating through the 3D array


for (int i = 0; i < threeDArray.length; i++) {
System.out.println("Layer " + i + ":");
for (int j = 0; j < threeDArray[i].length; j++) {
for (int k = 0; k < threeDArray[i][j].length; k++) {
System.out.print(threeDArray[i][j][k] + " ");
}
System.out.println();
}
System.out.println();
}
}
}

Output:
Layer 0:
123
456
789

Layer 1:
10 11 12
13 14 15
16 17 18

Explanation: This program uses nested loops to iterate through and print each element in a 3D array.

d. Modifying a Three-dimensional Array

public class ModifyThreeDArray {


public static void main(String[] args) {
int[][][] threeDArray = {
{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
},
{
{10, 11, 12},
{13, 14, 15},
{16, 17, 18}
}
};

// Modifying the array


threeDArray[0][0][0] = 100; // Changing value in layer 0, row 0, column 0
threeDArray[1][2][2] = 200; // Changing value in layer 1, row 2, column 2

// Printing the modified array


for (int i = 0; i < threeDArray.length; i++) {
System.out.println("Layer " + i + ":");
for (int j = 0; j < threeDArray[i].length; j++) {
for (int k = 0; k < threeDArray[i][j].length; k++) {
System.out.print(threeDArray[i][j][k] + " ");
}
System.out.println();
}
System.out.println();
}
}
}

Output:

Layer 0:
100 2 3
456
789

Layer 1:
10 11 12
13 14 15
16 17 200

Explanation: This program modifies specific elements in a 3D array and prints the updated array.
Practice Programs
Program 1: Create and Initialize a 3D Array

public class CreateAndInitialize3D {


public static void main(String[] args) {
int[][][] threeDArray = new int[3][2][4];

int value = 1;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 2; j++) {
for (int k = 0; k < 4; k++) {
threeDArray[i][j][k] = value++;
}
}
}
// Print the 3D array
for (int i = 0; i < threeDArray.length; i++) {
System.out.println("Layer " + i + ":");
for (int j = 0; j < threeDArray[i].length; j++) {
for (int k = 0; k < threeDArray[i][j].length; k++) {
System.out.print(threeDArray[i][j][k] + " ");
}
System.out.println();
}
System.out.println();
}
}
}

Output:
Layer 0:
1234
5678

Layer 1:
9 10 11 12
13 14 15 16

Layer 2:
17 18 19 20
21 22 23 24

Explanation: This program creates a 3D array with 3 layers, 2 rows, and 4 columns. It initializes the array with
sequential values and prints it.
Program 2: Sum of Elements in a 3D Array

public class Sum3DArray {


public static void main(String[] args) {
int[][][] threeDArray = {
{
{1, 2, 3},
{4, 5, 6}
},
{
{7, 8, 9},
{10, 11, 12}
}
};
int totalSum = 0;
for (int i = 0; i < threeDArray.length; i++) {
for (int j = 0; j < threeDArray[i].length; j++) {
for (int k = 0; k < threeDArray[i][j].length; k++) {
totalSum += threeDArray[i][j][k];
}
}
}
System.out.println("Total sum of elements: " + totalSum);
}
}

Output:

Total sum of elements: 78

Explanation: This program calculates the sum of all elements in a 3D array.

Program 3: Find the Maximum Element in a 3D Array

public class MaxElement3D {


public static void main(String[] args) {
int[][][] threeDArray = {
{
{1, 2, 3},
{4, 5, 6}
},
{
{7, 8, 9},
{10, 11, 12}
}
};

int maxElement = Integer.MIN_VALUE;


for (int i = 0; i < threeDArray.length; i++) {
for (int j = 0; j < threeDArray[i].length; j++) {
for (int k = 0; k < threeDArray[i][j].length; k++) {
if (threeDArray[i][j][k] > maxElement) {
maxElement = threeDArray[i][j][k];
}
}
}
}

System.out.println("Maximum element: " + maxElement);


}
}

Output:

Maximum element: 12

Explanation: This program finds and prints the maximum value in a 3D array.

Program 4: Transpose of a 3D Array

public class Transpose3D {


public static void main(String[] args) {
int[][][] threeDArray = {
{
{1, 2, 3},
{4, 5, 6}
},
{
{7, 8, 9},
{10, 11, 12}
}
};
int depth = threeDArray.length;
int rows = threeDArray[0].length;
int cols = threeDArray[0][0].length;
int[][][] transposed = new int[cols][rows][depth];

for (int i = 0; i < depth; i++) {


for (int j = 0; j < rows; j++) {
for (int k = 0; k < cols; k++) {
transposed[k][j][i] = threeDArray[i][j][k];
}
}
}

// Print the transposed 3D array


for (int i = 0; i < transposed.length; i++) {
System.out.println("Layer " + i + ":");
for (int j = 0; j < transposed[i].length; j++) {
for (int k = 0; k < transposed[i][j].length; k++) {
System.out.print(transposed[i][j][k] + " ");
}
System.out.println();
}
System.out.println();
}
}
}

Output:
Layer 0:
14
7 10

Layer 1:
25
8 11

Layer 2:
36
9 12

Explanation: This program creates the transpose of a 3D array, swapping layers, rows, and columns.

Do It Yourself

1. Write a Java program to create a 3D array of size 2x3x4, initialize it with sequential numbers starting
from 1, and print the array layer by layer.
2. Implement a Java program that calculates the sum of all elements in a 3D array. The dimensions and
values should be specified by you.
3. Write a program that finds and prints the minimum value in a 3D array.
4. Create a program that reverses the order of layers in a 3D array and prints the result.
5. Write a Java program to multiply two 3D arrays (of compatible sizes) and print the resulting array.

Quiz

1. How do you declare a 3D array in Java?


A) int[][] array = new int[2][3][4];
B) int[][][] array = new int[2][3][4];
C) int[] array = new int[2][3][4];
D) int[][] array = new int[2][3];

Answer: B) int[][][] array = new int[2][3][4];


2. How do you access an element in a 3D array?
A) array[index1][index2][index3]
B) array[index1, index2, index3]
C) array(index1, index2, index3)
D) array[index1][index2]

Answer: A) array[index1][index2][index3]

3. What will be the output of the following code snippet?

int[][][] array = {
{
{1, 2},
{3, 4}
},
{
{5, 6},
{7, 8}
}
};
System.out.println(array[1][1][1]);
A) 6
B) 7
C) 8
D) 5

Answer: C) 8

4. How can you initialize a 3D array with values?


A) Using nested loops
B) Directly in the declaration
C) Using a single-dimensional array
D) Both A and B

Answer: D) Both A and B

5. What is the output of the following code?

int[][][] array = new int[2][2][2];


System.out.println(array[0][1][0]);
A) 0
B) 1
C) Error
D) 2
Answer: A) 0
Arrays as Vectors

In Java, arrays and vectors (via the Vector class) are foundational structures for storing and manipulating
collections of elements. Arrays are fixed in size and type, while vectors (using Vector or ArrayList) provide a
dynamic, resizable alternative.

Introduction to Arrays and Vectors


Arrays:
• Arrays are collections of elements of the same type, stored in contiguous memory locations.
• Syntax: type[] arrayName = new type[size];
• Example: int[] numbers = new int[5];

Vectors (via Vector class):


• Vector is a part of Java's standard library and provides a dynamic array that can grow or shrink in size.
• Syntax: Vector<type> vectorName = new Vector<type>();
• Example: Vector<String> vector = new Vector<String>();
Converting Arrays to Vectors
Here are three methods to convert an array to a vector:

a. Using Collections.addAll() Method

Syntax:

public static boolean addAll(Collection<? super T> c, T... elements)

Example:

import java.util.*;
public class ArrayToVectorUsingAddAll {
public static void main(String[] args) {
Integer[] numbers = { 1, 2, 3, 4, 5 };
Vector<Integer> vector = new Vector<Integer>();
Collections.addAll(vector, numbers);
System.out.println("Vector using Collections.addAll(): " + vector);
}
}

Output:

Vector using Collections.addAll(): [1, 2, 3, 4, 5]

Explanation: This example demonstrates converting an array of integers to a Vector using the
Collections.addAll() method.
b. Using Arrays.asList() Method

Syntax:

public static <T> List<T> asList(T... a)

Example:

import java.util.*;

public class ArrayToVectorUsingAsList {


public static void main(String[] args) {
String[] words = { "Java", "Python", "JavaScript" };
Vector<String> vector = new Vector<String>(Arrays.asList(words));

System.out.println("Vector using Arrays.asList(): " + vector);


}
}

Output:

Vector using Arrays.asList(): [Java, Python, JavaScript]

Explanation: This example shows how to convert an array of strings into a Vector by first converting it into a
List using Arrays.asList().

c. Using Loop

Example:

import java.util.*;

public class ArrayToVectorUsingLoop {


public static void main(String[] args) {
Double[] numbers = { 1.1, 2.2, 3.3, 4.4 };
Vector<Double> vector = new Vector<Double>();

for (Double number : numbers) {


vector.addElement(number);
}
System.out.println("Vector using loop: " + vector);
}
}

Output:

Vector using loop: [1.1, 2.2, 3.3, 4.4]


Explanation: This example demonstrates converting an array of doubles into a Vector by manually adding each
element using a loop.

Practice Programs
Program 1: Convert Array of Characters to Vector

import java.util.*;

public class CharArrayToVector {


public static void main(String[] args) {
Character[] chars = { 'A', 'B', 'C', 'D' };
Vector<Character> vector = new Vector<Character>(Arrays.asList(chars));

System.out.println("Vector from Character array: " + vector);


}
}

Output:

Vector from Character array: [A, B, C, D]

Program 2: Convert Array of Floats to Vector Using Loop

import java.util.*;

public class FloatArrayToVector {


public static void main(String[] args) {
Float[] floats = { 3.14f, 1.61f, 2.71f };
Vector<Float> vector = new Vector<Float>();
for (Float value : floats) {
vector.addElement(value);
}
System.out.println("Vector from Float array: " + vector);
}
}

Output:

Vector from Float array: [3.14, 1.61, 2.71]

Program 3: Convert Array of Booleans to Vector

import java.util.*;

public class BooleanArrayToVector {


public static void main(String[] args) {
Boolean[] booleans = { true, false, true };
Vector<Boolean> vector = new Vector<Boolean>();
Collections.addAll(vector, booleans);
System.out.println("Vector from Boolean array: " + vector);
}
}

Output:

Vector from Boolean array: [true, false, true]

Program 4: Convert Array of Longs to Vector

import java.util.*;
public class LongArrayToVector {
public static void main(String[] args) {
Long[] longs = { 100L, 200L, 300L };
Vector<Long> vector = new Vector<Long>();

for (Long number : longs) {


vector.add(number);
}
System.out.println("Vector from Long array: " + vector);
}
}

Output:

Vector from Long array: [100, 200, 300]

Do It Yourself

1. Write a Java program to convert an array of integers to a Vector using the Collections.addAll() method.
Print the Vector after conversion.
2. Implement a Java program that converts an array of Double values to a Vector using Arrays.asList()
and prints the Vector.
3. Create a Java program that converts an array of String elements to a Vector using a loop. Print the
Vector after adding all elements.
4. Write a Java program that dynamically converts an array of Boolean values to a Vector using both
Collections.addAll() and a loop. Compare and print the Vector results from both methods.
5. Write a Java program that initializes a Vector with an array of Character elements. Use the addAll()
method to add more characters and print the final Vector.
Quiz

1. Which method is used to add all elements of an array to a Vector?


A) vector.addAll()
B) vector.add()
C) Collections.addAll()
D) vector.insertAll()

Answer: C) Collections.addAll()

2. What does the Arrays.asList() method return?


A) An ArrayList
B) A Vector
C) A List
D) An Array
Answer: C) A List

3. How can you convert an array to a Vector using a loop?


A) vector.addAll(Arrays.asList(array));
B) for (T element : array) vector.addElement(element);
C) vector.add(array);
D) vector = new Vector<>(Arrays.asList(array));

Answer: B) for (T element : array) vector.addElement(element);

4. What will be the output of the following code?


Integer[] numbers = { 10, 20, 30 };
Vector<Integer> vector = new Vector<Integer>(Arrays.asList(numbers));
System.out.println(vector);
A) [10, 20, 30]
B) [10, 20]
C) [30, 20, 10]
D) []

Answer: A) [10, 20, 30]

5. Which method is NOT used to convert an array to a Vector?


A) Using Collections.addAll()
B) Using Arrays.asList()
C) Using Collections.add()
D) Using a loop

Answer: C) Using Collections.add()


Introduction to Inheritance in Java
Inheritance is one of the core concepts in Object-Oriented Programming (OOP) and is a mechanism that allows
a new class to inherit properties and behaviors (methods) from an existing class. This concept helps in code
reusability and establishing a hierarchical relationship between classes.

1. What is Inheritance?
Inheritance allows a class (known as the child or subclass) to inherit fields and methods from another class
(known as the parent or superclass). This concept promotes code reuse and method overriding, facilitating a
more organized and hierarchical structure of code.

Key Concepts:

• Superclass (Parent Class): The class from which properties and methods are inherited.
• Subclass (Child Class): The class that inherits properties and methods from the superclass.
• extends Keyword: - Used to establish an inheritance relationship.
2. Syntax
To create a subclass that inherits from a superclass, use the extends keyword.

class Superclass {
// Superclass code
}

class Subclass extends Superclass {


// Subclass code
}
3. Why Do We Need Java Inheritance?
• Code Reusability: Inheritance allows subclasses to reuse the code written in the superclass. This means
that you can create new classes with the same functionality as existing ones without duplicating code.
• Method Overriding: Inheritance enables method overriding, which is a way to provide specific
implementations of methods in the subclass that are already defined in the superclass. This supports
runtime polymorphism.
• Abstraction: Inheritance allows abstraction by hiding the implementation details in the superclass while
providing a simplified interface to the user.
4. Important Terminologies Used in Java Inheritance
• Class: A template or blueprint from which objects are created. It defines common characteristics and
behaviors.
• Super Class/Parent Class: The class whose features are inherited. It is also known as the base class.
• Sub Class/Child Class: The class that inherits from another class. It can add new fields and methods in
addition to those inherited from the superclass.
• Reusability: The ability to use existing class code to create new classes, thereby avoiding code
duplication.
5. Example: Basic Inheritance

Superclass:

// Animal.java
public class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}

Subclass:

// Dog.java
public class Dog extends Animal {
void bark() {
System.out.println("The dog barks.");
}
}

Main Program:

// Main.java
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Method from superclass
dog.bark(); // Method from subclass
}
}

Output:
This animal eats food.
The dog barks.

Explanation: In this example, Dog inherits the eat() method from Animal and also has its own method bark().
Inheritance Types
Java supports several types of inheritance, each with its unique characteristics. Below are the different types of
inheritance supported by Java.
1. Single Inheritance
2. Multilevel Inheritance
3. Hierarchical Inheritance
4. Multiple Inheritance
5. Hybrid Inheritance

1. Single Inheritance
Definition: In single inheritance, a subclass (child class) is derived from only one superclass (parent class). The
subclass inherits the properties and behavior (methods) of a single parent class.

Syntax:

class Superclass {
// Fields and methods
}

class Subclass extends Superclass {


// Additional fields and methods
}

Example:
Sure! Here's a different example using a parent class Vehicle and a child class Car:

// Parent class
class Vehicle {
public void startEngine() {
System.out.println("Engine started");
}
}

// Child class
class Car extends Vehicle {
public void honk() {
System.out.println("Car horn honking");
}
}

// Driver class
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.startEngine(); // Inherited method
myCar.honk(); // Method in subclass
}
}

Output:
Engine started
Car horn honking

In this example:

• Vehicle is the parent class with a method startEngine().


• Car is the child class that extends Vehicle and adds a new method honk().
• The Main class creates an instance of Car, then calls both the inherited method startEngine() and the
subclass-specific method honk().

Picture:

2. Multilevel Inheritance
Definition: In multilevel inheritance, a class is derived from another derived class, forming a chain of
inheritance. The base class is at the top of the chain, with subsequent derived classes extending the previous
class.

Syntax:

class Grandparent {
// Fields and methods
}

class Parent extends Grandparent {


// Additional fields and methods
}

class Child extends Parent {


// Additional fields and methods
}

Example:
Here's a modified version of the example with a different scenario. In this example, we will use a grandparent
class Animal, a parent class Bird, and a child class Sparrow:

// Grandparent class
class Animal {
public void makeSound() {
System.out.println("Some sound");
}
}

// Parent class
class Bird extends Animal {
public void fly() {
System.out.println("Flies in the sky");
}
}

// Child class
class Sparrow extends Bird {
public void chirp() {
System.out.println("Chirps melodiously");
}
}

// Driver class
public class Main {
public static void main(String[] args) {
Sparrow mySparrow = new Sparrow();
mySparrow.makeSound(); // Inherited from Animal
mySparrow.fly(); // Inherited from Bird
mySparrow.chirp(); // Method in Sparrow
}
}

Output:

Some sound
Flies in the sky
Chirps melodiously

In this modified example:

• Animal is the grandparent class with a method makeSound().


• Bird is the parent class that extends Animal and adds a method fly().
• Sparrow is the child class that extends Bird and adds a method chirp().
• The Main class creates an instance of Sparrow and calls the inherited methods makeSound() and fly(),
as well as the subclass-specific method chirp().
Picture:

Explanation: The Three class inherits methods from both One and Two, demonstrating the chain of inheritance.

3. Hierarchical Inheritance
Definition: In hierarchical inheritance, one superclass is inherited by multiple subclasses. All subclasses share a
common base class.

Syntax:

class Superclass {
// Fields and methods
}
class Subclass1 extends Superclass {
// Additional fields and methods
}
class Subclass2 extends Superclass {
// Additional fields and methods
}

Example:

// Superclass
class A {
public void print_A() {
System.out.println("Class A");
}
}
// Subclass 1
class B extends A {
public void print_B() {
System.out.println("Class B");
}
}
// Subclass 2
class C extends A {
public void print_C() {
System.out.println("Class C");
}
}

// Driver Class
public class Test {
public static void main(String[] args) {
B obj_B = new B();
obj_B.print_A(); // Inherited from A
obj_B.print_B(); // Method in B

C obj_C = new C();


obj_C.print_A(); // Inherited from A
obj_C.print_C(); // Method in C
}
}

Output:

Class A
Class B
Class A
Class C

Picture:

Explanation: Classes B and C both inherit the print_A() method from class A, each with their own additional
methods.

4. Multiple Inheritance (Through Interfaces)


Definition: Java does not support multiple inheritance with classes but allows it through interfaces. A class can
implement multiple interfaces, inheriting behavior from multiple sources.

Syntax:

interface Interface1 {
void method1();
}

interface Interface2 {
void method2();
}

class ImplementingClass implements Interface1, Interface2 {


public void method1() {
System.out.println("Implementation of method1.");
}

public void method2() {


System.out.println("Implementation of method2.");
}
}

Example:
In Java, multiple inheritance is achieved through interfaces since a class can implement multiple interfaces.
Here’s an example demonstrating multiple inheritance using interfaces:

// First interface
interface Animal {
void eat();
}

// Second interface
interface Pet {
void play();
}

// Class implementing both interfaces


class Dog implements Animal, Pet {
public void eat() {
System.out.println("Dog is eating");
}

public void play() {


System.out.println("Dog is playing");
}
}

// Driver class
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.eat(); // Implemented from Animal interface
myDog.play(); // Implemented from Pet interface
}
}

Output:
Dog is eating
Dog is playing

In this example:

• Animal and Pet are two interfaces with methods eat() and play(), respectively.
• Dog is a class that implements both Animal and Pet interfaces, providing concrete implementations for
both eat() and play() methods.
• The Main class creates an instance of Dog and calls both methods eat() and play().

Picture:

Explanation: The Child class implements methods from both One and Two interfaces.

5. Hybrid Inheritance
Definition: Hybrid inheritance is a mix of two or more inheritance types, such as combining multilevel and
hierarchical inheritance. Java does not support hybrid inheritance involving multiple inheritance through
classes, but it can be achieved through interfaces.

Example:

// Interface for Multiple Inheritance


interface InterfaceA {
void methodA();
}

interface InterfaceB {
void methodB();
}

class Base {
void baseMethod() {
System.out.println("Base method");
}
}

// Hybrid class
class Derived extends Base implements InterfaceA, InterfaceB {
public void methodA() {
System.out.println("Method A");
}

public void methodB() {


System.out.println("Method B");
}
}

// Driver class
public class Test {
public static void main(String[] args) {
Derived obj = new Derived();
obj.baseMethod(); // Method from Base
obj.methodA(); // Method from InterfaceA
obj.methodB(); // Method from InterfaceB
}
}

Output:

Base method
Method A
Method B

Picture:

Explanation: The Derived class demonstrates hybrid inheritance by combining class inheritance and interface
inheritance.

Do It Yourself

1. Write a Java program where a Person class has fields name and age, and a subclass Employee that
adds an employeeID field. Implement methods to display all the information.
2. Create a Device class with a method powerOn(). Extend it to create a SmartDevice class with a
connect() method. Further, extend SmartDevice to create a Smartphone class with a call() method.
Demonstrate usage in the main() method.
3. Implement a School class with a location field and a showLocation() method. Create subclasses
Student and Teacher that add their own fields and methods. Show inheritance in the main() method.
4. Define interfaces Flyable and Swimmable with methods fly() and swim() respectively. Implement these
interfaces in a Duck class. Demonstrate both functionalities in the main() method.
5. Create a Vehicle class with a speed field. Extend it to Car and Bike classes. Implement an interface
Electric with methods charge() and plugIn(). Demonstrate hybrid inheritance by creating an ElectricCar
class that extends Car and implements Electric.

Quiz

1. Which type of inheritance is demonstrated when a class is inherited by more than one subclass?
a) Single Inheritance
b) Multilevel Inheritance
c) Hierarchical Inheritance
d) Multiple Inheritance

Answer: c) Hierarchical Inheritance

2. What is the key characteristic of multilevel inheritance?


a) A class inherits from multiple classes.
b) A class is derived from another derived class.
c) A class inherits from a single parent class.
d) Multiple subclasses share a common superclass.

Answer: b) A class is derived from another derived class.

3. Which of the following Java constructs supports multiple inheritance?


a) Classes
b) Interfaces
c) Both classes and interfaces
d) None of the above

Answer: b) Interfaces

4. In which type of inheritance does a class inherit properties from two or more parent classes?
a) Single Inheritance
b) Multilevel Inheritance
c) Hierarchical Inheritance
d) Multiple Inheritance

Answer: d) Multiple Inheritance

5. Which statement is TRUE about hybrid inheritance in Java?


a) Hybrid inheritance is achieved through multiple inheritance of classes.
b) Hybrid inheritance combines multiple inheritance with interface inheritance.
c) Hybrid inheritance is not possible in Java.
d) Hybrid inheritance can only be implemented using a single inheritance type.

Answer: b) Hybrid inheritance combines multiple inheritance with interface inheritance.


Object Class
Introduction
In Java programming, the Object class is fundamental as it serves as the root class for all other classes. Every
class in Java either directly or indirectly extends the Object class. Understanding the Object class is crucial for
effective Java programming as it allows for the implementation of essential functionalities.

Overview
The Object class is part of the java.lang package and is the ultimate superclass of all classes in Java. Every class
inherits from Object, either explicitly or implicitly, which provides common functionalities and facilitates
features like polymorphism.

Object Class in Java: Description and Characteristics


• Universal Superclass: The Object class is the universal superclass for all classes. Any class that does not
extend another class directly inherits from Object.
• Base for Polymorphism: The Object class provides the foundation for polymorphism, allowing objects
of different classes to be treated as objects of the Object class.
• Default Methods: The Object class provides default implementations of several methods, which can be
overridden to customize behavior.

Methods and Properties of the Object Class


The Object class provides several key methods:

1. equals(Object obj): Compares the current object with the specified object for equality.

Strqaing text1 = "Hello";


String text2 = "Hello";
System.out.println(text1.equals(text2)); // true

2. hashCode(): Returns a unique integer value associated with the object, useful for hashing-based data
structures.
String text = "Hello";
System.out.println(text.hashCode()); // Example output: -907987551

3. toString(): Returns a string representation of the object. By default, it returns the class name followed
by the object's hash code.

String text = "Hello";


System.out.println(text.toString()); // "Hello"

4. clone(): Creates a shallow copy of the object. The class must implement Cloneable for this method to
work.

// String class does not support cloning.

5. getClass(): Returns the runtime class of the object.

String text = "Hello";


System.out.println(text.getClass()); // class java.lang.String

6. wait(), notify(), notifyAll(): Used for thread synchronization and inter-thread communication. These
methods are used in conjunction with the synchronized keyword.
How to Use the Object Class in Java Programming
The Object class methods can be invoked on any Java object. Here's an example demonstrating the use of
toString():

public class Car {


private String brand;
private int year;

public Car(String brand, int year) {


this.brand = brand;
this.year = year;
}

@Override
public String toString() {
return "Car(brand='" + brand + "', year=" + year + ")";
}

public static void main(String[] args) {


Car myCar = new Car("Toyota", 2022);
System.out.println(myCar.toString());
}
}

Output:

Car(brand='Toyota', year=2022)
Object Class Methods: Description and Examples
1. hashCode() Method
import java.util.Objects;

public class Book {


private String title;
private String author;

public Book(String title, String author) {


this.title = title;
this.author = author;
}

@Override
public int hashCode() {
return Objects.hash(title, author);
}
public static void main(String[] args) {
Book book1 = new Book("Java Programming", "John Doe");
Book book2 = new Book("Python Basics", "Jane Smith");

System.out.println(book1.hashCode());
System.out.println(book2.hashCode());
}
}

2. toString() Method
The toString() method returns a string representation of the object. It is useful for debugging and logging
purposes.

3. equals(Object obj) Method


public class Point {
private int x;
private int y;

public Point(int x, int y) {


this.x = x;
this.y = y;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Point other = (Point) obj;
return x == other.x && y == other.y;
}
public static void main(String[] args) {
Point point1 = new Point(2, 3);
Point point2 = new Point(2, 3);
Point point3 = new Point(4, 5);

System.out.println(point1.equals(point2)); // true
System.out.println(point1.equals(point3)); // false
}
}
Best Practices for Using Object Class Methods
• Override equals() and hashCode() Together: Ensure that equals() and hashCode() are overridden
together to maintain consistency.
• Provide Meaningful toString() Representations: Override toString() to provide a useful description of
the object.
• Use instanceof for Type Checking: Use instanceof to check types in the overridden equals() method.
Overriding Object Class Methods
1. Overriding equals() Method

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Employee other = (Employee) obj;
return Objects.equals(name, other.name) && age == other.age;
}

2. Overriding hashCode() Method

@Override
public int hashCode() {
return Objects.hash(name, age);
}
Object Class and Inheritance
By default, if a class does not explicitly extend another class, it extends Object. This allows for features such as
polymorphism and code reuse across different classes.
Benefits of Object Class in Java
• Code Reusability: Methods and properties of the Object class are reused across different classes.
• Polymorphism: Allows objects of different classes to be treated as Object types.
• Reflection and Introspection: The getClass() method enables dynamic class information retrieval.

The Object class is a cornerstone of Java programming. Understanding its methods and proper usage is essential
for effective Java development. By mastering the Object class, you can enhance code reusability, implement
polymorphism, and leverage powerful object-oriented features.

Do It Yourself

1. Implement a class Student with name, id, and grade attributes. Override the toString(), equals(), and
hashCode() methods.
2. Write a program that creates an array of objects of a custom class and demonstrates how the equals()
and hashCode() methods are used in a HashSet.
3. Create a class Rectangle with length and width attributes. Override the toString() method to return the
area of the rectangle.
4. Implement a class Vehicle with make and model attributes. Write a program to demonstrate the usage
of `getClass()` method.

Quiz

1. Which method in the Object class is used to obtain a string representation of an object?
A) hashCode()
B) equals()
C) toString()
D) clone()

Answer: C) toString()

2. What is the return type of the hashCode() method in the Object class?
A) String
B) int
C) void
D) boolean

Answer: B) int

3. Which method must be overridden to ensure the correct behavior in hash-based collections?
A) clone()
B) toString()
C) hashCode()
D) getClass()

Answer: C) hashCode()

4. What does the getClass() method return?


A) Class name as a String
B) An integer representing the class
C) The runtime class of the object
D) The superclass of the object

Answer: C) The runtime class of the object

5. If a class overrides equals(), what should be done with the hashCode() method?
A) It should be left as default
B) It should be overridden as well
C) It should be set to zero
D) It should be removed

Answer: B) It should be overridden as well


Inhibiting Inheritance of a Class Using final
In Java, inheritance is a fundamental concept that allows one class to inherit properties and methods from
another. However, there are scenarios where you might want to prevent a class from being extended by other
classes. This is where the final keyword comes into play. By marking a class as final, you can effectively inhibit
its inheritance. This ensures that the class's implementation remains unchanged and secure from modification
through subclassing.

Syntax
To declare a class as final, simply use the final keyword in the class declaration:

final class ClassName {


// class body
}

Once a class is declared as final, no other class can extend it.


Characteristics of a final Class
1. Inhibits Subclassing: A final class cannot be extended. This is useful when you want to create immutable
classes or ensure that a class's behavior is not altered through inheritance.
2. Security and Integrity: Preventing inheritance can protect the integrity of the class and prevent
unintended modifications.
3. Optimizations: The Java Virtual Machine (JVM) can optimize final classes since it knows their structure
cannot be altered by inheritance.
Examples
Example 1: Simple final Class
final class MathConstants {
public static final double PI = 3.14159;
public static final double E = 2.71828;
}

// This will cause a compile-time error


// class ExtendedMathConstants extends MathConstants { }

In this example, MathConstants is a final class, so it cannot be extended. Attempting to do so will result in a
compile-time error.
Example 2: final Class with Methods
final class Utility {
public static void printMessage(String message) {
System.out.println(message);
}
}

public class Test {


public static void main(String[] args) {
Utility.printMessage("Hello, World!");
}
}
Here, Utility is a final class with a static method. This method can be used directly without allowing further
extension of the Utility class.
How to Use final Class in Java Programming
• Designing Immutable Classes: Use the final keyword to design classes whose instances should not be
modified once created.
• Security: Prevent inheritance of classes that contain critical or sensitive logic that should not be altered.
• Performance: Some performance optimizations can be applied by the JVM for final classes.

Practice Programs
1. Below is an example that demonstrates how to define a final class with some static fields, and then an
attempt to extend it in another class, which will result in a compiler error.
Example Code
// Define a final class with static fields
final class Configuration {
public static final String APP_NAME = "MyApplication";
public static final int MAX_USERS = 100;
public static final boolean DEBUG_MODE = true;

// Static method
public static void printConfig() {
System.out.println("Application Name: " + APP_NAME);
System.out.println("Max Users: " + MAX_USERS);
System.out.println("Debug Mode: " + DEBUG_MODE);
}
}

// Attempt to extend the final class


class ExtendedConfig extends Configuration { // Compiler error occurs here
// This class will never compile because Configuration is a final class
}

a. Marked as final, which means it cannot be extended.


b. Contains static fields like APP_NAME, MAX_USERS, and DEBUG_MODE to represent
configuration details.
c. Includes a static method printConfig() to print the configuration values.

2. Immutable Class Example: Write a final class named Point with x and y coordinates. Include methods
to access these coordinates but no methods to modify them.

final class Point {


private final int x;
private final int y;

public Point(int x, int y) {


this.x = x;
this.y = y;
}

public int getX() {


return x;
}

public int getY() {


return y;
}
}
public class TestPoint {
public static void main(String[] args) {
Point p = new Point(3, 4);
System.out.println("X coordinate: " + p.getX());
System.out.println("Y coordinate: " + p.getY());

// p.x = 5; // Compilation error: cannot assign a value to final variable 'x'


}
}

The final keyword in Java is a powerful tool for controlling class inheritance. By declaring a class as final, you
can prevent it from being subclassed, ensuring the integrity and security of its implementation. Understanding
when and how to use the final keyword is essential for effective Java programming and design.

Do It Yourself

1. Write a final class named Constants with constant values for PI and E. Attempt to extend this class in
another class and describe the error.
2. Implement a final class named Employee with private fields for name and id. Provide a constructor and
getter methods but no setters.
3. Explain the effect of marking a class as final on inheritance. Provide an example to illustrate your
explanation.
4. Discuss how marking a class as final can influence performance optimizations in the JVM.
5. Design a final class for a configuration settings manager that any other class should not alter.

Quiz

1. What happens if you try to extend a final class?


A) The subclass inherits all members of the final class.
B) The subclass can override methods of the final class.
C) The code will compile but will not run.
D) The code will not compile.

Answer: D) The code will not compile.

2. Which of the following classes can be declared final?


A) Abstract class
B) Interface
C) Regular class
D) All of the above

Answer: C) Regular class

3. Given the following class declaration, what will the compiler output if you attempt to extend it?

final class Example {


// class body
}
A) A runtime error
B) A compile-time error
C) The class will extend successfully
D) None of the above

Answer: B) A compile-time error

4. What is the main benefit of declaring a class as final?


A) It allows modification of the class.
B) It prevents other classes from inheriting it.
C) It makes the class abstract.
D) It allows dynamic method dispatch.

Answer: B) It prevents other classes from inheriting it.

5. In which scenario is it appropriate to use a final class?


A) When you want to create a class that should not be subclassed.
B) When you want to allow inheritance but prevent method overriding.
C) When you want to create an interface.
D) When you want to create an abstract class.

Answer: A) When you want to create a class that should not be subclassed.

Access Control and Inheritance in Java


Access control is a fundamental concept in Java that defines the visibility and accessibility of classes,
methods, and fields within an application. Proper use of access control ensures that classes and their
members are used in the intended manner, enhancing encapsulation and security. Inheritance allows
one class to acquire the properties and behaviors of another class. Understanding how access control
interacts with inheritance is crucial for designing robust and maintainable Java applications.

Access Modifiers in Java


Java provides four primary access modifiers that determine the visibility of classes, methods, and fields:

1. public: The member or class is accessible from any other class.


2. protected: The member is accessible within its own package and by subclasses (even if they are in
different packages).
3. default (no modifier): The member is accessible only within its own package.
4. private: The member is accessible only within its own class.

Syntax
1. Public Access Modifier

public class MyClass {


public int publicField;
public void publicMethod() {
// method body
}
}

2. Protected Access Modifier

public class ParentClass {


protected int protectedField;
protected void protectedMethod() {
// method body
}
}

3. Default Access Modifier

class PackageClass {
int defaultField;
void defaultMethod() {
// method body
}
}

4. Private Access Modifier

public class MyClass {


private int privateField;
private void privateMethod() {
// method body
}
}
Access Control and Inheritance
When it comes to inheritance, access control modifiers play a crucial role in determining which members of a
superclass are inherited by a subclass:

1. Public Members: Accessible from anywhere, including subclasses.


2. Protected Members: Accessible within the same package and by subclasses, regardless of their package.
3. Default Members: Accessible only within the same package. Subclasses in different packages cannot
access default members.
4. Private Members: Not accessible from subclasses. They are only accessible within the class where they
are defined.

Example: Access Control in Inheritance


// Superclass
public class Animal {
public String name;
protected int age;
int weight; // default access
private String color;

public void makeSound() {


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

protected void eat() {


System.out.println("Eating...");
}

void sleep() {
System.out.println("Sleeping...");
}

private void walk() {


System.out.println("Walking...");
}
}

// Subclass
public class Dog extends Animal {
public void displayInfo() {
System.out.println("Name: " + name); // public field accessible
System.out.println("Age: " + age); // protected field accessible
// System.out.println("Weight: " + weight); // default field not accessible (if in a different package)
// System.out.println("Color: " + color); // private field not accessible
}

@Override
public void makeSound() {
System.out.println("Bark");
}

// @Override
// protected void walk() { // private method not accessible
// System.out.println("Dog walking...");
// }
}

How to Use Access Control with Inheritance


• Designing APIs: Use public methods for the functionality that needs to be exposed and protected
methods for functionality that subclasses need to use.
• Encapsulation: Use private fields and methods to encapsulate the internal state and behavior of a class.
• Package Organization: Use default access for classes and members that are intended to be used within
the same package but not exposed to other packages.

Practice Programs
1. Access Control Test

Create a superclass with various access modifiers and a subclass that tries to access these members. Observe
which members are accessible and which are not.

// Superclass
public class Super {
public int pubField = 1;
protected int proField = 2;
int defField = 3; // default access
private int priField = 4;

public void pubMethod() {}


protected void proMethod() {}
void defMethod() {}
private void priMethod() {}
}

// Subclass
public class Sub extends Super {
public void testAccess() {
System.out.println(pubField); // Accessible
System.out.println(proField); // Accessible
System.out.println(defField); // Accessible if in the same package
// System.out.println(priField); // Not Accessible

pubMethod(); // Accessible
proMethod(); // Accessible
defMethod(); // Accessible if in the same package
// priMethod(); // Not Accessible
}
}

2. Encapsulation Example

Design a class that uses private fields and provide public methods to access these fields. Create a subclass that
tries to interact with the superclass's fields through public methods.

public class Person {


private String name;
private int age;

public void setName(String name) {


this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}

public class Student extends Person {


public void displayInfo() {
setName("John");
setAge(20);
System.out.println("Name: " + getName());
System.out.println("Age: " + getAge());
}
}

Understanding access control and its interaction with inheritance is essential for writing robust Java
applications. By properly using access modifiers, you can ensure that your classes and their members are
encapsulated, secure, and correctly exposed or hidden as needed. This promotes better design practices and
helps maintain the integrity of your code.

Do It Yourself

1. Access Control Analysis: Given a superclass with fields and methods using all access modifiers, write a
subclass and determine which fields and methods are accessible.
2. Encapsulation Exercise: Implement a class with private fields and provide public getter and setter
methods. Write a subclass that uses these methods to access and modify the fields.
3. Inheritance and Access Control: Explain how access control affects inheritance. Provide examples
demonstrating public, protected, default, and private access in inheritance.
4. Modify Visibility: Change the access level of certain fields and methods in a class and observe how these
changes affect subclass behavior.
5. Class Design: Design a class hierarchy where a superclass provides general methods and a subclass
extends it with more specific implementations. Use different access levels for methods and fields to
control visibility.

Quiz

1. Which access modifier allows a member to be accessible from any class?


A) protected
B) private
C) default
D) public
Answer: D) public

2. Which access modifier allows a member to be accessed only within its own package and subclasses?
A) private
B) protected
C) default
D) public
Answer: B) protected

3. If a class has a private field, how can this field be accessed in a subclass?
A) Directly, if the subclass is in the same package.
B) Directly, if the subclass is in a different package.
C) Through a public method in the superclass.
D) Through reflection only.
Answer: C) Through a public method in the superclass.

4. Which of the following is NOT accessible in a subclass?


A) protected fields
B) default fields (if in a different package)
C) public methods
D) private methods
Answer: D) private methods

5. What will be the output if you try to access a default field from a subclass located in a different
package?
A) The field will be accessible.
B) The field will not be accessible.
C) The field will be accessible only through reflection.
D) The compiler will ignore the field.

Answer: B) The field will not be accessible.


Multilevel Inheritance
Introduction
Multilevel inheritance is a type of inheritance in object-oriented programming where a class is derived from
another derived class, forming a hierarchy. This means a class can inherit from another class that is itself derived
from another class. This concept allows for the creation of a chain of classes, each inheriting the properties and
methods of the class above it.
Syntax
In Java, the syntax for multilevel inheritance involves creating a chain of classes where each class extends the
previous class:

// Base class
class A {
void methodA() {
System.out.println("Method in class A");
}
}

// Derived class from A


class B extends A {
void methodB() {
System.out.println("Method in class B");
}
}

// Further derived class from B


class C extends B {
void methodC() {
System.out.println("Method in class C");
}
}
Example
Let's illustrate multilevel inheritance with a practical example of a class hierarchy representing different types
of employees in a company:

1. Base Class: Employee


2. Intermediate Class: Manager (inherits from Employee)
3. Derived Class: TeamLead (inherits from Manager)

// Base class
class Employee {
String name;
int id;

Employee(String name, int id) {


this.name = name;
this.id = id;
}

void displayInfo() {
System.out.println("Name: " + name);
System.out.println("ID: " + id);
}
}

// Derived class
class Manager extends Employee {
String department;

Manager(String name, int id, String department) {


super(name, id);
this.department = department;
}

void displayManagerInfo() {
displayInfo();
System.out.println("Department: " + department);
}
}

// Further derived class


class TeamLead extends Manager {
String project;
TeamLead(String name, int id, String department, String project) {
super(name, id, department);
this.project = project;
}

void displayTeamLeadInfo() {
displayManagerInfo();
System.out.println("Project: " + project);
}
}

// Test the classes


public class TestInheritance {
public static void main(String[] args) {
TeamLead lead = new TeamLead("John Doe", 123, "IT", "Project A");
lead.displayTeamLeadInfo();
}
}
Output:
Name: John Doe
ID: 123
Department: IT
Project: Project A

Explanation
1. Class Employee: The base class with common attributes name and id, and a method to display these
details.
2. Class Manager: Inherits from Employee and adds a new attribute department. It includes a method to
display the manager’s details.
3. Class TeamLead: Inherits from Manager and adds another attribute project. It includes a method to
display the team lead’s details.

In this hierarchy:
• Employee is the top-level class.
• Manager inherits from Employee.
• TeamLead inherits from Manager.

1. Multilevel Inheritance Diagram:

Multilevel inheritance allows the creation of complex class hierarchies, enabling code reuse and the
organization of classes in a structured manner. By understanding and implementing multilevel inheritance,
students can design more flexible and scalable object-oriented systems.

Do It Yourself

1. Create a multilevel inheritance hierarchy for a library system with classes Library (base class), Section
(intermediate class), and Book (derived class). Implement methods to manage library operations.
2. Implement a class hierarchy for a zoo with a base class Animal, an intermediate class Mammal, and a
derived class Lion. Include methods to display characteristics at each level.
3. Create a multilevel inheritance hierarchy with a base class Shape, an intermediate class Polygon, and a
derived class Triangle. Override methods in Triangle to calculate and display area.
4. Design an employee management system with a base class Employee, an intermediate class Manager,
and a derived class Director. Include methods to display the hierarchy and employee details.
5. Implement a class hierarchy for an educational institution with a base class Person, an intermediate
class Teacher, and a derived class Professor. Demonstrate inheritance and method overriding.
Quiz

1. Which of the following correctly describes multilevel inheritance?


A) A class inherits from another class which in turn inherits from a third class.
B) A class inherits from multiple classes.
C) Multiple classes inherit from a single class.
D) A class is derived from multiple classes.

Answer: A) A class inherits from another class which in turn inherits from a third class.

2. In a multilevel inheritance hierarchy, which class can access the methods of its ancestor classes?
A) Only the direct parent class
B) Only the immediate child class
C) Any descendant class
D) Only the top-level class
Answer: C) Any descendant class

3. Given the following hierarchy, which class will have access to the methods of class Base?

class Base {
void methodBase() {}
}
class Derived1 extends Base {}
class Derived2 extends Derived1 {}
A) Only Base
B) Derived1 and Derived2
C) Only Derived2
D) Only Derived1
Answer: B) Derived1 and Derived2

4. Which keyword is used to extend a class in Java?


A) implements
B) extends
C) inherits
D) derives
Answer: B) extends

5. If a class C inherits from class B, and class B inherits from class A, which of the following methods is
accessible in class C?
A) Only methods defined in class C
B) Only methods defined in class B
C) Only methods defined in class A
D) Methods defined in class A, B, and C

Answer: D) Methods defined in class A, B, and C


Application of the Keyword super in Java
Introduction
In Java, the keyword super is used to refer to the superclass (parent class) of the current object. It provides a
way to access superclass methods and constructors, and to resolve ambiguities between superclass and
subclass members. The super keyword can be used in several scenarios including calling superclass
constructors, accessing superclass methods, and accessing superclass fields.
Syntax
1. Calling Superclass Constructor:
super(arguments);

2. Accessing Superclass Method:


super.methodName(arguments);

3. Accessing Superclass Field:


super.fieldName;

Examples
1. Calling Superclass Constructor
When a subclass is instantiated, its constructor can call the constructor of its superclass using super() to initialize
inherited fields.

class Animal {
String name;

Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
Dog(String name) {
super(name); // Calls the constructor of Animal
}
void display() {
System.out.println("Dog's name is: " + name);
}
}
public class TestSuper {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.display();
}
}

Output:

Dog's name is: Buddy


2. Accessing Superclass Method
If a subclass overrides a method from its superclass, super can be used to call the superclass version
of that method.

class Parent {
void show() {
System.out.println("Parent class method");
}
}
class Child extends Parent {
void show() {
super.show(); // Calls the show() method of Parent
System.out.println("Child class method");
}
}
public class TestSuper {
public static void main(String[] args) {
Child child = new Child();
child.show();
}
}

Output:
Parent class method
Child class method

3. Accessing Superclass Field


In case of field hiding, super is used to access the field of the superclass.

class Parent {
int x = 10;
}

class Child extends Parent {


int x = 20;
void display() {
System.out.println("Parent x: " + super.x); // Accesses x from Parent
System.out.println("Child x: " + x); // Accesses x from Child
}
}
public class TestSuper {
public static void main(String[] args) {
Child child = new Child();
child.display();
}
}
Output:
Parent x: 10
Child x: 20

Explanation
• Calling Superclass Constructor: The super keyword can be used to invoke a constructor of the
superclass. This is essential when the superclass constructor requires parameters to initialize its fields.

• Accessing Superclass Method: When a method in a subclass overrides a method in the superclass, the
super keyword can be used to call the original method from the superclass. This is useful for extending
functionality while preserving the base functionality.

• Accessing Superclass Field: When a subclass declares a field with the same name as a field in the
superclass, super allows accessing the superclass field to avoid ambiguity.

The super keyword is a fundamental feature in Java that helps manage class hierarchies by providing access to
superclass members. Understanding how to use super effectively is crucial for leveraging inheritance in Java
and ensuring that subclass instances correctly interact with their superclass elements.

Do It Yourself

1. Implement a base class Vehicle with a parameterized constructor. Create a derived class Car that uses
super() to call the constructor of Vehicle. Add additional attributes and methods in Car.
2. Define a class Shape with a method draw(). Create a subclass Circle that overrides draw() and uses
super.draw() to call the method in Shape.
3. Implement a base class Animal with a field age. Create a derived class Cat that hides the age field and
use super.age to access the field in Animal.
4. Create a class hierarchy with Base, Intermediate, and Final classes. Use super to call methods and
constructors across the hierarchy.
5. Define a base class Account with a method deposit(). Extend it with SavingsAccount and
CheckingAccount. Override deposit() and use super.deposit() in each subclass.

Quiz

1. What does the super keyword do in Java?


A) Refers to the superclass constructor, methods, and fields.
B) Creates a new instance of the superclass.
C) Deletes the superclass.
D) Replaces the superclass with the current class.

Answer: A) Refers to the superclass constructor, methods, and fields.

2. Which of the following statements is true about super() in Java?


A) super() must be the first statement in the constructor of a subclass.
B) super() can be called after other statements in the constructor.
C) super() is used to access the methods of the current class.
D) super() cannot be used in a constructor.
Answer: A) super() must be the first statement in the constructor of a subclass.

3. Given the following code, what will be the output?

class A {
void display() {
System.out.println("Class A");
}
}
class B extends A {
void display() {
super.display();
System.out.println("Class B");
}
}
public class Test {
public static void main(String[] args) {
B obj = new B();
obj.display();
}
}
A) Class A Class B
B) Class B Class A
C) Class A
D) Class B

Answer: A) Class A Class B

4. Which keyword is used to access a field from the superclass in Java?


A) this
B) super
C) extends
D) implements
Answer: B) super

5.In the following code, what will be the result of super.x?

class A {
int x = 10;
}
class B extends A {
int x = 20;

void show() {
System.out.println(super.x);
}
}
public class Test {
public static void main(String[] args) {
B obj = new B();
obj.show();
}
}
A) 10
B) 20
C) 30
D) Compilation error

Answer: A) 10

Constructor Method and Inheritance in Java


Introduction
In Java, constructors are special methods used to initialize objects. They are called when an instance of a class
is created. Constructors play a crucial role in inheritance by ensuring that the superclass is properly initialized
before the subclass is instantiated. This document explores the role of constructors in inheritance, including
their syntax, examples, explanations, and practical applications.
Syntax
1. Constructor Declaration:

ClassName(parameters) {
// constructor body
}

2. Calling Superclass Constructor:


super(arguments);

Examples
1. Basic Constructor in Inheritance
When a subclass is instantiated, the constructor of the superclass is called first, either implicitly or explicitly. If
the superclass has a no-argument constructor, it is called automatically. If the superclass has a parameterized
constructor, you need to use super() to call it.

class Animal {
Animal() {
System.out.println("Animal constructor");
}
}
class Dog extends Animal {
Dog() {
super(); // Calls Animal constructor
System.out.println("Dog constructor");
}
}
public class TestConstructor {
public static void main(String[] args) {
Dog dog = new Dog();
}
}

Output:
Animal constructor
Dog constructor

2. Parameterized Constructor in Inheritance


When the superclass has a parameterized constructor, you must call it from the subclass constructor using
super().

class Animal {
String name;

Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
Dog(String name) {
super(name); // Calls Animal(String name)
System.out.println("Dog constructor");
}
}
public class TestConstructor {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
System.out.println("Dog's name: " + dog.name);
}
}

Output:
Dog constructor
Dog's name: Buddy

3. Constructor Overloading in Inheritance


Both the superclass and subclass can have overloaded constructors.

class Animal {
String name;

Animal() {
this.name = "Unknown";
}
Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
int age;

Dog() {
super(); // Calls Animal()
this.age = 0;
}
Dog(String name, int age) {
super(name); // Calls Animal(String name)
this.age = age;
}
}
public class TestConstructor {
public static void main(String[] args) {
Dog dog1 = new Dog();
Dog dog2 = new Dog("Buddy", 5);
System.out.println("Dog1 name: " + dog1.name + ", age: " + dog1.age);
System.out.println("Dog2 name: " + dog2.name + ", age: " + dog2.age);
}
}

Output:

Dog1 name: Unknown, age: 0


Dog2 name: Buddy, age: 5

Explanation
• Superclass Constructor Call: When a subclass object is created, the constructor of the superclass is
called first. This ensures that the superclass is properly initialized before the subclass starts its
initialization.

• Parameterized Constructors: If a superclass has parameterized constructors, the subclass must


explicitly call one of these constructors using super(). This allows you to initialize the superclass with
specific values.

• Constructor Overloading: Both superclass and subclass can have multiple constructors with different
parameter lists. Constructor overloading allows for different ways to initialize objects.
Practice Programs

1. Shape Hierarchy: Create a base class Shape with a no-argument constructor and a parameterized
constructor. Extend it with Circle and Rectangle classes that use both constructors to initialize their
properties.
2. Employee Management: Design a base class Employee with constructors for initializing employee ID
and name. Create subclasses FullTimeEmployee and PartTimeEmployee that call these constructors and
add additional fields.

3. Vehicle System: Implement a base class Vehicle with constructors to set make and model. Extend it with
Car and Bike classes that use the superclass constructors and initialize additional attributes.

4. Person and Student: Create a base class Person with a parameterized constructor. Extend it with
Student that initializes additional attributes using super() and demonstrates constructor chaining.

5. Library Items: Develop a base class LibraryItem with constructors for item ID and title. Extend it with
Book and Magazine classes that initialize additional properties and demonstrate constructor
overloading.

Understanding constructors and their role in inheritance is essential for managing class hierarchies in Java.
Constructors ensure proper initialization of objects and facilitate the inheritance mechanism by setting up
superclass properties before subclass-specific initialization. This knowledge is crucial for writing efficient and
maintainable Java code.

Do It Yourself

1. Implement a base class Employee with a constructor that initializes name and ID. Extend it with Manager
and Intern classes that use super() to initialize the base class fields and add additional attributes.
2. Define a base class Animal with a parameterized constructor for setting name and age. Create a subclass
Bird that uses constructor chaining to initialize both the base class and its own fields.
3. Create a class Person with multiple constructors for name and age. Extend it with Student and Teacher
classes that use different constructors to initialize their fields.
4. Design a class hierarchy with Vehicle as the base class, and Car and Truck as subclasses. Implement
overloaded constructors in each class to handle different initialization scenarios.
5. Write a program that demonstrates the use of both no-argument and parameterized constructors in a
class hierarchy where Parent and Child classes are involved.

Quiz

1. What happens if a subclass constructor does not explicitly call a superclass constructor?
A) The subclass constructor will not compile.
B) The default no-argument constructor of the superclass is called automatically.
C) The superclass constructor must be defined as static.
D) The superclass constructor is skipped.
Answer: B) The default no-argument constructor of the superclass is called automatically.

2. Which keyword is used to invoke a superclass constructor from a subclass?


A) this
B) super
C) extends
D) implements
Answer: B) super
3. Given the following code, what will be the output?

class A {
A(int x) {
System.out.println("A constructor with value: " + x);
}
}
class B extends A {
B() {
super(10);
System.out.println("B constructor");
}
}
public class Test {
public static void main(String[] args) {
B obj = new B();
}
}
A) A constructor with value: 10 B constructor
B) A constructor with value: 10
C) B constructor
D) Compilation error
Answer: A) A constructor with value: 10 B constructor

4. Which of the following is true about constructor overloading in Java?


A) Constructor overloading is not allowed in Java.
B) A subclass can have a constructor with the same name as its superclass.
C) A constructor can be overloaded by changing the return type.
D) Constructor overloading is determined by the number and type of parameters.

Answer: D) Constructor overloading is determined by the number and type of parameters.

5. What is the result of the following code?

class Parent {
Parent() {
System.out.println("Parent constructor");
}
}
class Child extends Parent {
Child() {
System.out.println("Child constructor");
}
}
public class Test {
public static void main(String[] args) {
Child obj = new Child();
}
}
A) Parent constructor Child constructor
B) Child constructor
C) Parent constructor
D) Compilation error

Answer: A) Parent constructor Child constructor

Method Overriding in Java


Introduction
Method overriding is a fundamental concept in Java's object-oriented programming that allows a subclass to
provide a specific implementation of a method that is already defined in its superclass. This concept is pivotal
for achieving runtime polymorphism, which enables a program to choose the appropriate method
implementation based on the object's runtime type.

Syntax
class Superclass {
void methodName() {
// Superclass method implementation
}
}

class Subclass extends Superclass {


@Override
void methodName() {
// Subclass method implementation
}
}

@Override Annotation: This annotation is used to indicate that the method is intended to override a
method in the superclass. It is optional but recommended as it helps to catch errors during compilation.
Examples
1. Basic Method Overriding
In this example, the subclass overrides the display() method of the superclass Animal.

class Animal {
void display() {
System.out.println("This is an animal.");
}
}

class Dog extends Animal {


@Override
void display() {
System.out.println("This is a dog.");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Animal();
animal.display(); // Output: This is an animal.

Dog dog = new Dog();


dog.display(); // Output: This is a dog.
}
}

Output:
This is an animal.
This is a dog.

2. Method Overriding with Parameters


The overridden method in the subclass can have the same parameters as the method in the superclass.

class Vehicle {
void start(String type) {
System.out.println("Starting " + type);
}
}
class Car extends Vehicle {
@Override
void start(String type) {
System.out.println("Car is starting with " + type);
}
}
public class Test {
public static void main(String[] args) {
Vehicle vehicle = new Vehicle();
vehicle.start("engine");

Car car = new Car();


car.start("electricity");
}
}
Output:
Starting engine
Car is starting with electricity

3. Method Overriding with Return Type


In Java, a subclass method can override a superclass method while changing the return type to a subtype
(covariant return type).

class Animal {
Animal getAnimal() {
return this;
}
}
class Dog extends Animal {
@Override
Dog getAnimal() {
return this;
}
void display() {
System.out.println("This is a Dog.");
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
dog.getAnimal().display();
}
}

Output:
This is a dog.

Explanation
• Method Signature: To override a method, the method signature in the subclass must exactly match the
method signature in the superclass. This includes the method name, return type, and parameter list.

• Access Modifiers: The overridden method in the subclass can have the same or more permissive
access modifier than the method in the superclass. For example, if the superclass method is protected,
the subclass method can be protected or public, but not private.

• @Override Annotation: This annotation helps to ensure that the method is correctly overriding a
superclass method and not overloading it. It also improves code readability and maintainability.

Method overriding is a critical feature in Java that allows subclasses to provide specific implementations of
methods defined in their superclasses. This mechanism supports runtime polymorphism, enabling flexible and
dynamic method invocation. Understanding method overriding helps in designing robust and maintainable
object-oriented systems.
Do It Yourself

1. Implement a base class Vehicle with a method accelerate(). Create a subclass Bike that overrides
accelerate() and demonstrate the use of the overridden method.
2. Write a base class Printer with a method print(String document). Extend it with LaserPrinter and
InkjetPrinter classes that override print() to provide specific printing implementations.
3. Create a base class Building with a method getType(). Extend it with House and Skyscraper classes that
override getType() to return more specific types.
4. Define a base class Person with a protected method getDetails(). Extend it with Student and Teacher
classes that override getDetails() to provide detailed information.
5. Design a class hierarchy with a base class Appliance and subclasses WashingMachine, Refrigerator, and
Oven. Override a method function() in each subclass to demonstrate specific functionalities.

Quiz

1. Which annotation is used to indicate that a method is overriding a superclass method?


A) @Override
B) @OverrideMethod
C) @Overriding
D) @OverrideMethod
Answer: A) @Override

2. Which of the following is true about method overriding?


A) The method name and return type must be different in the subclass.
B) The method in the subclass must have the same return type or a subtype.
C) Method overriding allows changing the method’s name.
D) The overridden method can have different access modifiers than the method in the superclass.
Answer: B) The method in the subclass must have the same return type or a subtype.

3. Given the following code, what will be the output?

class Animal {
void sound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog bark");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Dog();
a.sound();
}
}
A) Animal sound
B) Dog bark
C) Compilation error
D) Runtime error
Answer: B) Dog bark

4. Which of the following is a valid reason to use method overriding?


A) To increase the method's visibility in the subclass.
B) To call a superclass method in a subclass.
C) To provide a specific implementation of a method in a subclass.
D) To prevent method overriding in subclasses.
Answer: C) To provide a specific implementation of a method in a subclass.

5.What is the result of the following code?

class Base {
void show() {
System.out.println("Base class");
}
}
class Derived extends Base {
void show() {
System.out.println("Derived class");
}
}
public class Test {
public static void main(String[] args) {
Base obj = new Derived();
obj.show();
}
}
A) Base class
B) Derived class
C) Compilation error
D) Runtime error

Answer: B) Derived class

Dynamic Method Dispatch in Java


Introduction
Dynamic Method Dispatch is a core concept in Java that supports runtime polymorphism. It allows a method to
be called based on the actual object type, rather than the reference type, at runtime. This capability is
fundamental to the concept of polymorphism and method overriding in Java.
Syntax
Dynamic Method Dispatch involves the following key elements:
1. Superclass: Defines a method.
2. Subclass: Overrides the method from the superclass.
3. Reference Variable: Holds a reference to an object of the subclass but is of the type of the superclass.

Here's a basic syntax outline:

class Superclass {
void display() {
System.out.println("Superclass display");
}
}
class Subclass extends Superclass {
@Override
void display() {
System.out.println("Subclass display");
}
}
public class Test {
public static void main(String[] args) {
Superclass obj = new Subclass(); // Upcasting
obj.display(); // Calls Subclass's display method
}
}

Explanation
• Upcasting: Refers to the process of assigning a subclass object to a superclass reference. This is essential
for dynamic method dispatch.
• Method Overriding: Allows a subclass to provide a specific implementation of a method already defined
in its superclass.
• Runtime Method Resolution: The actual method that gets called is determined at runtime based on the
object's type, not the reference type.

Examples
1. Basic Example of Dynamic Method Dispatch
class Animal {
void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bark");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Meow");
}
}
public class Test {
public static void main(String[] args) {
Animal myAnimal;

myAnimal = new Dog();


myAnimal.makeSound(); // Output: Bark

myAnimal = new Cat();


myAnimal.makeSound(); // Output: Meow
}
}

Output:
Bark
Meow

2. Dynamic Method Dispatch with Method Overloading


class Printer {
void print(int a) {
System.out.println("Printing integer: " + a);
}
}
class ColorPrinter extends Printer {
@Override
void print(int a) {
System.out.println("Printing integer in color: " + a);
}
void print(String str) {
System.out.println("Printing string in color: " + str);
}
}
public class Test {
public static void main(String[] args) {
Printer printer = new ColorPrinter();
printer.print(10); // Output: Printing integer in color: 10
}
}

Output:
Printing integer in color: 10
Practice Programs
1. Shape Drawing: Create a base class Shape with a method draw(). Derive Circle, Rectangle, and Triangle
classes from it. Override the draw() method in each derived class. Use dynamic method dispatch to call
the draw() method on various shape objects.
2. Employee Management: Develop a base class Employee with a method calculateSalary(). Extend it with
FullTimeEmployee and PartTimeEmployee classes. Override calculateSalary() in each subclass and use
dynamic method dispatch to compute salaries.
3. Vehicle System: Implement a base class Vehicle with a method start(). Extend it with Car, Bike, and Truck
classes. Override start() in each subclass. Use dynamic method dispatch to start different vehicle objects.
4. Media Playback: Define a base class Media with a method play(). Derive Audio and Video classes from
it. Override play() in each subclass. Use dynamic method dispatch to play different media types.
5. Payment Processing: Create a base class Payment with a method process(). Extend it with
CreditCardPayment and PaypalPayment classes. Override process() in each subclass and use dynamic
method dispatch to handle various payment methods.

Dynamic Method Dispatch is a powerful feature of Java that supports runtime polymorphism, allowing for
flexible and adaptable code. Understanding and applying this concept is crucial for designing robust and
maintainable object-oriented systems.

Do It Yourself

1. Write a program with a base class Animal and derived classes Dog and Cat. Override the makeSound()
method in each derived class. Use dynamic method dispatch to invoke the makeSound() method.
2. Design a class hierarchy with a base class Vehicle and subclasses Car, Truck, and Motorcycle. Each
subclass should override a method startEngine(). Demonstrate dynamic method dispatch.
3. Implement a base class Calculator with overloaded add() methods. Extend it with ScientificCalculator
that overrides one of the add() methods. Use dynamic method dispatch to invoke the overridden
method.
4. Create a base class Account with a method getBalance(). Extend it with SavingsAccount and
CheckingAccount classes. Override getBalance() in each subclass. Use dynamic method dispatch to
display account balances.
5. Define a base class Book with a method getDetails(). Extend it with EBook and PrintedBook classes.
Override getDetails() in each subclass and demonstrate dynamic method dispatch.

Quiz

1. What is Dynamic Method Dispatch?


A) A process of resolving method calls at compile time
B) A process of method overloading
C) A process of method overriding at runtime
D) A process of method hiding
Answer: C) A process of method overriding at runtime

2. In Dynamic Method Dispatch, which method implementation is called?


A) The method in the superclass
B) The method in the subclass
C) The method with the highest access level
D) The method based on the reference type
Answer: B) The method in the subclass

3.Given the following code, what will be the output?

class Animal {
void makeSound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks");
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Dog();
a.makeSound();
}
}
A) Animal sound
B) Dog barks
C) Compilation error
D) Runtime error
Answer: B) Dog barks

4.Which of the following allows a subclass to provide a specific implementation of a method defined in a
superclass?
A) Method Overloading
B) Method Hiding
C) Method Overriding
D) Method Binding
Answer: C) Method Overriding

5.What happens if a method is not overridden in a subclass?


A) The subclass method is invoked
B) The superclass method is called
C) Compilation error occurs
D) Runtime error occurs

Answer: B) The superclass method is called


Abstract Classes in Java
Introduction
Abstract classes in Java are classes that cannot be instantiated on their own and are intended to be subclasses.
They provide a way to define methods that must be implemented by subclasses and can also contain concrete
methods with implementations. Abstract classes are a key part of Java's abstraction mechanism and are used
to define a common interface for a group of related classes.

Syntax
1. Declaration: An abstract class is declared using the abstract keyword.
2. Abstract Methods: Methods declared without an implementation using the abstract keyword.
3. Concrete Methods: Regular methods with an implementation can also be included.

Syntax Example:

abstract class AbstractClass {


abstract void abstractMethod(); // Abstract method (no body)

void concreteMethod() { // Regular method


System.out.println("This is a concrete method.");
}
}
Key Points
• Abstract Methods: Must be implemented by subclasses.
• Concrete Methods: Can have implementations.
• Abstract Class Instantiation: Cannot be instantiated directly.
• Subclassing: Subclasses must implement all abstract methods to be concrete.

Examples
1. Basic Example
abstract class Animal {
abstract void makeSound(); // Abstract method

void sleep() { // Concrete method


System.out.println("Sleeping");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bark");
}
}

public class Test {


public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // Output: Bark
myDog.sleep(); // Output: Sleeping
}
}

Output:
Bark
Sleeping

2. Abstract Class with Constructor


abstract class Shape {
String color;
Shape(String color) {
this.color = color;
}
abstract void draw();

void displayColor() {
System.out.println("Color: " + color);
}
}
class Circle extends Shape {
Circle(String color) {
super(color);
}

@Override
void draw() {
System.out.println("Drawing Circle");
}
}

public class Test {


public static void main(String[] args) {
Shape circle = new Circle("Red");
circle.draw(); // Output: Drawing Circle
circle.displayColor(); // Output: Color: Red
}
}

Output:
Drawing Circle
Color: Red

Practice Programs
1. Vehicle Hierarchy: Create an abstract class Vehicle with an abstract method start(). Extend it with Car
and Bike classes that implement the start() method. Demonstrate the use of abstract class and method
overriding.
2. Employee System: Design an abstract class Employee with an abstract method calculateSalary(). Extend
it with FullTimeEmployee and PartTimeEmployee classes. Implement calculateSalary() in both
subclasses and demonstrate their usage.
3. Shape Drawing: Define an abstract class Shape with an abstract method draw(). Derive Rectangle,
Triangle, and Circle classes from it. Implement the draw() method in each subclass and use an array of
Shape to invoke the draw() method.
4. Account Management: Create an abstract class Account with abstract methods deposit() and
withdraw(). Extend it with SavingsAccount and CheckingAccount classes. Implement the methods in
each subclass and demonstrate their functionality.
5. Appliance System: Implement an abstract class Appliance with an abstract method operate(). Extend it
with WashingMachine and Refrigerator classes. Provide implementations for operate() and show how
these appliances work.

Abstract classes in Java are a fundamental feature for creating a common interface for a group of related
classes, enforcing a structure that subclasses must follow. They allow for the definition of abstract methods
that must be implemented by subclasses while providing the flexibility to include concrete methods with
implementations. Understanding and utilizing abstract classes is crucial for designing flexible and maintainable
object-oriented systems.

Do It Yourself

1. Write a program with an abstract class Appliance that has an abstract method turnOn(). Create two
subclasses, Fan and Light, that implement the turnOn() method. Display the output of both.
2. Create an abstract class Calculator with an abstract method add(). Implement the method in a subclass
ScientificCalculator with method overloading. Provide different implementations for adding integers
and floating-point numbers.
3. Design an abstract class Book with an abstract method getTitle(). Implement a concrete class Novel that
extends Book, using the constructor to initialize the book's title. Display the title using the getTitle()
method.
4. Implement an abstract class Vehicle with an abstract method fuelEfficiency(). Derive ElectricCar and
DieselTruck classes from it. Provide specific implementations for fuelEfficiency() in both subclasses.
5. Create an abstract class GameCharacter with an abstract method attack(). Implement subclasses
Warrior and Mage that override the attack() method. Demonstrate their attacks.

Quiz

1. Which of the following cannot be done with an abstract class?


A) Create an instance of the class
B) Define abstract methods
C) Define concrete methods
D) Define constructors
Answer: A) Create an instance of the class

2.Which keyword is used to declare an abstract class in Java?


A) abstract
B) interface
C) final
D) static
Answer: A) abstract

3.Given the following code, what will be the output?

abstract class Animal {


abstract void makeSound();
}
class Cat extends Animal {
void makeSound() {
System.out.println("Meow");
}
}
public class Test {
public static void main(String[] args) {
Animal myCat = new Cat();
myCat.makeSound();
}
}
A) Compilation error
B) Runtime error
C) Meow
D) No output
Answer: C) Meow

4.What is the purpose of an abstract method?


A) To provide a complete method implementation
B) To allow method implementation in the subclass
C) To prevent a method from being overridden
D) To allow for multiple implementations in the same class

Answer: B) To allow method implementation in the subclass

5.Which of the following statements is true about an abstract class?


A) An abstract class can be instantiated directly.
B) An abstract class can have both abstract and concrete methods.
C) An abstract class cannot have constructors.
D) All methods in an abstract class must be abstract.

Answer: B) An abstract class can have both abstract and concrete methods
Interfaces and Inheritance in Java
Introduction
In Java, interfaces and inheritance are two fundamental concepts that support polymorphism and abstraction.
While inheritance allows a class to inherit properties and methods from another class, interfaces provide a way
to define a contract that classes can implement. Understanding how to use both effectively can lead to more
flexible and maintainable code.
Interfaces in Java
Syntax
1. Declaration: An interface is declared using the interface keyword.
2. Methods: All methods in an interface are implicitly public and abstract.
3. Fields: Fields in an interface are implicitly public, static, and final.

Syntax Example:

interface Drawable {
void draw(); // Abstract method
}
Key Points
• Methods: Cannot have a body; must be implemented by classes.
• Fields: Can only be constants (i.e., static and final).
• Inheritance: A class can implement multiple interfaces.
• Default Methods: Interfaces can have default methods with a body, introduced in Java 8.

Examples
1. Basic Interface Implementation
interface Animal {
void makeSound();
}
class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("Bark");
}
}
public class Test {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // Output: Bark
}
}
Output:
Bark
2. Interface with Default Method
interface Animal {
void makeSound();

default void eat() {


System.out.println("Eating...");
}
}
class Cat implements Animal {
@Override
public void makeSound() {
System.out.println("Meow");
}
}
public class Test {
public static void main(String[] args) {
Cat myCat = new Cat();
myCat.makeSound(); // Output: Meow
myCat.eat(); // Output: Eating...
}
}

Output:
Meow
Eating...
Inheritance in Java

Syntax
1. Class Inheritance: Use the extends keyword to inherit from a superclass.
2. Method Overriding: A subclass can override methods of the superclass using the @Override annotation.

Syntax Example:
class Animal {
void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
@Override
void eat() {
System.out.println("Dog is eating...");
}
}
Key Points
• Single Inheritance: A class can inherit from only one superclass.
• Method Overriding: Allows a subclass to provide a specific implementation of a method that is already
defined in its superclass.
• Super Keyword: Used to access superclass methods and constructors.
Examples
1. Basic Inheritance
class Animal {
void makeSound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bark");
}
}
public class Test {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.makeSound(); // Output: Bark
}
}

Output:
Bark

2. Super Keyword Usage


class Animal {
void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
@Override
void eat() {
super.eat(); // Calling superclass method
System.out.println("Dog is eating...");
}
}
public class Test {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.eat(); // Output: Eating... Dog is eating...
}
}
Output:
Eating...
Dog is eating...
Interfaces and Inheritance Together
An important aspect of Java is how interfaces and inheritance can be used together. A class can extend one
class and implement multiple interfaces.
Example
interface Flyable {
void fly();
}

class Animal {
void makeSound() {
System.out.println("Some sound");
}
}
class Bird extends Animal implements Flyable {
@Override
public void fly() {
System.out.println("Flying...");
}
@Override
void makeSound() {
System.out.println("Tweet");
}
}
public class InterfaceInheritanceEx3 {
public static void main(String[] args) {
Bird myBird = new Bird();
myBird.makeSound(); // Output: Tweet
myBird.fly(); // Output: Flying...
}
}
Output:
Tweet
Flying...

Interfaces and inheritance are powerful features in Java that enable polymorphism and abstraction. Interfaces
allow classes to define a contract that must be fulfilled, while inheritance facilitates code reuse and extension.
Mastering both concepts will help in designing robust and scalable object-oriented systems.

Do It Yourself

1. Create an interface Shape with an abstract method draw(). Implement this interface in Circle and Square
classes. Show how to create objects of these classes and call their draw() methods.
2. Write a program with a superclass Vehicle and a subclass Car. The Car class should override a method
startEngine() from Vehicle. Demonstrate the usage of the Car class.
3. Define two interfaces Readable and Writable with methods read() and write() respectively. Create a
class Document that implements both interfaces. Show how to use this class to read from and write to
a document.
4. Create a superclass Person with a method getName(). Derive a subclass Student that overrides
getName() and uses the super keyword to call the superclass method. Display the results.
5. Write an interface Appliance with a default method turnOn(). Implement this interface in Fan and Light
classes. Display how these appliances are turned on using the default method.

Quiz

1. What does an interface in Java define?


A) A set of classes
B) A set of methods without implementations
C) A set of fields and methods with implementations
D) A set of concrete methods

Answer: B) A set of methods without implementations

2.Which keyword is used to implement an interface in Java?


A) implements
B) extends
C) interface
D) abstract
Answer: A) implements

3.Given the following code, what will be the output?

interface A {
void display();
}
class B implements A {
public void display() {
System.out.println("Display from B");
}
}
public class Test {
public static void main(String[] args) {
A obj = new B();
obj.display();
}
}
A) Compilation error
B) Runtime error
C) Display from B
D) No output
Answer: C) Display from B

4.Which of the following statements is true about class inheritance in Java?


A) A class can extend multiple classes
B) A class can implement multiple interfaces
C) A class can implement multiple classes
D) A class cannot extend any other class

Answer: B) A class can implement multiple interfaces

5.What is the purpose of the super keyword in Java?


A) To access the superclass constructor
B) To access the superclass methods and fields
C) To call the subclass methods
D) To create a new superclass

Answer: B) To access the superclass methods and fields

What are Interfaces in Java?


In Java, an interface is an abstract type used to specify the behavior of a class. An interface in Java acts as a
blueprint for a class, specifying what methods a class should implement but not how these methods should be
implemented. Interfaces are a key mechanism for achieving abstraction in Java, allowing you to define methods
that other classes must implement.
Key Characteristics of Interfaces:
• Abstraction: Interfaces provide a way to achieve abstraction. They allow you to define methods without
implementing them, letting other classes provide the actual implementation.
• Multiple Inheritance: Java does not support multiple inheritance with classes. However, a class can
implement multiple interfaces, thereby achieving multiple inheritance.
• No Instantiation: Interfaces cannot be instantiated on their own. They must be implemented by classes.
Example:
Consider a scenario where you have different types of vehicles, like bicycles and cars, which share common
functionalities. Instead of defining these functionalities separately in each vehicle class, you can define an
interface with these methods and let each vehicle class implement the interface.

2. Declaration of Interface

Syntax
To declare an interface in Java, use the interface keyword. The syntax is as follows:

interface InterfaceName {
// Declare constants (public, static, final by default)
int CONSTANT = 100;

// Declare methods (public and abstract by default)


void method1();
void method2();
}
Example:
interface Vehicle {
void start();
void stop();
}

In this example, Vehicle is an interface with two abstract methods: start() and stop(). Any class that implements
the Vehicle interface must provide implementations for these methods.
Features of Interfaces:
• Method Declaration: Methods in an interface are implicitly public and abstract (in earlier versions of
Java). This means they do not have a body.
• Field Declaration: Fields in an interface are public, static, and final by default. They must be initialized
when declared.
• No Constructors: Interfaces cannot have constructors because they cannot be instantiated.
• No Instance Variables: Interfaces cannot contain instance variables.

3. Implementation of Interface

Syntax
To implement an interface, use the implements keyword. A class that implements an interface must provide
concrete implementations for all the methods declared in the interface.

class ClassName implements InterfaceName {


// Implement the methods of the interface
@Override
public void method1() {
// Method implementation
}
@Override
public void method2() {
// Method implementation
}
}

Example:
interface Vehicle {
void start();
void stop();
}

class Car implements Vehicle {


@Override
public void start() {
System.out.println("Car started.");
}

@Override
public void stop() {
System.out.println("Car stopped.");
}
}
public class Test {
public static void main(String[] args) {
Car myCar = new Car();
myCar.start();
myCar.stop();
}
}
Output:
Car started.
Car stopped.

Real-World Example:
Consider the example of vehicles with common functionalities like changing gear, speeding up, and applying
brakes. We can define an interface Vehicle with these methods and then implement this interface in classes
like Bicycle and Bike.

Code Example:
interface Vehicle {
void changeGear(int gear);
void speedUp(int increment);
void applyBrakes(int decrement);
}
class Bicycle implements Vehicle {
int speed = 0;
int gear = 0;
@Override
public void changeGear(int newGear) {
gear = newGear;
}
@Override
public void speedUp(int increment) {
speed += increment;
}
@Override
public void applyBrakes(int decrement) {
speed -= decrement;
}
public void printStates() {
System.out.println("Speed: " + speed + " Gear: " + gear);
}
}
class Bike implements Vehicle {
int speed = 0;
int gear = 0;
@Override
public void changeGear(int newGear) {
gear = newGear;
}
@Override
public void speedUp(int increment) {
speed += increment;
}
@Override
public void applyBrakes(int decrement) {
speed -= decrement;
}
public void printStates() {
System.out.println("Speed: " + speed + " Gear: " + gear);
}
}
public class Main {
public static void main(String[] args) {
Bicycle bicycle = new Bicycle();
bicycle.changeGear(2);
bicycle.speedUp(3);
bicycle.applyBrakes(1);
System.out.println("Bicycle state:");
bicycle.printStates();

Bike bike = new Bike();


bike.changeGear(1);
bike.speedUp(4);
bike.applyBrakes(3);
System.out.println("Bike state:");
bike.printStates();
}
}
Output:
Bicycle state:
Speed: 2 Gear: 2
Bike state:
Speed: 1 Gear: 1
Advantages of Interfaces:
1. Abstraction: Interfaces help in achieving abstraction by hiding the implementation details from the user.
2. Multiple Inheritance: Interfaces allow a class to inherit from multiple sources, which is not possible with
classes alone.
3. Loose Coupling: Interfaces help in achieving loose coupling by defining methods that can be
implemented differently by various classes.

New Features in JDK 8 and Beyond:


• Default Methods: Interfaces can now have default methods with an implementation. This allows you to
add new methods to interfaces without breaking existing implementations.

interface MyInterface {
default void defaultMethod() {
System.out.println("Default method in interface");
}
}

Static Methods: Interfaces can now have static methods that can be called independently of an object.

interface MyInterface {
static void staticMethod() {
System.out.println("Static method in interface");
}
}

Private Methods: JDK 9 introduced private methods in interfaces, allowing better code organization within the
interface.

interface MyInterface {
private void privateMethod() {
// Implementation
}

default void defaultMethod() {


privateMethod();
}
}
Extending Interfaces
An interface can extend another interface. When a class implements an interface that extends another
interface, it must provide implementations for all methods from the parent interfaces.
Example:
interface A {
void method1();
void method2();
}

interface B extends A {
void method3();
}
class MyClass implements B {
@Override
public void method1() {
System.out.println("Method 1");
}
@Override
public void method2() {
System.out.println("Method 2");
}
@Override
public void method3() {
System.out.println("Method 3");
}
}
Output:
Method 1
Method 2
Method 3

• Interfaces in Java are a way to achieve abstraction and multiple inheritance.


• They contain abstract methods that must be implemented by the classes that use them.
• Interfaces can also have default and static methods since JDK 8 and private methods since JDK 9.
• They cannot be instantiated on their own but can be used as references to objects of implementing
classes.

Do It Yourself

1. Define an interface Appliance with methods turnOn() and turnOff(). Implement this interface in classes
WashingMachine and Refrigerator.
2. Write an interface Vehicle with methods accelerate() and brake(). Implement this interface in classes
Bike and Car.
3. Define an interface Shape with methods area() and perimeter(). Implement this interface in Square and
Triangle.
4. Create an interface PaymentGateway with methods initiateTransaction() and confirmTransaction().
Implement this interface in classes Stripe and PayPal.
5. Design an interface Student with methods getName() and getGrade(). Implement this interface in
classes Undergraduate and Postgraduate.

Quiz

1. What keyword is used to define an interface in Java?


A) interface
B) class
C) abstract
D) implements
Answer: A) interface

2. Which of the following can be defined in an interface?


A) Constructors
B) Instance variables
C) Abstract methods
D) Instance methods with a body
Answer: C) Abstract methods

3. Given the following code, what will be the output?


public interface Example {
void show();
default void display() {
System.out.println("Display method");
}
}
public class Test implements Example {
public void show() {
System.out.println("Show method");
}
public static void main(String[] args) {
Test obj = new Test();
obj.show();
obj.display();
}
}
A) Show method
B) Display method
C) Show method
D) Show method Display method
Answer: D) Show method Display method

4. Can a class implement multiple interfaces?


A) Yes
B) No
C) Only if they are not conflicting
D) Only if one interface extends another
Answer: A) Yes

5.Which method of an interface can be called without creating an instance of the interface?
A) Abstract method
B) Default method
C) Static method
D) Constructor
Answer: C) Static method

Multiple Interfaces in Java


I
In Java, a class can implement multiple interfaces. This feature allows a class to inherit from more than one
source, providing a way to achieve multiple inheritance of type. This is particularly useful in scenarios where a
class needs to implement various functionalities that can be abstracted into different interfaces.

Why Use Multiple Interfaces?


1. Multiple Inheritance: Java does not support multiple inheritance with classes, but multiple inheritance
is achieved through interfaces.
2. Modularity: It allows for modular design by splitting functionalities into different interfaces.
3. Flexibility: A class can implement various behaviors by implementing multiple interfaces, making it
versatile.

Syntax
To implement multiple interfaces, use a comma-separated list in the implements clause of the class declaration.

class ClassName implements Interface1, Interface2, Interface3 {


// Implement all methods from Interface1, Interface2, and Interface3
}

Example
Consider two interfaces: Vehicle and Electric:
interface Vehicle {
void start();
void stop();
}
interface Electric {
void charge();
}

A class ElectricCar implementing both interfaces would look like this:


class ElectricCar implements Vehicle, Electric {
@Override
public void start() {
System.out.println("Electric car started.");
}
@Override
public void stop() {
System.out.println("Electric car stopped.");
}
@Override
public void charge() {
System.out.println("Charging electric car.");
}
}

In the main method, you can test the ElectricCar class:

public class Test {


public static void main(String[] args) {
ElectricCar myCar = new ElectricCar();
myCar.start();
myCar.charge();
myCar.stop();
}
}
Output:
Electric car started.
Charging electric car.
Electric car stopped.

Explanation
• Interface Implementation: The ElectricCar class implements both Vehicle and Electric interfaces. It must
provide concrete implementations for all the methods declared in these interfaces.
• Multiple Interface Implementation: The class demonstrates how a single class can take on multiple
behaviors by implementing different interfaces.

Practice Programs
1. Example 1: Implement two interfaces Animal and Pet. Create a class Dog that implements both
interfaces and provides implementations for the methods.
2. Example 2: Define an interface Person with methods eat() and sleep(). Define another interface Worker
with methods work() and rest(). Create a class Engineer that implements both interfaces.

Do It Yourself

1. Define two interfaces: Appliance and SmartDevice. The Appliance interface should have methods
turnOn() and turnOff(). The SmartDevice interface should have methods connect() and disconnect().
Create a class SmartWashingMachine that implements both interfaces.
2. Create an interface Vehicle with methods accelerate() and brake(). Create another interface Electric with
a method charge(). Implement both interfaces in a class ElectricScooter.
3. Define two interfaces: Player with methods play() and pause(), and Recorder with a method record().
Implement both interfaces in a class MultimediaDevice.
4. Write an interface Computer with methods powerOn() and powerOff(). Write another interface
Networkable with a method connectToNetwork(). Implement both interfaces in a class Laptop.

Quiz

1. Which of the following is true about a class implementing multiple interfaces in Java?
A. The class must provide an implementation for all methods of all interfaces.
B. The class can implement methods from only one interface.
C. The class inherits all methods from the interfaces without the need for implementation.
D. Interfaces can contain constructors.

Answer: A. The class must provide an implementation for all methods of all interfaces.

2. What happens if a class implements two interfaces that have a method with the same name but different
return types?
A. Compilation error.
B. The class must implement both methods with different names.
C. The class must provide only one implementation for the method.
D. The class can choose to implement one of the methods.

Answer: A. Compilation error.

3. In which version of Java were default methods introduced in interfaces?


A. Java 5
B. Java 6
C. Java 7
D. Java 8

Answer: D. Java 8

4. Given the following interfaces and class, which of the following statements is correct?

interface A {
void method();
}

interface B {
void method();
}

class C implements A, B {
@Override
public void method() {
System.out.println("Method implemented.");
}
}
A. Class C will have two method implementations.
B. Class C must provide a single implementation for method as it is declared in both interfaces.
C. Compilation error due to method conflict.
D. Method implementations in interfaces are optional.

Answer: B. Class C must provide a single implementation for method as it is declared in both interfaces.

5. Can an interface extend multiple interfaces?


A. No, an interface can only extend one interface.
B. Yes, an interface can extend multiple interfaces.
C. Yes, but only if the extending interface is abstract.
D. No, because interfaces cannot extend other interfaces.

Answer: B. Yes, an interface can extend multiple interfaces.

Nested Interfaces in Java


Introduction
In Java, an interface can be declared inside another interface or class, forming what is known as a nested
interface. Nested interfaces allow logical grouping of interfaces and enhance the organization of your code,
especially when interfaces are only applicable within the context of a particular class or interface. A nested
interface can be both public or private depending on its use case.

Nested interfaces are primarily used to define a contract for internal communication between nested classes
and their outer class.
Syntax for Nested Interfaces
Nested interfaces are declared like regular interfaces but inside another class or interface. Here’s the syntax for
both scenarios:

Declaring Nested Interface Inside a Class:

class OuterClass {
// Nested Interface
interface NestedInterface {
void method();
}
}

Declaring Nested Interface Inside an Interface:

interface OuterInterface {
// Nested Interface
interface InnerInterface {
void method();
}
}
Example: Nested Interface Inside a Class
Below is an example of a nested interface declared within a class and how it is implemented by another class:
// Outer Class containing a Nested Interface
class Computer {
// Nested Interface
public interface USB {
void connect();
}
}

// Implementing the nested interface


class Keyboard implements Computer.USB {
@Override
public void connect() {
System.out.println("Keyboard connected via USB.");
}
}

public class Main {


public static void main(String[] args) {
Computer.USB keyboard = new Keyboard();
keyboard.connect();
}
}

Output:

Keyboard connected via USB.

Explanation:
• USB is the nested interface inside the Computer class.
• The Keyboard class implements the USB interface, and in the main method, we instantiate and use the
Keyboard object via the Computer.USB reference.

Example: Nested Interface Inside an Interface
Here’s an example of a nested interface inside another interface:

// Outer Interface containing a Nested Interface


interface Vehicle {
// Nested Interface
interface Engine {
void start();
}
}

// Class implementing the nested interface


class Car implements Vehicle.Engine {
@Override
public void start() {
System.out.println("Car engine started.");
}
}

public class Main {


public static void main(String[] args) {
Vehicle.Engine car = new Car();
car.start();
}
}

Output:

Car engine started.

Explanation:
• The Engine interface is nested inside the Vehicle interface.
• The Car class implements the Vehicle.Engine nested interface.
• The main method demonstrates the instantiation and usage of the Car class via the Vehicle.Engine
reference.
Advantages of Nested Interfaces
• Encapsulation: Nested interfaces can be used to tightly couple the functionality with the outer class or
interface, making the code more encapsulated.
• Logical Grouping: You can logically group the interfaces that are related only to the outer class or
interface, improving code organization.
• Readability: Nested interfaces within a class or interface make it clear that the interface is specifically
tied to the outer type.

Practice Program: Nested Interface Inside a Class


class Mobile {
// Nested Interface
public interface Charger {
void charge();
}
}

// Implementing the nested interface


class FastCharger implements Mobile.Charger {
@Override
public void charge() {
System.out.println("Mobile is charging with fast charger.");
}
}
public class NestedInterfaceDemo {
public static void main(String[] args) {
Mobile.Charger charger = new FastCharger();
charger.charge();
}
}
Expected Output:

Mobile is charging with fast charger.

Do It Yourself

1. Create a SmartHome interface with a nested DeviceControl interface. Implement classes like Light and
Fan that control devices using turnOn() and turnOff() methods.
2. Design an Employee interface that contains a nested Department interface. Implement the Department
interface in classes like HRDepartment and FinanceDepartment, and show how an employee belongs to
a specific department.
3. Develop a Game interface with a nested Player interface, containing methods like attack() and defend().
Implement Player in classes like Knight and Archer with unique behaviors for each action.
4. Create a Shopping interface with a nested Payment interface. Implement payment methods like
CreditCard and PayPal, each using methods from the Payment interface.
5. Create a University interface with a nested Course interface. Implement different courses like
MathCourse and HistoryCourse and print course details for each one.

Quiz

1. Which of the following is true about nested interfaces?


a) A nested interface cannot be declared inside a class.
b) A nested interface must be private.
c) A nested interface can only be declared inside another interface.
d) A nested interface can be declared inside both classes and interfaces.

Answer: d) A nested interface can be declared inside both classes and interfaces.

2. How can you access a nested interface declared inside a class?


a) By using the class name followed by the interface name.
b) By using the implements keyword.
c) By creating an instance of the outer class.
d) By importing the class containing the interface.

Answer: a) By using the class name followed by the interface name.

3. Which keyword is used to implement a nested interface inside a class?


a) extend
b) implement
c) interface
d) instantiate

Answer: b) implement

4. Consider the following nested interface:


class A {
interface B {
void display();
}
}
How will you implement the display() method in another class?
a) class C implements A.B { public void display() { /* code */ } }
b) class C extends A.B { public void display() { /* code */ } }
c) class C inherits A.B { public void display() { /* code */ } }
d) class C calls A.B { public void display() { /* code / } }

Answer: a) class C implements A.B { public void display() { / code */ } }

5. In which version of Java was support for private methods in interfaces introduced?
a) Java 7
b) Java 8
c) Java 9
d) Java 11

Answer: c) Java 9

Inheritance of Interfaces in Java


In Java, interfaces can extend other interfaces, which is known as interface inheritance. This allows one
interface to inherit the abstract methods of another interface and possibly add new methods. Multiple
inheritance is possible with interfaces, which means one interface can extend more than one interface.

Key Points:
• An interface can extend one or more other interfaces.
• A class that implements an interface must provide implementations for all methods of the interface,
including methods from inherited interfaces.
• Interfaces only inherit method signatures (abstract methods) and constants from the extended
interfaces.
• There is no ambiguity in multiple inheritance with interfaces because they don’t define method bodies.

Syntax of Interface Inheritance


Here’s how interface inheritance is written in Java:

interface A {
void methodA();
}
interface B extends A {
void methodB();
}
class C implements B {
public void methodA() {
System.out.println("Implementing methodA()");
}

public void methodB() {


System.out.println("Implementing methodB()");
}
}

In this example:
• Interface B extends Interface A, so it inherits methodA().
• The class C implements Interface B, so it must implement both methodA() and methodB().

Example of Multiple Interface Inheritance


Here’s how a single interface can extend multiple interfaces:

interface A {
void methodA();
}

interface B {
void methodB();
}

interface C extends A, B {
void methodC();
}

class D implements C {
public void methodA() {
System.out.println("Implementing methodA()");
}

public void methodB() {


System.out.println("Implementing methodB()");
}

public void methodC() {


System.out.println("Implementing methodC()");
}
}

In this example:
• Interface C extends both Interface A and Interface B, so it inherits methodA() and methodB().
• Class D implements Interface C, so it must provide implementations for methodA(), methodB(), and
methodC().
Explanation of Interface Inheritance
• Single Interface Inheritance: When one interface extends another, the sub-interface inherits all the
abstract methods of the parent interface.
• Multiple Interface Inheritance: If an interface extends multiple interfaces, it inherits methods from all
of them. A class that implements such an interface must implement all the methods from the parent
interfaces as well as any methods in the child interface.
• No Method Bodies: Interfaces do not have method bodies, so there is no ambiguity (unlike classes),
even if multiple interfaces define methods with the same signature.

Practice Program
Here’s a simple program that demonstrates inheritance of interfaces in Java:

interface Vehicle {
void start();
}
interface FourWheeler extends Vehicle {
void accelerate();
}
class Car implements FourWheeler {
public void start() {
System.out.println("Car is starting");
}
public void accelerate() {
System.out.println("Car is accelerating");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.start();
myCar.accelerate();
}
}

Explanation:
• FourWheeler extends Vehicle, so it inherits the start() method.
• Car implements FourWheeler, so it must provide implementations for both start() and accelerate()
methods.
Do It Yourself

1. Create an OnlinePayment interface that contains methods for making a payment. Extend this interface
to create a CreditCardPayment interface. Write a class that implements both and processes a payment.
2. Define a Device interface with a turnOn() method. Extend it to create a SmartDevice interface that
includes connectToWiFi(). Implement both in a SmartLight class.
3. Design a User interface and extend it to create a StudentUser interface. Implement a class that allows a
student to borrow books from the library using methods from both interfaces.
4. Create a Team interface with methods to addPlayer(). Extend it with a FootballTeam interface to include
setFormation(). Implement these in a FootballClub class.
5. Define an OnlineCourse interface with startCourse() method. Extend it with LiveCourse and
RecordedCourse interfaces. Implement both in a JavaCourse class.

Quiz

1. What happens when an interface inherits another interface in Java?


A) The new interface gets the method bodies from the parent interface.
B) The new interface inherits the method signatures from the parent interface.
C) The new interface cannot define any new methods.
D) The new interface becomes an abstract class.

Answer: B

2. If an interface extends two interfaces with the same method signature, how many methods does a
class implementing this interface need to implement?
A) One method
B) Two methods
C) No methods
D) It depends on the return types

Answer: A
3. Which of the following is true about interface inheritance?
A) An interface can extend a class.
B) An interface can extend multiple interfaces.
C) A class can extend multiple interfaces.
D) A class that implements an interface cannot implement another interface.
Answer: B

4.What must a class do when it implements an interface that extends another interface?
A) Implement methods from the sub-interface only.
B) Implement methods from the parent interface only.
C) Implement methods from both the parent and sub-interfaces.
D) Nothing, as interface methods do not require implementation.

Answer: C

5.Which of the following is correct about extending multiple interfaces in Java?


A) It leads to ambiguity.
B) It is not allowed in Java.
C) It is allowed and there’s no ambiguity because interfaces do not have method implementations.
D) A class that implements multiple interfaces must implement each interface separately.

Answer: C

Default Methods in Interfaces


In Java 8, a significant addition was made to the interface construct: default methods. Prior to Java 8, interfaces
could only contain abstract methods (methods without a body). However, default methods allow developers
to add methods with an implementation inside an interface without affecting classes that implement it.

Key Benefits of Default Methods:

• Backward compatibility: When a new method is added to an interface, all existing classes that
implement the interface would break unless the new method is provided with a default implementation.
• Code reusability: Default methods enable us to share common logic across all implementing classes,
reducing code duplication.
Syntax:
interface InterfaceName {
// Abstract method
void abstractMethod();

// Default method
default void defaultMethod() {
System.out.println("This is a default method.");
}
}

In this example, defaultMethod() has a body and can be overridden by implementing classes.
Example:
interface Animal {
// Abstract method
void sound();

// Default method
default void sleep() {
System.out.println("The animal is sleeping.");
}
}

class Dog implements Animal {


@Override
public void sound() {
System.out.println("Dog barks");
}
}
class Cat implements Animal {
@Override
public void sound() {
System.out.println("Cat meows");
}

// Overriding the default method


@Override
public void sleep() {
System.out.println("Cat sleeps quietly.");
}
}
public class Main {
public static void main(String[] args) {
Animal dog = new Dog();
dog.sound(); // Output: Dog barks
dog.sleep(); // Output: The animal is sleeping.

Animal cat = new Cat();


cat.sound(); // Output: Cat meows
cat.sleep(); // Output: Cat sleeps quietly.
}
}

Explanation:
• The Animal interface defines a default method sleep() and an abstract method sound().
• The Dog class implements Animal and uses the default implementation of sleep().
• The Cat class also implements Animal but overrides the sleep() method, providing its own
implementation.

Practice Program:
interface Vehicle {
void speed();

default void fuel() {


System.out.println("The vehicle runs on fuel.");
}
}

class Car implements Vehicle {


@Override
public void speed() {
System.out.println("Car speed: 100 km/h");
}
}
class ElectricCar implements Vehicle {
@Override
public void speed() {
System.out.println("Electric Car speed: 120 km/h");
}
@Override
public void fuel() {
System.out.println("The electric car runs on electricity.");
}
}
public class VehicleDemo {
public static void main(String[] args) {
Vehicle car = new Car();
car.speed(); // Output: Car speed: 100 km/h
car.fuel(); // Output: The vehicle runs on fuel.
Vehicle electricCar = new ElectricCar();
electricCar.speed(); // Output: Electric Car speed: 120 km/h
electricCar.fuel(); // Output: The electric car runs on electricity.
}
}
Explanation:
In this program, we have:

• An interface Vehicle with a default method fuel() and an abstract method speed().
• The Car class uses the default implementation of fuel(), while the ElectricCar class overrides it.

Do It Yourself

1. Write an interface Shape with a default method draw() and implement it in classes Circle and Square,
overriding the draw() method in Square.
2. Create an interface Appliance with a default method powerOn() and abstract method function().
Implement the interface in Fan and WashingMachine.
3. Modify the Dog class from the example above to override the sleep() method.
4. Write an interface Device with a default method start(), then create two classes Laptop and Smartphone
that implement it.
5. Add a new default method in the Vehicle interface from the practice program, and override it in the
ElectricCar class.

Quiz

1. What is the main purpose of default methods in Java interfaces?


a) To allow interfaces to define constants
b) To provide a method implementation
c) To replace abstract methods
d) To allow multiple inheritance

Answer: b) To provide a method implementation

2.Which version of Java introduced default methods?


a) Java 6
b) Java 7
c) Java 8
d) Java 9
Answer: c) Java 8

3.Can a class that implements an interface override a default method?


a) Yes
b) No

Answer: a) Yes

4.If a class does not override a default method, what happens?


a) The program will not compile
b) The class will use the default method implementation
c) The method will throw an exception
d) The method becomes abstract
Answer: b) The class will use the default method implementation

5.Can an interface have both abstract and default methods?


a) Yes
b) No

Answer: a) Yes

Static Methods in Interface


Static methods in interfaces were introduced in Java 8, allowing interfaces to include method definitions with
the static keyword. These methods belong to the interface rather than to an instance of a class that implements
the interface. This enables developers to provide utility methods related to an interface directly inside the
interface, similar to static methods in classes.

Key Characteristics of Static Methods in Interfaces:

1. Not Inherited: Static methods are not inherited by classes that implement the interface.
2. Accessed via Interface Name: They must be accessed using the interface name, not through class
instances.
3. Used for Utility Methods: They are generally used to provide utility methods that are relevant to the
interface's functionality but do not need to be overridden by implementing classes.

Syntax:
interface InterfaceName {
// Static method
static void staticMethod() {
System.out.println("This is a static method in the interface.");
}
}

In this syntax, the static method staticMethod() belongs to the interface and must be invoked using the
interface name.
Example:
interface Calculator {
// Abstract method
int add(int a, int b);

// Static method
static int subtract(int a, int b) {
return a - b;
}
}
class SimpleCalculator implements Calculator {
@Override
public int add(int a, int b) {
return a + b;
}
}

public class Main {


public static void main(String[] args) {
Calculator calc = new SimpleCalculator();
System.out.println("Addition: " + calc.add(10, 5)); // Output: 15

// Accessing the static method from the interface


System.out.println("Subtraction: " + Calculator.subtract(10, 5)); // Output: 5
}
}

Explanation:
• The Calculator interface defines a static method subtract() and an abstract method add().
• The class SimpleCalculator implements the add() method, but it does not need to implement the
subtract() method since it is static and belongs to the interface.
• The static method is accessed using the interface name (Calculator.subtract()), not through an instance
of the class.

Practice Program:
interface Converter {
// Static method
static double inchesToCentimeters(double inches) {
return inches * 2.54;
}

// Abstract method
double centimetersToInches(double centimeters);
}
class UnitConverter implements Converter {
@Override
public double centimetersToInches(double centimeters) {
return centimeters / 2.54;
}
}
public class ConverterDemo {
public static void main(String[] args) {
// Accessing static method from the interface
System.out.println("10 inches in cm: " + Converter.inchesToCentimeters(10)); // Output: 25.4
// Using an instance to call the abstract method
UnitConverter converter = new UnitConverter();
System.out.println("25.4 cm in inches: " + converter.centimetersToInches(25.4)); // Output: 10.0
}
}
Explanation:
• The interface Converter contains a static method inchesToCentimeters() and an abstract method
centimetersToInches().
• The UnitConverter class implements the centimetersToInches() method.
• The static method inchesToCentimeters() is accessed directly using the interface name.

Static methods in interfaces allow utility methods to be defined directly within the interface. These methods
are not inherited by implementing classes and can be accessed using the interface name. Introduced in Java 8,
static methods add flexibility in providing shared functionality across all implementing classes without requiring
code duplication.

Do It Yourself

1. Create an interface TemperatureConverter with a static method to convert Fahrenheit to Celsius and an
abstract method to convert Celsius to Fahrenheit. Implement the interface in a class TempConverter.
2. Write an interface MathOperations with a static method multiply(int a, int b) and an abstract method
divide(int a, int b). Implement the interface in a class BasicMath.
3. Modify the Calculator example to add another static method multiply() in the interface and use it in the
Main class.
4. Write a program with an interface DistanceConverter that contains a static method to convert
kilometers to miles. Implement the interface to add an abstract method that converts miles to
kilometers.
5. Write an interface ShapeUtils with a static method calculateArea() that takes the radius of a circle and
returns the area. Implement the interface to add abstract methods for perimeter calculation.

Quiz

1. How are static methods in an interface accessed in Java?


a) Through an instance of the implementing class
b) Through the class name
c) Through the interface name
d) Through inheritance

Answer: c) Through the interface name

2.What is true about static methods in interfaces?


a) They can be overridden by implementing classes.
b) They can only be accessed through instances of the interface.
c) They must be implemented by all classes that implement the interface.
d) They are not inherited by implementing classes.

Answer: d) They are not inherited by implementing classes.

3.In which version of Java were static methods in interfaces introduced?


a) Java 6
b) Java 7
c) Java 8
d) Java 9

Answer: c) Java 8

4.Can static methods in interfaces access instance variables?


a) Yes, always
b) No, static methods cannot access instance variables
c) Yes, but only if they are public
d) Yes, but only through inheritance

Answer: b) No, static methods cannot access instance variables

5.Which of the following is a valid reason to use static methods in interfaces?


a) To provide methods that can be overridden
b) To provide utility methods that belong to the interface
c) To replace abstract methods
d) To provide multiple inheritance

Answer: b) To provide utility methods that belong to the interface

Functional Interfaces in Java


Introduction: A functional interface in Java is an interface that contains only one abstract method (though it
can have multiple default or static methods). These interfaces are often used to represent functions or actions
in a concise and readable manner. The introduction of lambda expressions in Java 8 made functional interfaces
especially important because lambda expressions require the context of a functional interface to work.

Java provides several built-in functional interfaces such as Runnable, Callable, Comparator, etc., and allows
developers to create custom functional interfaces.

Key Features of Functional Interfaces:

1. Single Abstract Method (SAM): A functional interface contains exactly one abstract method. This is also
known as the Single Abstract Method (SAM) rule.
2. Default and Static Methods Allowed: A functional interface can have multiple default or static methods.
3. @FunctionalInterface Annotation: Although optional, using the @FunctionalInterface annotation helps
ensure that the interface is treated as a functional interface by the compiler.

Syntax:
@FunctionalInterface
interface MyFunctionalInterface {
void myMethod();
}

In this example, MyFunctionalInterface is a functional interface with a single abstract method myMethod().
Example 1: Simple Functional Interface
@FunctionalInterface
interface Greeting {
void sayHello(String name);
}
public class Main {
public static void main(String[] args) {
// Using Lambda Expression to implement the Functional Interface
Greeting greet = (name) -> System.out.println("Hello, " + name);

// Calling the method


greet.sayHello("Meera");
}
}

Explanation:
• The Greeting interface contains one abstract method sayHello(), making it a functional interface.
• A lambda expression is used to provide the implementation of sayHello() in the Main class.
• The method is invoked by passing the name "Meera", which prints Hello, Meera to the console.

Example 2: Using Built-In Functional Interface (Runnable)


public class RunnableExample {
public static void main(String[] args) {
// Lambda Expression for Runnable Functional Interface
Runnable task = () -> System.out.println("Task is running...");
// Using Thread to run the task
Thread thread = new Thread(task);
thread.start();
}
}

Explanation:
• Runnable is a functional interface provided by Java.
• It has a single abstract method run(), which is implemented using a lambda expression in this example.
• The lambda expression represents the task to be run by a new thread.

Built-in Functional Interfaces in Java


Java provides several built-in functional interfaces that are commonly used with lambda expressions. Some
examples include:

• Function<T, R>: Represents a function that accepts one argument and produces a result.
• Consumer<T>: Represents an operation that accepts a single argument and returns no result.
• Supplier<T>: Represents a supplier of results, i.e., a method that returns a value but takes no arguments.
• Predicate<T>: Represents a predicate (boolean-valued function) of one argument.
Example: Using Function<T, R> Functional Interface
import java.util.function.Function;
public class FunctionExample {
public static void main(String[] args) {
// Using Function Functional Interface to convert String to Integer
Function<String, Integer> stringToLength = (str) -> str.length();
System.out.println("Length of 'Functional': " + stringToLength.apply("Functional")); // Output: 9
}
}

Explanation:

Function<String, Integer> takes a String as input and returns an Integer as output.


The lambda expression is used to implement the apply() method, which calculates and returns the length of the
string.

Here's the modified version of your content with clearer formatting, consistent naming conventions, and minor
enhancements for better understanding:

Predicate
The Predicate functional interface represents a function that accepts an argument and returns a boolean value
based on a condition. It is commonly used in situations where filtering or testing logic is required. For example,
it can be used to check whether a given number is even or odd.

Example: Predicate Functional Interface


import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class PredicateExample {
public static void main(String[] args) {
List<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
numbers.add(5);

// Predicate to check if a number is even


Predicate<Integer> isEven = n -> n % 2 == 0;
// Filtering odd numbers using Predicate.negate()
List<Integer> oddNumbers = numbers.stream()
.filter(isEven.negate())
.toList();
System.out.println("Odd numbers: " + oddNumbers);
}
}
Explanation:
• The Predicate<Integer> functional interface named isEven checks whether the given integer is even
using the modulo operator %.
• The Stream API's filter() method is used to create a list of odd numbers by negating the isEven predicate
using the negate() method.

Consumer
The Consumer functional interface takes an argument but does not return a value. It is typically used for
operations like printing or modifying data without returning any result.

Example: Consumer Functional Interface


import java.util.function.Consumer;
public class ExampleConsumer {
public static void main(String[] args) {
// Consumer to print the length of a string
Consumer<String> printLength = (String str) -> System.out.println("Length of string: " + str.length());
// Using accept() method
printLength.accept("Hello, world!"); // Output: Length of string: 13
}
}
Explanation:
• The Consumer<String> interface named printLength takes a string and prints its length.
• The lambda expression (String str) -> System.out.println("Length of string: " + str.length()) defines the
behavior of the Consumer.
• The accept() method takes the string "Hello, world!" as an argument and prints the output.

Supplier
The Supplier functional interface does not take any arguments but returns a value. It is often used to provide
or generate values, such as a random number.
Example: Supplier Functional Interface
import java.util.function.Supplier;

public class ExampleSupplier {


public static void main(String[] args) {
// Supplier to generate a random integer between 0 and 100
Supplier<Integer> randomInt = () -> (int) (Math.random() * 100);
// Using get() method
System.out.println("Random number: " + randomInt.get());
}
}

Explanation:
• The Supplier<Integer> interface named randomInt generates and returns a random integer between 0
and 100.
• The lambda expression () -> (int) (Math.random() * 100) defines the behavior of the Supplier.
• The get() method is used to generate and return the random integer.

Function
The Function functional interface takes one argument and returns a result. It is often used for transformations,
such as converting a string into an integer or performing mathematical operations.

Example: Function Functional Interface


import java.util.function.Function;
public class ExampleFunction {
public static void main(String[] args) {
// Function to square an integer
Function<Integer, Integer> square = (Integer x) -> x * x;
// Using apply() method
System.out.println("Square of 5: " + square.apply(5)); // Output: Square of 5: 25
}
}

Explanation:
• The Function<Integer, Integer> interface named square takes an integer and returns its square.
• The lambda expression (Integer x) -> x * x defines the behavior of the Function.
• The apply() method is used to pass the integer 5 as an argument and return the squared result.

Key Points:
• Predicate: Returns a boolean value based on a condition.
• Consumer: Accepts an argument but does not return any value.
• Supplier: Returns a value but does not take any arguments.
• Function: Accepts an argument and returns a result.

Practice Program:
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}

public class CalculatorDemo {


public static void main(String[] args) {
// Lambda Expression for addition
Calculator addition = (a, b) -> a + b;
System.out.println("Addition: " + addition.calculate(5, 10)); // Output: 15
// Lambda Expression for subtraction
Calculator subtraction = (a, b) -> a - b;
System.out.println("Subtraction: " + subtraction.calculate(10, 5)); // Output: 5
}
}
Explanation:
• Calculator is a functional interface with one abstract method calculate().
• Lambda expressions are used to define the behavior for addition and subtraction.
• The calculate() method is invoked with the respective lambda expressions.

Functional interfaces play a crucial role in Java, especially after the introduction of lambda expressions in Java
8. They allow for cleaner, more expressive code by using anonymous methods (lambda expressions) to
implement behavior without needing a full class. In Java, functional interfaces can be custom-defined or utilize
the built-in interfaces provided in the java.util.function package. This reading material, including syntax,
examples, practice programs, homework questions, and multiple-choice questions, provides a comprehensive
understanding of functional interfaces for students.

Do It Yourself

1. Create a functional interface ShapeArea that calculates the area of different shapes using lambda
expressions. Implement the functional interface for calculating the area of a circle and a rectangle.
2. Write a program that uses the Predicate functional interface to check if a given number is even or odd
using lambda expressions.
3. Create a functional interface StringManipulator with a method that takes a string and returns its
uppercase equivalent. Use a lambda expression to implement it.
4. Write a functional interface MathOperation with a method that performs a division of two integers. Use
a lambda expression to provide the implementation and handle division by zero gracefully.
5. Implement a functional interface EmployeeBonusCalculator that calculates bonuses for employees
based on their performance score using lambda expressions.

Quiz

1. What is the main feature of a functional interface?


a) It can have multiple abstract methods.
b) It can have only one abstract method.
c) It cannot have any methods.
d) It must be implemented by an abstract class.

Answer: b) It can have only one abstract method.

2.Which annotation is used to declare a functional interface in Java?


a) @FunctionalInterface
b) @Override
c) @Lambda
d) @Interface
Answer: a) @FunctionalInterface

3.What is the use of the @FunctionalInterface annotation?


a) To make an interface non-inheritable.
b) To enforce that the interface contains only one abstract method.
c) To define that an interface must have a default method.
d) To specify that an interface must be static.

Answer: b) To enforce that the interface contains only one abstract method.

4.Lambda expressions in Java are typically associated with:


a) Abstract classes
b) Functional interfaces
c) Inheritance
d) Packages

Answer: b) Functional interfaces

5.Which of the following is a valid built-in functional interface in Java?


a) Runnable
b) Function<T, R>
c) Supplier<T>
d) All of the above

Answer: d) All of the above

Annotations in Java
Annotations in Java provide metadata to the program elements like classes, methods, variables, and more.
They help supplement the code with additional information that can be processed by the compiler or JVM,
without altering the actual functionality of the code.

• Annotations start with @.


• They do not change the behavior of a compiled program.
• They are used to attach metadata to variables, constructors, methods, classes, etc.
• They are more than comments because they may affect how the compiler or runtime processes the
code.
• They can replace some uses of XML configurations and marker interfaces.
Hierarchy of Annotations in Java
Java annotations can be categorized into built-in and custom annotations. Below, we will explore how
annotations are implemented, followed by the different types and categories of annotations.
Annotation Syntax
Annotations in Java are written using the @ symbol followed by the annotation name. They are applied to
classes, methods, fields, or parameters.

@AnnotationName
public class MyClass {
// class code
}

Example: Annotations Are Not Just Comments


In the following program, the @Override annotation is used to indicate that a method is intended to override
a method in its superclass. If the method does not correctly override a superclass method, a compile-time error
occurs.

Code Example
class BaseClass {
public void show() {
System.out.println("BaseClass show()");
}
}
class SubClass extends BaseClass {
// Incorrect override due to method signature mismatch
@Override
public void show(int x) {
System.out.println("SubClass show(int x)");
}
public static void main(String[] args) {
SubClass obj = new SubClass();
obj.show();
}
}
Output:
Error: method does not override or implement a method from a supertype

If you remove the (int x) parameter or the @Override annotation, the program will compile successfully.

Categories of Annotations
1. Marker Annotations:

Marker annotations are used to mark a declaration. These annotations contain no members and do not hold
any data.
Example:
@Override

2.Single-Value Annotations:
These annotations contain a single member and allow a shorthand for specifying the value of that member.
Example:

@TestAnnotation("Test Value")

3.Full Annotations:
These annotations contain multiple members and store multiple values using a key-value pair format.
Example:
@TestAnnotation(owner = "John", value = "Test Class")

4.Type Annotations:
Type annotations can be applied to any use of a type (e.g., return types, variables, etc.).
Example:

@interface TypeAnno {}

@TypeAnno String message = "Type Annotated String";

5.Repeating Annotations:

Repeating annotations allow applying the same annotation multiple times to a single element.
Example:
@Words(word = "Hello", value = 1)
@Words(word = "World", value = 2)
public void greet() { }

Predefined (Standard) Annotations


Java includes several predefined annotations, such as:

1. @Deprecated:
• Marks an element as obsolete.

@Deprecated
public void oldMethod() {
// Old code
}

2. @Override:

• Ensures that a method overrides a superclass method.

@Override
public void toString() {
return "Override Example";
}

3. @SuppressWarnings:
• Instructs the compiler to suppress specific warnings.

@SuppressWarnings("unchecked")
public void myMethod() {
// code
}

User-Defined (Custom) Annotations


Developers can define their own annotations using the @interface keyword.

Syntax for Custom Annotations:


@interface MyAnnotation {
String name();
int value() default 0;
}

Example of a Custom Annotation:


@interface Developer {
String developer() default "Unknown";
String date();
}

public class CustomAnnotationExample {


@Developer(developer = "Alice", date = "01/01/2024")
public void myMethod() {
System.out.println("Method with custom annotation");
}
public static void main(String[] args) {
CustomAnnotationExample obj = new CustomAnnotationExample();
obj.myMethod();
}
}

Practice Program
Write a Java program to use annotations:

@Retention(RetentionPolicy.RUNTIME)
@interface MyMarker { }

public class TestMarkerAnnotation {

@MyMarker
public void markedMethod() {
System.out.println("This method is marked with a custom annotation.");
}
public static void main(String[] args) {
TestMarkerAnnotation obj = new TestMarkerAnnotation();
obj.markedMethod();
}
}

Annotations in Java are a powerful tool for associating metadata with program elements. They play a vital role
in modern Java development, offering flexibility in code documentation, compiler instructions, and runtime
processing.

Do It Yourself

1. Write a program to define and use a custom annotation.


2. Create a repeatable annotation and apply it to a method.
3. Use the @Deprecated annotation in a class and explain its impact.
4. Explain the difference between @Override and @SuppressWarnings annotations in Java.

Quiz

1. Which of the following is not a predefined annotation in Java?


a) @Override
b) @SuppressWarnings
c) @Marker
d) @Deprecated
Answer: c) @Marker

2.What is the primary purpose of marker annotations?


a) To store data
b) To provide metadata
c) To mark a declaration
d) To generate runtime exceptions
Answer: c) To mark a declaration

3.What is the default retention policy of annotations?


a) SOURCE
b) RUNTIME
c) CLASS
d) FIELD
Answer: c) CLASS

4.Which of the following annotations is used to suppress warnings in Java?


a) @SuppressWarnings
b) @Override
c) @Deprecated
d) @Retention
Answer: a) @SuppressWarnings
5.What is required to create a repeatable annotation in Java?
a) @Retention
b) @Target
c) @Repeatable
d) @Documented
Answer: c) @Repeatable

You might also like