OOP_Java_QB Ans
OOP_Java_QB Ans
These are the important questions in Object Oriented Programming using Java taken
from previous year questions, the questions in bold have repeated multiple times
The lab programs are very important
Module 01
An Overview of Java: Object-Oriented Programming (Two Paradigms, Abstraction, The Three OOP Principles),
Using Blocks of Code, Lexical Issues (Whitespace, Identifiers, Literals, Comments, Separators, The Java
Keywords).
Data Types, Variables, and Arrays: The Primitive Types (Integers, Floating-Point Types, Characters, Booleans),
Variables, Type Conversion and Casting, Automatic Type Promotion in Expressions, Arrays, Introducing Type
Inference with Local Variables.
Operators: Arithmetic Operators, Relational Operators, Boolean Logical Operators, The Assignment Operator,
The? Operator, Operator Precedence, Using Parentheses.
Control Statements: Java’s Selection Statements (if, The Traditional switch), Iteration Statements (while, do-
while, for, The For-Each Version of the for Loop, Local Variable Type Inference in a for Loop, Nested Loops),
Jump Statements (Using break, Using continue, return).
Page | 1
Explanation:
The binary representation of 20 (00010100) becomes 00000101 after shifting 2 bits to the right. This
is equivalent to 20/22=520 / 2^2 = 520/22=5.
1. Encapsulation
Encapsulation is the process of bundling the data (attributes) and methods (functions) that operate on
the data into a single unit called a class. It also restricts direct access to some components of an object
to protect its integrity.
Key Features:
Page | 2
Access Modifiers: Control visibility of class members (e.g., private, protected, public).
Getter and Setter Methods: Provide controlled access to private attributes.
Example:
class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Student student = new Student();
student.setName("John Doe"); // Using setter
System.out.println(student.getName()); // Using getter
}
}
Benefits:
Protects data integrity.
Hides internal implementation details.
2. Inheritance
Inheritance allows a class (child or subclass) to inherit the properties and methods of another class
(parent or superclass). This promotes code reusability and hierarchical relationships.
Key Features:
A child class can extend a parent class.
The child class can override methods of the parent class.
Example:
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
class Dog extends Animal {
void bark() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited from Animal class
dog.bark(); // Defined in Dog class
}
}
Benefits:
Avoids code duplication.
Establishes an "is-a" relationship.
3. Polymorphism
Polymorphism allows objects to take multiple forms. The same method can behave differently based
on the object or context. There are two types:
Compile-Time Polymorphism (Method Overloading): Achieved by defining multiple
methods with the same name but different parameters.
Runtime Polymorphism (Method Overriding): Achieved by overriding a method in a
subclass.
Example 1: Method Overloading
Page | 3
class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(5, 3));
System.out.println(calc.add(5.5, 3.5));
}
}
Example 2: Method Overriding
class Animal {
void sound() {
System.out.println("Animal makes a sound.");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Dog(); // Upcasting
animal.sound(); // Calls Dog's sound method
}
}
Benefits:
Enhances flexibility and reusability.
Simplifies code readability.
4. Abstraction
Abstraction focuses on showing only the essential details of an object while hiding its internal
implementation. It can be achieved using:
Abstract Classes
Interfaces
Key Features:
Abstract classes can have both abstract (unimplemented) and concrete (implemented)
methods.
Interfaces provide a contract that classes must implement.
Example 1: Using an Abstract Class
abstract class Shape {
abstract void draw(); // Abstract method
}
class Circle extends Shape {
void draw() {
System.out.println("Drawing a circle.");
}
}
public class Main {
public static void main(String[] args) {
Shape shape = new Circle();
shape.draw();
Page | 4
}
}
Example 2: Using an Interface
interface Drawable {
void draw();
}
class Rectangle implements Drawable {
public void draw() {
System.out.println("Drawing a rectangle.");
}
}
public class Main {
public static void main(String[] args) {
Drawable drawable = new Rectangle();
drawable.draw();
}
}
Benefits:
Provides a clear separation between what an object does and how it does it.
Promotes a cleaner, modular codebase.
03. Develop a Java Program to add two matrices using command line arguments 10
An public class MatrixAddition {
s public static void main(String[] args) {
if (args.length != 1) {
System.out.println("Usage: java MatrixAddition
<order_N>");
return;
}
int N = Integer.parseInt(args[0]);
if (N <= 0) {
System.out.println("Please provide a valid positive
integer for the
order N.");
return;
}
int[][] matrix1 = new int[N][N];
int[][] matrix2 = new int[N][N];
fillMatrix(matrix1, 1);
fillMatrix(matrix2, 2);
System.out.println("Matrix 1:");
Page | 5
printMatrix(matrix1);
System.out.println("\nMatrix 2:");
printMatrix(matrix2);
int[][] resultMatrix = addMatrices(matrix1, matrix2);
// Print the result matrix
System.out.println("\nResultant Matrix (Matrix1 +
Matrix2):");
printMatrix(resultMatrix);
}
private static void fillMatrix(int[][] matrix, int startValue)
{
int value = startValue;
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
matrix[i][j] = value++;
}
}
}
private static int[][] addMatrices(int[][] matrix1, int[][]
matrix2) {
int N = matrix1.length;
int[][] resultMatrix = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
resultMatrix[i][j]=matrix1[i][j]+matrix2[i][j];
}
}
return resultMatrix;
}
private static void printMatrix(int[][] matrix) {
for (int[] row : matrix) {
for (int value : row) {
System.out.print(value + "\t");
}
System.out.println();
}
}
}
04. Discuss the different data types supported by Java along with the default values and literals 8
An Java is a statically-typed programming language, meaning every variable must be declared with a
s specific data type before it can be used. Java data types are divided into primitive data types and
non-primitive data types.
1. Primitive Data Types
Primitive data types are predefined by the Java language. These are the most basic data types and
cannot be broken down further.
Categories of Primitive Data Types
Page | 6
Details of Primitive Types:
1. byte:
o Range: −128-128−128 to 127127127.
o Suitable for saving memory in large arrays.
byte b = 100;
2. short:
o Range: −32,768-32,768−32,768 to 32,76732,76732,767.
o Rarely used as int is more common.
short s = 20000;
3. int:
o Range: −231-2^{31}−231 to 231−12^{31}-1231−1.
o Default type for integer literals.
int num = 100000;
4. long:
o Range: −263-2^{63}−263 to 263−12^{63}-1263−1.
o Must be suffixed with L or l for literals.
long bigNumber = 10000000000L;
5. float:
o Used for single-precision floating-point calculations.
o Must be suffixed with f or F for literals.
float pi = 3.14f;
6. double:
o Default type for decimal numbers; supports high precision.
double area = 12.5678;
7. char:
o Stores a single character or Unicode value.
char letter = 'A'
char unicode = '\u0041'; // Unicode for 'A'
8. boolean:
o Holds only true or false.
boolean isJavaFun = true;
Literals in Java
Literals represent fixed values that can be assigned to variables.
Types of Literals
1. Integer Literals:
o Decimal: int num = 100;
o Octal: int num = 0123; (starts with 0).
o Hexadecimal: int num = 0x1A; (starts with 0x or 0X).
o Binary: int num = 0b1010; (starts with 0b or 0B).
2. Floating-Point Literals:
o Examples: 3.14, 0.5f, 1.2e3 (scientific notation).
3. Character Literals:
o Single character enclosed in single quotes: 'A', '1', '\n'.
o Unicode representation: '\u0041' (Unicode for 'A').
4. String Literals:
o Sequence of characters enclosed in double quotes: "Hello".
5. Boolean Literals:
o Only true or false.
6. Null Literal:
o Represents the absence of a value for reference types: null.
Page | 8
System.out.println(celsius + "°C is equal to " + fahrenheit
+ "°F");
scanner.close();
}
}
06. Justify the statement “Compile once and run anywhere” in Java 8
An The statement "Compile once, run anywhere" is a fundamental principle of Java. This means that
s Java programs, once compiled, can run on any platform that has a Java Virtual Machine (JVM),
regardless of the underlying hardware and operating system. This platform independence is achieved
through Java's architecture and its bytecode-based execution model.
Justification
1. Source Code Compilation to Bytecode:
o When a Java program is compiled, it is not converted directly into machine code
(specific to a hardware platform) like traditional languages such as C/C++.
o Instead, the Java compiler (javac) converts the source code into an intermediate,
platform-independent format called bytecode (contained in .class files).
2. Bytecode and JVM:
o The compiled bytecode can be executed on any device or platform that has a JVM
installed.
o The JVM is responsible for interpreting or just-in-time (JIT) compiling the bytecode
into native machine code that the specific platform's processor can execute.
3. Write Once, Run Anywhere (WORA):
o As the JVM abstracts platform-specific details, the same bytecode can run on
Windows, macOS, Linux, or any other system with a compatible JVM.
o Developers do not need to modify the code for different platforms.
Page | 9
Advantages of “Compile Once, Run Anywhere”
1. Portability:
o Applications can run on any platform with a JVM, making Java ideal for cross-
platform development.
2. Reduced Development Time:
o Developers do not need to rewrite or recompile code for different platforms.
3. Code Consistency:
o The same bytecode runs identically on all JVMs, ensuring consistent behavior across
platforms.
4. Scalability:
o Java applications can scale easily across different environments without significant
modifications.
Conclusion
Java achieves platform independence through its bytecode and JVM. By compiling the code once into
bytecode and relying on JVM implementations for different platforms, Java ensures that applications
are portable and can "write once, run anywhere." This principle has been one of the key reasons for
Java's widespread adoption in diverse domains like web development, enterprise applications, and
mobile development.
07. List the various operators supported by Java. Illustrate the working of >> and >>> operators with an 6
example
An Operators Supported by Java
s Java provides a rich set of operators, which are categorized as follows:
1. Arithmetic Operators
Perform basic mathematical operations.
Operator Operation Example
+ Addition a+b
- Subtraction a-b
* Multiplication a * b
/ Division a/b
% Modulus a%b
3. Logical Operators
Used for combining boolean expressions.
Operator Operation Example
&& Logical AND (a > b) && (b > c)
` `
! Logical NOT !(a > b)
4. Bitwise Operators
Operate at the binary level.
Operator Operation Example
& Bitwise AND a&b
` ` Bitwise OR
Page | 10
^ Bitwise XOR a^b
~ Bitwise Complement ~a
<< Left Shift a << 2
>> Right Shift a >> 2
>>> Unsigned Right Shift a >>> 2
5. Assignment Operators
Assign values to variables.
Operator Operation Example
= Assign a = 10
+= Add and assign a += 5
-= Subtract and assign a -= 5
*= Multiply and assign a *= 2
/= Divide and assign a /= 2
%= Modulus and assign a %= 2
6. Unary Operators
Operate on a single operand.
Operator Operation Example
+ Unary plus +a
- Unary minus -a
++ Increment a++
-- Decrement a--
! Logical NOT !a
7. Ternary Operator
Syntax: condition ? value1 : value2
Example:
int a = 5, b = 10;
int max = (a > b) ? a : b; // max = 10
8. Special Operators
Operator Operation Example
instanceof Checks object type obj instanceof String
new Creates an object String s = new String();
Examples
Example Code for >> and >>>:
public class ShiftOperators {
public static void main(String[] args) {
int num1 = 32; // Positive number
int num2 = -32; // Negative number
Page | 11
System.out.println("num2 >> 2: " + (num2 >> 2));
System.out.println("num1 >>> 2: " + (num1 >>> 2));
System.out.println("num2 >>> 2: " + (num2 >>> 2));
}
}
Output Explanation
For num1 = 32 (binary: 00000000 00100000) and num2 = -32 (binary: 11111111 11100000):
1. num1 >> 2:
o Binary: 00000000 00100000 → 00000000 00001000
o Result: 8
2. num2 >> 2:
o Binary: 11111111 11100000 → 11111111 11111000 (preserving sign bit)
o Result: -8
3. num1 >>> 2:
o Binary: 00000000 00100000 → 00000000 00001000
o Result: 8
4. num2 >>> 2:
o Binary: 11111111 11100000 → 00111111 11111000 (fills with 0s)
o Result: A large positive value (e.g., 1073741816).
1. Case Sensitivity
Java is case-sensitive, meaning identifiers like MyVariable and myvariable are treated as
different entities.
Example:
int value = 5;
System.out.println(Value); // Error: Value cannot be resolved to a variable
Issue: Developers may accidentally use inconsistent capitalization, leading to errors.
2. Use of Keywords
Keywords are reserved words in Java with predefined meanings (e.g., class, int, if, static).
These cannot be used as identifiers for variables, methods, or classes.
Example:
int class = 10; // Error: 'class' is a reserved word
Issue: Accidental use of keywords can result in syntax errors.
4. Literals
Java supports different types of literals (integer, floating-point, character, string, boolean).
Misuse or improper formatting of literals can lead to errors.
Example:
int num = 123L; // Error: Possible loss of precision
Issue: Mixing data types or omitting necessary type suffixes (L, F) can cause issues.
Page | 12
5. Escape Sequences
Java uses escape sequences (e.g., \n, \t, \") in string and character literals.
Improper use or omission of escape sequences can lead to lexical errors.
Example:
String str = "This is a "test" string"; // Error: Unterminated
string literal
Issue: Forgetting escape sequences for special characters like quotes or backslashes.
6. Comments Misuse
Java supports single-line (//) and multi-line (/* */) comments.
Unclosed or improperly nested comments can lead to compilation errors.
Example:
/* This is a comment
System.out.println("Hello"); // Error: Unclosed comment
Issue: Missing comment closures disrupt code parsing.
7. Unicode Characters
Java supports Unicode, allowing identifiers and literals to use characters from various
languages.
Misusing Unicode escape sequences (\uXXXX) can lead to unintended results.
Example:
char ch = '\u123G'; // Error: Invalid Unicode escape
Issue: Improper Unicode syntax or unsupported characters.
8. String Concatenation
String literals can be concatenated using the + operator.
Improperly formatted concatenations may result in unexpected outputs.
Example:
System.out.println("Result: " + 10 + 20); // Output: Result:
1020
Issue: Misinterpretation of operator precedence can lead to logical errors.
9. Whitespace Sensitivity
Java ignores extra whitespace between tokens but requires whitespace in specific cases, such
as separating keywords or identifiers.
Example:
intnewVariable = 5; // Error: 'intnewVariable' cannot be
resolved to a type
Issue: Missing whitespace between tokens results in invalid syntax.
1. Simple if Statement
The simplest form of an if statement, used when you want to execute a single block of code if a
condition is true.
Syntax:
if (condition) {
// Code to be executed if the condition is true
}
Example:
int age = 20;
if (age >= 18) {
System.out.println("You are eligible to vote.");
}
2. if-else Statement
Used when there are two possible paths: one if the condition is true and another if it is false.
Syntax:
if (condition) {
// Code to execute if the condition is true
} else {
// Code to execute if the condition is false
}
Example:
int age = 16;
if (age >= 18) {
System.out.println("You are eligible to vote.");
} else {
System.out.println("You are not eligible to vote.");
}
4. Nested if Statement
An if statement inside another if statement, used when there is a need to check a condition only if a
previous condition is true.
Syntax:
if (condition1) {
if (condition2) {
// Code to execute if both condition1 and condition2 are true
}
}
Example:
int number = 10;
if (number > 0) {
if (number % 2 == 0) {
System.out.println("The number is positive and even.");
}
}
5. Ternary Operator (? :)
Though not an if statement, it is a shorthand for simple if-else statements.
Syntax:
variable = (condition) ? expression1 : expression2;
Example:
int age = 20;
String eligibility = (age >= 18) ? "Eligible to vote" : "Not eligible
to vote";
System.out.println(eligibility);
Page | 15
1. Traditional for Loop
This is the most commonly used form, where the loop is controlled using an initializer, condition, and
increment/decrement.
Syntax:
for (initialization; condition; update) {
// Code to execute
}
Example:
for (int i = 0; i < 5; i++) {
System.out.println("Iteration: " + i);
}
Output:
Iteration: 0
Iteration: 1
Iteration: 2
Iteration: 3
Iteration: 4
Page | 16
Example:
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
System.out.println("i = " + i + ", j = " + j);
}
}
Output:
i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 2, j = 1
i = 2, j = 2
i = 2, j = 3
i = 3, j = 1
i = 3, j = 2
i = 3, j = 3
Summary Table
Page | 17
Type Usage Example Use Case
Traditional for Loop General-purpose looping with Printing numbers from 1 to
counters. 100.
Enhanced for Loop Traversing arrays or collections. Iterating through a list of
items.
Infinite for Loop Running a loop until explicitly Server event loops.
stopped.
Nested for Loop Handling multidimensional data. Printing matrices.
Multiple Variables Managing multiple counters. Simultaneous iteration.
Loop
With Break/Continue Customizing flow within a loop. Skipping values or exiting
early.
11. Demonstrate working of break with labels in JAVA 7
An In Java, the break statement is commonly used to exit a loop or terminate a switch statement. With
s labels, the break statement can be used to exit nested loops by specifying which loop to break out of.
Here's a simple demonstration of the break statement with labels:
Code Example:
public class BreakWithLabelsDemo {
public static void main(String[] args) {
outer:
for (int i = 1; i <= 3; i++) {
System.out.println("Outer loop iteration: " + i);
for (int j = 1; j <= 3; j++) {
System.out.println(" Inner loop iteration: " + j);
if (i == 2 && j == 2) {
System.out.println("Breaking out of the outer
loop");
break outer;
}
}
}
System.out.println("Exited the loops");
}
}
Output:
Outer loop iteration: 1
Inner loop iteration: 1
Inner loop iteration: 2
Inner loop iteration: 3
Outer loop iteration: 2
Inner loop iteration: 1
Inner loop iteration: 2
Breaking out of the outer loop
Exited the loops
Explanation:
1. Label Definition: The outer label is assigned to the outer for loop.
2. Condition Check: When both i and j are 2, the break outer statement executes.
3. Effect of break outer: It directly terminates the labeled outer loop, skipping all remaining
iterations of both the inner and outer loops.
4. Program Continuation: After breaking out of the loops, the program resumes execution from
the statement following the outer loop.
1. Single-Dimensional Array
A single-dimensional array stores elements in a linear format (like a list).
Example:
public class SingleDimensionalArray {
public static void main(String[] args) {
// Declare and initialize an array
int[] numbers = {10, 20, 30, 40, 50};
2. Multi-Dimensional Array
A multi-dimensional array (commonly a 2D array) stores data in a matrix-like structure with rows and
columns.
Example:
public class MultiDimensionalArray {
public static void main(String[] args) {
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
Page | 19
{7, 8, 9}
};
System.out.println("Multi-Dimensional Array (2D 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:
Multi-Dimensional Array (2D Array):
1 2 3
4 5 6
7 8 9
3. Jagged Array
A jagged array is an array of arrays, where each sub-array can have a different length.
Example:
public class JaggedArray {
public static void main(String[] args) {
int[][] jaggedArray = {
{1, 2},
{3, 4, 5},
{6}
};
System.out.println("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:
Jagged Array:
1 2
3 4 5
6
4. Array of Objects
Arrays can also store objects instead of primitive data types.
Example:
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
void display() {
System.out.println("Name: " + name + ", Age: " + age);
}
}
public class ArrayOfObjects {
public static void main(String[] args) {
Student[] students = {
Page | 20
new Student("Alice", 20),
new Student("Bob", 22),
new Student("Charlie", 19)
};
System.out.println("Array of Objects:");
for (Student student : students) {
student.display();
}
}
}
Output:
Array of Objects:
Name: Alice, Age: 20
Name: Bob, Age: 22
Name: Charlie, Age: 19
Summary:
Type Structure Example
Single-Dimensional Linear list of elements {10, 20, 30}
Array
Multi-Dimensional Matrix-like structure (rows and {{1, 2}, {3, 4}}
Array columns)
Jagged Array Arrays of varying lengths {{1, 2}, {3, 4, 5}, {6}}
Array of Objects Array storing custom objects new Student[] {Student1,
Student2, ...}
14. Write a program to illustrate break statement with labels 7
An public class BreakWithLabelExample {
s public static void main(String[] args) {
outerLoop:
for (int i = 1; i <= 5; i++) {
System.out.println("Outer Loop, Iteration " + i);
for (int j = 1; j <= 5; j++) {
System.out.println(" Inner Loop, Iteration " + j);
if (i == 3 && j == 3) {
System.out.println(" Breaking out of the outer
loop at i = " + i + ", j = " + j);
break outerLoop;
}
}
}
System.out.println("Exited the loops.");
}
}
15. Describe the meaning of each of the keyword in “public static void main” and write an example 7
program.
An The phrase public static void main in Java is part of the method signature for the entry point of a Java
s application. Let's break down the meaning of each keyword:
1. public
Visibility Modifier: The public keyword is an access modifier that specifies the visibility of
the method. A public method can be accessed from anywhere in the program or even from
other classes or packages. In this case, the main method must be public so that it can be
invoked by the Java Virtual Machine (JVM) to start the application, regardless of where the
call comes from.
2. static
Static Keyword: The static keyword indicates that the method belongs to the class itself, not
to any specific instance of the class. This is crucial because the main method is called before
any object of the class is created. Therefore, it must be static to allow the JVM to call it without
creating an instance of the class.
Page | 21
3. void
Return Type: The void keyword specifies that the main method does not return any value. In
Java, methods that do not return anything use the void keyword to indicate this. The main
method's role is to serve as an entry point to the program, so there is no need for it to return
any value.
4. main
Method Name: The main is the name of the method. In Java, the main method is special
because it is the entry point of the program. When the program is run, the JVM looks for the
main method to begin executing the program.
Example Program:
Here is a simple Java program that demonstrates the public static void main method:
public class HelloWorld {
public static void main(String[] args) {
// Printing a message to the console
System.out.println("Hello, World!");
}
}
Explanation of the Program:
1. public class HelloWorld: Defines a class named HelloWorld.
2. public static void main(String[] args): The main method that serves as the entry point for
the Java program. It is declared as public (so it can be called by the JVM), static (so it can be
called without creating an instance of the class), and void (it does not return any value). The
String[] args part allows command-line arguments to be passed to the program.
3. System.out.println("Hello, World!"): This statement prints "Hello, World!" to the console.
How It Works:
When you run this Java program, the JVM looks for the main method to start execution. It
runs the code inside the method and prints "Hello, World!" to the console.
2. Char to Int
Promotion to int: A char (which is essentially a 16-bit Unicode character) is promoted to an
int when involved in arithmetic operations.
Example:
char c = 'A';
int result = c + 10; // 'A' is promoted to int (65), then 10
is added
System.out.println(result); // Output: 75
Reason: A char is treated as an unsigned integer, so Java promotes it to an int for calculations.
Page | 22
Promotion to a larger type: When you perform operations on smaller primitive types (byte,
short, char, int, float, long, double), Java promotes them to the largest type in the expression.
Rules for promotion:
o byte, short, and char are promoted to int.
o int is promoted to long, float, or double depending on the operation.
o long is promoted to float or double as necessary.
o float is promoted to double.
Example:
byte b = 10;
short s = 20;
int result = b + s; // byte and short are promoted to int
System.out.println(result); // Output: 30
5. Floating-Point Promotions
Promotion to double: Any operation that involves a float and a double promotes the result to
double.
Example:
float f = 10.5f;
double result = f + 20.5; // float is promoted to double
System.out.println(result); // Output: 31.0
17. Demonstrate the working of enhanced for loop with an example program. 7
An public class EnhancedForLoopExample {
s public static void main(String[] args) {
// Declare and initialize an array
int[] numbers = {10, 20, 30, 40, 50};
System.out.println("Using Enhanced For Loop:");
for (int number : numbers) {
System.out.println("Number: " + number); // Access and
print each element
}
String[] fruits = {"Apple", "Banana", "Cherry", "Date"};
System.out.println("\nUsing Enhanced For Loop for
Strings:");
for (String fruit : fruits) {
System.out.println("Fruit: " + fruit); // Access and
print each element
}
}
}
Module 02
Introducing Classes: Class Fundamentals, Declaring Objects, Assigning Object Reference Variables, Introducing
Methods, Constructors, The this Keyword, Garbage Collection.
Methods and Classes: Overloading Methods, Objects as Parameters, Argument Passing, Returning Objects,
Recursion, Access Control, Understanding static, Introducing final, Introducing Nested and Inner Classes.
Page | 24
1. Default Constructor
A default constructor is a constructor that has no parameters. If no constructor is explicitly
defined in a class, Java provides a default constructor implicitly. The default constructor
initializes the object with default values.
Key points about Default Constructor:
It doesn’t take any parameters.
It assigns default values to instance variables (e.g., 0 for integers, null for objects, false
for booleans).
Example of Default Constructor:
class Car {
String model;
int year;
public Car() {
model = "Unknown";
year = 2020;
}
public void display() {
System.out.println("Car Model: " + model);
System.out.println("Car Year: " + year);
}
}
public class Main {
public static void main(String[] args) {
// Creating an object using the default constructor
Car car1 = new Car();
car1.display(); // Displays: Car Model: Unknown, Car
Year: 2020
}
}
Output:
Car Model: Unknown
Car Year: 2020
In this example:
The Car class has a default constructor that initializes the model to "Unknown" and
year to 2020.
When a Car object is created using the default constructor, the values are set as per the
constructor.
2. Parameterized Constructor
A parameterized constructor allows passing arguments to initialize an object with specific
values. This constructor provides more flexibility compared to the default constructor because it
can accept parameters to initialize the object with custom values.
Key points about Parameterized Constructor:
It takes one or more arguments.
It allows initializing instance variables with specific values provided during object
creation.
Example of Parameterized Constructor:
class Car {
String model;
int year;
public Car(String model, int year) {
this.model = model;
this.year = year;
}
Conclusion:
Constructors are fundamental in Java for initializing objects. The default constructor provides
default values, while the parameterized constructor gives you the flexibility to initialize
objects with specific values at the time of object creation. Both types of constructors are
essential for object-oriented programming and provide the foundation for creating objects with
different states.
Page | 26
}
}
public class Main {
public static void main(String[] args) {
Counter obj1 = new Counter();
obj1.displayCount();
Counter obj2 = new Counter();
obj2.displayCount();
Counter obj3 = new Counter();
obj3.displayCount
across all instances
}
}
Explanation:
In the Counter class, the static variable count is incremented whenever a new object is
created.
All instances (obj1, obj2, and obj3) share the same static variable count, so the value of
count increases with each object created.
The static variable count is initialized only once, and its value is shared across all
instances of the class.
2. Static Method
A static method is a method that belongs to the class rather than any specific object. This means
that you can call a static method without creating an instance of the class. Static methods can
access other static variables and static methods directly but cannot access instance variables or
instance methods directly because they are not associated with any object instance.
Key Points:
No Object Required: Static methods are called on the class itself, not on instances of
the class.
Accessing Static Members: Static methods can only directly access static variables and
other static methods in the class. They cannot access instance variables or instance
methods directly.
Can Be Called Without Creating an Object: Since static methods are tied to the class,
you do not need to create an instance of the class to invoke them.
Example of Static Method:
class MathOperations {
static int add(int a, int b) {
return a + b;
}
public Employee() {
this("Unknown"); // Constructor chaining
}
Page | 28
public Employee(String name) {
this.name = name;
}
}
4. Passing current object as a parameter: Passes the current object to another method.
class Person {
String name;
Page | 29
helps in managing memory efficiently without requiring manual memory management like in
languages such as C++.
How Garbage Collection Works:
1. Object Creation and Reference:
o When an object is created, memory is allocated from the heap.
o As long as there are references to the object, it remains in memory.
o When there are no references to an object (i.e., the object is unreachable), the
object becomes eligible for garbage collection.
2. Garbage Collector (GC):
o The garbage collector is a part of the JVM that automatically handles the
deallocation of memory. It frees up memory by collecting and removing
unreachable objects from the heap.
o Unreachable objects are those that no longer have any references pointing to
them.
3. Mark-and-Sweep Algorithm:
o Most Java garbage collectors use the Mark-and-Sweep algorithm to manage
memory:
Mark Phase: The garbage collector traverses the heap, starting from
reachable objects (objects that can be accessed from the root, such as
local variables, active threads, etc.). It marks these objects as reachable.
Sweep Phase: The garbage collector sweeps through the heap and
removes objects that were not marked as reachable (unreachable
objects), thus reclaiming memory.
4. Generational Garbage Collection:
o Java uses Generational Garbage Collection where the heap is divided into
generations (young generation and old generation).
Young Generation: This is where most objects are initially allocated.
Objects in the young generation are typically short-lived and are
collected more frequently.
Old Generation: Objects that survive multiple garbage collection
cycles in the young generation are promoted to the old generation. The
old generation is collected less frequently, as the objects here are long-
lived.
5. Garbage Collector Types:
o Java provides several garbage collection algorithms, including:
Serial Garbage Collector: A simple, single-threaded collector used for
small applications or applications with limited resources.
Parallel Garbage Collector: Uses multiple threads to perform garbage
collection, improving performance for multi-threaded applications.
CMS (Concurrent Mark-Sweep) Garbage Collector: Focuses on
minimizing application pause times by performing most of the work
concurrently with the application threads.
G1 Garbage Collector: The Garbage First (G1) collector is designed
for large heaps and aims to balance low pause times and high
throughput.
Explicit Garbage Collection:
Although garbage collection is automatic in Java, it can be triggered manually by calling:
System.gc();
However, calling System.gc() is generally discouraged because it does not guarantee immediate
garbage collection. It simply suggests to the JVM that garbage collection should be performed.
Memory Management Process in Java
Allocation: When objects are created using new, the memory is allocated in the heap.
Deallocation: When an object is no longer referenced, it becomes eligible for garbage
collection. The JVM identifies these objects and frees up the memory.
Garbage Collection: The garbage collector runs periodically to reclaim memory
occupied by objects that are no longer needed. It may introduce pauses in the program
(called GC pause) to perform memory cleanup.
Advantages of Garbage Collection in Java:
Page | 30
1. Automatic Memory Management: Developers do not need to manually allocate or free
memory, reducing the chances of memory leaks and errors.
2. Simplifies Code: Without worrying about explicit memory management, developers can
focus more on logic and functionality.
3. Efficiency: The JVM uses efficient garbage collection techniques (e.g., generational
GC) to minimize the impact on performance.
Example of Garbage Collection:
class GarbageCollectorExample {
public static void main(String[] args) {
GarbageCollectorExample obj1 = new
GarbageCollectorExample();
GarbageCollectorExample obj2 = new
GarbageCollectorExample();
obj1 = null;
System.gc();
System.out.println("Garbage collection invoked!");
}
}
Explanation:
obj1 = null;: The object previously referenced by obj1 is now unreachable. It becomes
eligible for garbage collection.
System.gc();: This is a request to the JVM to run garbage collection, although the actual
collection process is not guaranteed to happen immediately.
In conclusion, Java’s garbage collection mechanism helps manage memory efficiently by
automatically reclaiming unused objects, reducing the risk of memory leaks and allowing
developers to focus more on application logic.
05. Write a program to perform Stack operation using proper class and Methods. 7
Ans import java.util.Scanner;
public class Stack {
private static final int MAX_SIZE = 10;
private int[] stackArray;
private int top;
public Stack() {
stackArray = new int[MAX_SIZE];
top = -1;
}
public void push(int value) {
if (top < MAX_SIZE - 1) {
stackArray[++top] = value;
System.out.println("Pushed: " + value);
} else {
System.out.println("Stack Overflow! Cannot push " +
value + ".");
}
}
public int pop() {
if (top >= 0) {
int poppedValue = stackArray[top--];
System.out.println("Popped: " + poppedValue);
return poppedValue;
} else {
System.out.println("Stack Underflow! Cannot pop
from an empty
stack.");
return -1; // Return a default value for
simplicity
}
}
Page | 31
public int peek() {
if (top >= 0) {
System.out.println("Peeked: " + stackArray[top]);
return stackArray[top];
} else {
System.out.println("Stack is empty. Cannot peek.");
return -1; // Return a default value for simplicity
}
}
public void display() {
if (top >= 0) {
System.out.print("Stack Contents: ");
for (int i = 0; i <= top; i++) {
System.out.print(stackArray[i] + " ");
}
System.out.println();
} else {
System.out.println("Stack is empty.");
}
}
public boolean isEmpty() {
return top == -1;
}
public boolean isFull() {
return top == MAX_SIZE - 1;
}
public static void main(String[] args) {
Stack stack = new Stack();
Scanner scanner = new Scanner(System.in);
int choice;
do {
System.out.println("\nStack Menu:");
System.out.println("1. Push");
System.out.println("2. Pop");
System.out.println("3. Peek");
System.out.println("4. Display Stack Contents");
System.out.println("5. Check if the stack is empty");
System.out.println("6. Check if the stack is full");
System.out.println("0. Exit");
System.out.print("Enter your choice: ");
choice = scanner.nextInt();
switch (choice) {
case 1:
System.out.print("Enter the value to push:
");
int valueToPush = scanner.nextInt();
stack.push(valueToPush);
break;
case 2:
stack.pop();
break;
case 3:
stack.peek();
break;
case 4:
stack.display();
break;
case 5:
Page | 32
System.out.println("Is the stack empty? "
+ stack.isEmpty());
break;
case 6:
System.out.println("Is the stack full? " +
stack.isFull());
break;
case 0:
System.out.println("Exiting the program.
Goodbye!");
break;
default:
System.out.println("Invalid choice. Please
try again.");
}
} while (choice != 0);
scanner.close();
}
06. Write a JAVA program demonstrating Method overloading. 7
Ans class Calculator {
public int add(int a, int b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
public double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("Sum of 10 and 20 (int): " +
calc.add(10, 20));
System.out.println("Sum of 10, 20 and 30 (int): " +
calc.add(10, 20, 30));
System.out.println("Sum of 10.5 and 20.5 (double): " +
calc.add(10.5, 20.5));
}
}
07. Explain call by value and call by reference with example program. 8
Ans In Java, method arguments can be passed in two different ways: Call by Value and Call by
Reference.
1. Call by Value:
In Call by Value, when a method is called, the value of the actual parameter is passed to the
method. The method operates on a copy of the argument, meaning that changes made to the
parameter inside the method do not affect the original variable outside the method.
Example of Call by Value:
class CallByValueExample {
public static void modifyValue(int a) {
a = 20;
System.out.println("Inside method: " + a);
}
Page | 33
modifyValue(num);
System.out.println("After method call: " + num);
}
}
Explanation:
Before method call: The variable num is initialized to 10.
The method modifyValue(int a) receives a copy of the value of num (which is 10). Inside
the method, the local variable a is changed to 20, but the original variable num outside
the method remains unchanged.
After method call: The original value of num remains 10 because the method worked
on a copy of the value, not the actual variable.
Output:
Before method call: 10
Inside method: 20
After method call: 10
2. Call by Reference:
In Call by Reference, the reference (or memory address) of the actual parameter is passed to
the method. This means that the method operates directly on the actual parameter, and any
changes made inside the method affect the original variable outside the method.
However, Java does not support Call by Reference directly for primitive data types. In Java,
only objects (non-primitive types) are passed by reference.
Example of Call by Reference (using objects):
class Person {
String name;
Person(String name) {
this.name = name;
}
}
class CallByReferenceExample {
public static void changeName(Person p) {
p.name = "John";
}
public static void main(String[] args) {
Person person = new Person("Alice");
System.out.println("Before method call: " +person.name);
changeName(person);
System.out.println("After method call: " +person.name);"
}
}
Explanation:
Before method call: The object person has the name "Alice".
The changeName() method receives the reference to the person object, which means it
has access to the original person object in memory.
Inside the method, we change the name property of the person object.
After method call: The name is changed to "John" because the method operated on the
original object via reference.
Output:
Before method call: Alice
After method call: John
Page | 34
Applicable to Primitive types (e.g., int, float, char, Objects (non-primitive types,
etc.). e.g., String, Array, Custom
Objects).
Example Modifying a primitive type inside a Modifying the properties of an
method. object inside a method.
In Java:
Primitive types (like int, float, char, etc.) are always passed by value.
Objects are passed by reference. However, this doesn't mean that you can change the
reference itself to point to a new object. It only means that the method can modify the
internal state (fields) of the object.
Conclusion:
Call by Value in Java works by passing a copy of the variable (for primitive types), and
changes to the copy do not affect the original variable.
Call by Reference is how objects are passed in Java, where the method works on the
reference to the object, allowing changes to the object's internal state, but not the
reference itself.
1. Inner Class
An inner class is a non-static class defined inside another class. It can access the instance
variables and methods of the outer class, even those that are private. Inner classes are associated
with an instance of the outer class, meaning they are created only when an object of the outer
class is created.
Types of Inner Classes:
Member Inner Class: Defined inside the body of a class.
Local Inner Class: Defined within a method of the outer class.
Anonymous Inner Class: A class without a name, defined at the point of use.
Example of Inner Class (Member Inner Class):
class OuterClass {
private String outerField = "Outer Class Field";
class InnerClass {
void display() {
System.out.println("Accessing from Inner Class: " +
outerField);
}
}
void createInnerClass() {
InnerClass inner = new InnerClass();
inner.display();
}
}
public class Main {
public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.createInnerClass();
}
}
Output:
Accessing from Inner Class: Outer Class Field
Explanation:
InnerClass is defined inside OuterClass and has access to the outerField variable of the
outer class.
Page | 35
The inner class is instantiated and used inside the createInnerClass() method of the outer
class.
Page | 36
localInner.show();
}
}
greeting.greet();
}
}
Output:
Hello from Anonymous Inner Class!
Explanation:
The anonymous inner class implements the Greeting interface and defines the greet()
method inline without a separate class definition.
Conclusion
Nested classes in Java include inner classes and static nested classes.
Inner classes can access both static and instance members of the outer class.
Static nested classes only access static members of the outer class and do not require an
instance of the outer class to be created.
Local inner classes are defined within methods and can access local variables.
Anonymous inner classes are unnamed and used for one-time use, typically for
implementing interfaces or extending classes.
Nested and inner classes provide powerful ways to organize and structure your code for better
readability and maintainability.
Page | 37
Feature Method Overloading Method Overriding
Definition Multiple methods with the same A subclass provides its own
name but different parameter implementation of a method that is
lists in the same class or subclass. already defined in the superclass.
Method Signature Same method name but different Same method name, same
parameter list (either in number parameter list, and same return
or type). type as in the superclass.
Return Type Can be different for overloaded Must be the same or a subtype of
methods. the return type in the superclass.
Polymorphism Compile-time polymorphism Runtime polymorphism (also
Type (also known as static known as dynamic
polymorphism). polymorphism).
Inheritance Does not require inheritance. Requires inheritance. A subclass
Methods can be overloaded overrides a method from the
within the same class or subclass. superclass.
Purpose Allows multiple methods with the Allows a subclass to provide a
same name but different specific implementation of a
parameter lists. method already defined in the
superclass.
Resolution Resolved at compile-time based Resolved at runtime based on the
on the method signature. actual object type.
Scope Works within the same class or Involves a subclass overriding a
subclass. method in the superclass.
Example add(int a, int b), add(double a, sound() in Animal and Dog where
double b) Dog overrides Animal's sound()
method.
Method Signature Differentiated by the number or Differentiated by the class
Differentiation types of parameters. hierarchy (parent vs. child).
10. How do you overload a constructor? Explain with a program. 8
Ans Constructor Overloading in Java
Constructor Overloading in Java is similar to method overloading, where multiple constructors
with the same name (constructor name is always the same as the class name) are defined, but
they have different parameter lists. This allows the creation of objects in different ways based on
the number or type of arguments passed.
Rules for Constructor Overloading:
1. Constructors must have the same name as the class.
2. Constructors must differ in the number or type of parameters.
3. Constructor overloading does not depend on the return type.
Program
class Book {
String title;
String author;
double price;
public Book(String title) {
this.title = title;
this.author = "Unknown";
this.price = 0.0;
}
public Book(String title, String author) {
this.title = title;
this.author = author;
this.price = 0.0;
}
public Book(String title, String author, double price) {
this.title = title;
this.author = author;
this.price = price;
Page | 38
}
public void displayDetails() {
System.out.println("Title: " + title);
System.out.println("Author: " + author);
System.out.println("Price: " + price);
}
}
public class Main {
public static void main(String[] args) {
// Creating objects using different constructors
Book book1 = new Book("Java Programming");
Book book2 = new Book("Data Structures", "John Doe");
Book book3 = new Book("Advanced Java", "Jane Smith",
499.99);
System.out.println("Book 1 Details:");
book1.displayDetails();
System.out.println();
System.out.println("Book 2 Details:");
book2.displayDetails();
System.out.println();
System.out.println("Book 3 Details:");
book3.displayDetails();
}
}
11. Define recursion. Write a recursive program to find nth Fibonacci number. 8
Ans Recursion in Java
Recursion is a process in which a method calls itself directly or indirectly to solve a problem.
The key idea behind recursion is breaking down a problem into smaller sub-problems of the
same type. Every recursive function must have a base case to prevent infinite recursion.
Fibonacci Sequence
The Fibonacci sequence is a series of numbers where each number is the sum of the two
preceding ones. The sequence starts with 0 and 1, and the next numbers in the sequence are
obtained by adding the previous two.
Fibonacci sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
The nth Fibonacci number can be defined recursively as:
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) for n > 1
Page | 39
o Base Case: If n is 0 or 1, the method returns n (F(0) = 0, F(1) = 1).
o Recursive Case: If n > 1, the method calls itself with n-1 and n-2, and adds the
results. This continues until the base case is reached.
In the main() method, we call fibonacci(6) to find the 6th Fibonacci number. The
recursion unfolds as:
o fibonacci(6) calls fibonacci(5) and fibonacci(4)
o fibonacci(5) calls fibonacci(4) and fibonacci(3)
o And so on, until the base cases are reached (fibonacci(0) and fibonacci(1)).
Time Complexity of Recursive Fibonacci:
The recursive approach has exponential time complexity, i.e., O(2^n), due to
overlapping subproblems (recalculating the same Fibonacci numbers multiple times).
This can be improved with memoization or dynamic programming.
12. What are various access specifiers in Java? List out the behaviour of each of them. 7
Ans In Java, access specifiers (also called access modifiers) define the visibility and accessibility of
classes, methods, constructors, and variables. They determine how and from where a particular
class member (method, field, etc.) can be accessed.
There are four primary access specifiers in Java:
1. public Access Specifier:
Visibility: The public access specifier makes a class, method, or field accessible from
any other class in any package.
Scope: It is the least restrictive access level.
Usage: Use public when you want the members of a class to be accessible to all other
classes, even outside of the package.
Behavior:
Class: If a class is declared public, it can be accessed from anywhere, including classes
from other packages.
Method: A public method can be called from any other class.
Field: A public field can be accessed from any other class.
Example:
public class Example {
public int num; // Public field
Page | 40
}
Summary Table:
Access Visibility Scope Usage
Specifier
public Accessible from any other Least restrictive Use when you want the
class, even outside the member to be accessible
package globally.
protected Accessible within the More restrictive than Use when you want to
same package and public, but allows allow access within the
subclasses (even in subclass access package and by
different packages) subclasses.
private Accessible only within Most restrictive Use when you want to
the same class hide data and limit
access to the class.
Page | 41
Default Accessible only within More restrictive than Use when you want the
(package- the same package protected, but allows member to be accessed
private) package access only within the package.
Best Practices:
Use private for encapsulating data within a class.
Use protected when you want to allow subclasses to access certain members.
Use public for methods or fields that need to be accessed globally.
Use default access for classes and methods that should only be accessed within the same
package.
13. Examine Java Garbage collection mechanism by classifying the 3 generations of Java heap. 6
Ans Java Garbage Collection Mechanism:
In Java, Garbage Collection (GC) is the process of automatically reclaiming memory by
destroying unreachable objects, thereby preventing memory leaks. The Java Virtual Machine
(JVM) manages this process to ensure that the program runs efficiently by handling memory
deallocation.
Java's memory management is organized into different generations, which help optimize the
garbage collection process. The heap memory is divided into three generations:
1. Young Generation
2. Old Generation
3. Permanent Generation (in older JVM versions) / Metaspace (in newer JVM versions)
Each generation has its own garbage collection strategy based on the lifetime and age of
objects.
1. Young Generation:
The Young Generation is where new objects are created. Since most objects in a program are
short-lived, this generation is designed to efficiently handle object creation and removal. It is
divided into three parts:
Eden Space:
o This is where new objects are initially allocated.
o Most objects are created here and quickly discarded when they are no longer
needed.
Survivor Space (S0 and S1):
o After an object survives its first garbage collection cycle in Eden, it is moved to
one of the Survivor Spaces (S0 or S1).
o Objects are moved between these two spaces in alternating collections.
o The Survivor Spaces are used to hold objects that are "young" but have survived
at least one garbage collection.
Garbage Collection in Young Generation:
Minor GC: The garbage collection process in the Young Generation is called Minor
GC. It typically happens when the Eden space is full. Minor GCs are quick and collect
only the Young Generation.
Objects that survive Minor GC are promoted to the Old Generation, while the rest are
discarded.
Typical Characteristics:
Short-lived objects (like temporary variables or method-local objects) are allocated
here.
The garbage collection is frequent in this region, as many objects are short-lived and
become unreachable quickly.
Page | 43
Permanent JVM metadata (class Full GC Rare (when Class metadata,
Generation / definitions, method metadata is method data
Metaspace definitions) removed)
Conclusion:
The Java Garbage Collection mechanism relies on dividing the heap into three generations to
optimize memory management. By having separate strategies for young and old objects, the
JVM can efficiently manage memory, performing quick collections for short-lived objects in the
Young Generation and more costly collections for long-lived objects in the Old Generation. The
Metaspace (or Permanent Generation in older versions) is responsible for managing class
metadata outside of the heap.
14. Develop a Java program to find area of rectangle, area of circle and area of triangle using 10
method overloading concept. Call these methods from main method with suitable inputs
Ans public class AreaCalculator {
public double calculateArea(double length, double width) {
return length * width;
}
public double calculateArea(double radius) {
return Math.PI * radius * radius;
}
public double calculateArea(double base, double height) {
return 0.5 * base * height;
}
public static void main(String[] args) {
AreaCalculator calculator = new AreaCalculator();
double rectangleArea =calculator.calculateArea(5.0,3.0);
System.out.println("Area of Rectangle:" +rectangleArea);
double circleArea = calculator.calculateArea(7.0);
System.out.println("Area of Circle: " + circleArea);
double triangleArea = calculator.calculateArea(6.0,4.0);
System.out.println("Area of Triangle: " + triangleArea);
}
}
15. Interpret the general form of a class with example. 4
Ans General Form of a Class in Java
A Java class is a blueprint for creating objects, containing fields (instance variables), methods,
and constructors.
General Structure:
public class ClassName {
// Instance variables (fields)
private String name;
private int age;
// Constructor
public ClassName(String name, int age) {
this.name = name;
this.age = age;
}
// Instance method
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
// Static method
public static void staticMethod() {
System.out.println("Static method");
Page | 44
}
Page | 46
String designation;
int empid;
double basicSalary;
public void read() {
Scanner sc = new Scanner(System.in);
System.out.print("Enter employee name: ");
name = sc.nextLine();
System.out.print("Enter employee designation: ");
designation = sc.nextLine();
System.out.print("Enter employee ID: ");
empid = sc.nextInt();
System.out.print("Enter employee basic salary: ");
basicSalary = sc.nextDouble();
}
public void write() {
System.out.println("\nEmployee Information:");
System.out.println("Name: " + name);
System.out.println("Designation: " + designation);
System.out.println("Employee ID: " + empid);
System.out.println("Basic Salary: " + basicSalary);
}
}
public class Main {
public static void main(String[] args) {
Employee[] employees = new Employee[5];
for (int i = 0; i < 5; i++) {
employees[i] = new Employee();
System.out.println("\nEnter details for Employee " +
(i + 1) + ":");
employees[i].read();
}
System.out.println("\nEmployee Information Entered:");
for (int i = 0; i < 5; i++) {
employees[i].write(); // Write employee data
}
}
}
18. Interpret with an example, types of constructions. 4
Ans In Java, constructors are special methods used to initialize objects when they are created.
Constructors are called automatically when an object is instantiated using the new keyword.
There are primarily two types of constructors in Java:
1. Default Constructor
2. Parameterized Constructor
1. Default Constructor
A default constructor is a constructor that is provided by the Java compiler when no explicit
constructor is defined. It has no parameters and initializes the object with default values.
For instance variables: The default constructor initializes instance variables to their
default values (e.g., 0 for numeric types, null for objects, false for boolean).
Example of Default Constructor:
class Student {
String name;
int age;
public Student() {
name = "Unknown";
age = 18;
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
Page | 47
}
}
public class Main {
public static void main(String[] args) {
// Creating object using default constructor
Student student = new Student();
student.display();
}
}
Output:
Name: Unknown
Age: 18
Explanation:
The default constructor initializes the name to "Unknown" and age to 18.
Since no other constructor was defined, the Java compiler automatically provides a
default constructor.
2. Parameterized Constructor
A parameterized constructor is one that accepts parameters to initialize an object with specific
values during instantiation. You can define a parameterized constructor to initialize instance
variables with custom values.
Example of Parameterized Constructor:
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name; // Assigning parameter value to
instance variable
this.age = age;
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
public class Main {
public static void main(String[] args) {
Student student1 = new Student("Alice", 20);
Student student2 = new Student("Bob", 22);
student1.display();
student2.display();
}
}
Output:
Name: Alice
Age: 20
Name: Bob
Age: 22
Explanation:
The parameterized constructor accepts two parameters, name and age, and assigns them
to the instance variables.
When creating the student1 and student2 objects, specific values are passed to the
constructor to initialize the objects with those values.
Page | 48
Initialization Initializes instance variables with Initializes instance variables with
default values (e.g., 0, null). values passed to the constructor.
Automatic or Automatically provided by the Must be explicitly defined by the
Explicit compiler if no constructor is programmer.
defined.
Usage Useful for basic initialization or Useful when you want to initialize
when you want default values. an object with custom values.
Constructor Overloading
Java allows constructor overloading, meaning that you can define multiple constructors with
the same name but different parameter lists. This enables creating objects with different sets of
initialization values.
Example of Constructor Overloading:
class Student {
String name;
int age;
public Student() {
name = "Unknown";
age = 18;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public void display() {
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}
public class Main {
public static void main(String[] args) {
// Creating object using default constructor
Student student1 = new Student();
student1.display();
Conclusion:
Default constructors are automatically provided by the compiler when no other
constructors are defined, and they initialize the object with default values.
Parameterized constructors allow you to initialize the object with custom values at the
time of creation.
Constructor overloading allows you to define multiple constructors with different
parameter lists for flexible object initialization.
Module 03
Page | 49
Inheritance: Inheritance Basics, using super, Creating a Multilevel Hierarchy, When Constructors Are Executed,
Method Overriding, Dynamic Method Dispatch, Using Abstract Classes, Using final with Inheritance, Local
Variable Type Inference and Inheritance, The Object Class.
Interfaces: Interfaces, Default Interface Methods, Use static Methods in an Interface, Private Interface Methods.
03. Write a java program to implement multilevel inheritance with 3 levels of hierarchy. 8
Ans In Java, multiple inheritance (the ability for a class to inherit from more than one class) is not
allowed with classes due to the potential for ambiguity. However, interfaces provide a way to
achieve multiple inheritance because a class can implement multiple interfaces. This allows a
class to inherit abstract behavior (method signatures) from more than one interface without the
complications of class inheritance.
How Interfaces Achieve Multiple Inheritance in Java:
1. Interfaces define a contract: An interface in Java defines a set of methods that a class
must implement, but it does not provide the implementation itself.
2. A class can implement multiple interfaces: Unlike classes, a class in Java can
implement multiple interfaces, thereby inheriting abstract methods from all the
interfaces. This allows a class to have behavior from multiple sources, which is akin to
multiple inheritance.
Example: Achieving Multiple Inheritance Using Interfaces
interface Animal {
void eat();
}
interface Bird {
void fly();
}
class Eagle implements Animal, Bird {
public void eat() {
System.out.println("Eagle is eating.");
}
public void fly() {
System.out.println("Eagle is flying.");
}
}
Page | 54
With default methods introduced in Java 8, interfaces can also provide default
implementations, making the feature even more powerful.
This approach allows for clean and maintainable designs while avoiding the ambiguity and
complexity issues associated with multiple inheritance in classes.
Let me know if you'd like more examples or explanations!
06. What is meant by interface? State its need and write syntax and features of interface. 7
Ans Interface in Java
An interface in Java is a reference type, similar to a class, that can contain only constants,
method signatures, default methods, static methods, and nested types. An interface cannot
contain instance fields or constructors. Interfaces are used to represent a contract for what a
class can do, without specifying how it does it.
Need for Interface:
1. Multiple Inheritance: Java does not support multiple inheritance (i.e., a class cannot
extend more than one class), but interfaces allow multiple inheritance. A class can
implement multiple interfaces.
2. Decoupling: Interfaces help in achieving loose coupling between classes by defining a
contract for interaction without revealing the implementation details.
3. Polymorphism: Interfaces help achieve polymorphism by allowing objects to be
referenced through interfaces, promoting code reusability.
Syntax of Interface:
interface InterfaceName {
int CONSTANT = 100;
void method1();
void method2();
default void defaultMethod() {
System.out.println("This is a default method.");
}
static void staticMethod() {
System.out.println("This is a static method.");
}
}
Features of Interface:
1. Abstract Methods: Methods declared in an interface are abstract by default (i.e., they
do not have a body).
2. Constants: All variables in an interface are implicitly public, static, and final.
3. Default Methods: Since Java 8, interfaces can have default methods with a body.
Page | 56
4. Static Methods: Interfaces can also have static methods.
5. Multiple Inheritance: A class can implement multiple interfaces, overcoming Java's
restriction on multiple class inheritance.
6. Implementation: A class implements an interface using the implements keyword.
Example of Interface:
interface Animal {
void sound();
default void sleep() {
System.out.println("The animal is sleeping.");
}
static void breathe() {
System.out.println("The animal is breathing.");
}
}
class Dog implements Animal {
public void sound() {
System.out.println("The dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound();
dog.sleep();
Animal.breathe();
}
}
Output:
The dog barks.
The animal is sleeping.
The animal is breathing.
Explanation:
1. Interface Definition: The Animal interface defines an abstract method sound(), a
default method sleep(), and a static method breathe().
2. Implementation: The Dog class implements the Animal interface, providing its own
implementation of the sound() method.
3. Usage: In the Main class, we create a Dog object and call the sound(), sleep(), and
static method breathe() (which is accessed through the interface).
Key Points:
Interfaces can only contain method signatures and constants (except default and static
methods introduced in Java 8).
A class that implements an interface must provide concrete implementations for all
abstract methods in the interface.
Polymorphism in Java
Polymorphism is the ability of an object to take many forms. It allows a single interface or
method to represent different types of objects. Java supports two types of polymorphism:
1. Compile-time Polymorphism (Static Polymorphism): Achieved through method
overloading and operator overloading.
2. Runtime Polymorphism (Dynamic Polymorphism): Achieved through method
overriding, where the method to be invoked is determined at runtime.
Types of Polymorphism:
1. Method Overloading (Compile-time Polymorphism):
o Same method name but with different parameters (number/type of parameters).
2. Method Overriding (Runtime Polymorphism):
o A subclass provides a specific implementation of a method that is already
defined in its superclass.
Example of Compile-time Polymorphism (Method Overloading):
class Calculator {
public int add(int a, int b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3));
System.out.println(calc.add(1, 2, 3));
}
}
Output:
5
6
Example of Runtime Polymorphism (Method Overriding):
class Animal {
public void sound() {
System.out.println("Animal makes a sound");
}
Page | 58
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
myAnimal.sound();
Dog myDog = new Dog();
myDog.sound();
// Demonstrating polymorphism
Animal myAnimalRef = new Dog();
myAnimalRef.sound();
}
}
Output:
Animal makes a sound
Dog barks
Dog barks
Explanation:
Method Overloading: The add() method is overloaded with different parameter lists.
Method Overriding: The sound() method in the Dog class overrides the method in the
Animal class. When the reference type is Animal but the actual object is of type Dog,
the Dog class's sound() method is called, demonstrating runtime polymorphism.
Page | 59
Example of Method Overriding:
class Animal {
public void sound() {
System.out.println("Animals make sounds");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
public void sound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.sound();
Animal dog = new Dog();
dog.sound();
Animal cat = new Cat();
cat.sound();
}
}
Explanation:
1. Superclass (Animal):
o The class Animal has a method sound(), which is a general method that
describes the sound of animals.
2. Subclass (Dog and Cat):
o The class Dog and Cat both extend the Animal class and override the sound()
method to provide their specific implementations. The Dog class prints "Dog
barks", and the Cat class prints "Cat meows".
3. Method Overriding:
o In both the Dog and Cat classes, the sound() method has the same name, return
type (void), and parameter list (no parameters) as the method in the Animal
class, but with different implementations.
4. Runtime Polymorphism (Dynamic Method Dispatch):
o In the main method, objects of Dog and Cat are created, but they are
referenced by the Animal class type (Animal dog = new Dog();).
o When the sound() method is called on these references, the version of the
method that gets executed is determined at runtime. Even though the reference
type is Animal, the method in the respective subclass (Dog or Cat) is invoked.
Output:
Animals make sounds
Dog barks
Cat meows
Advantages of Method Overriding:
1. Runtime Polymorphism: It allows different classes to implement the same method in
a way that is specific to their own class.
2. Flexibility and Extensibility: The ability to override methods gives subclasses the
flexibility to change or extend the behavior of the inherited methods.
09. What is importance of super keyword in inheritance? Illustrate with suitable example. 7
Page | 60
Ans Importance of the super Keyword in Inheritance
In Java, the super keyword is used to refer to the immediate parent class object. It plays a vital
role in inheritance and is mainly used in the following scenarios:
1. Accessing Parent Class Methods: When a method is overridden in the child class, the
super keyword can be used to access the method of the parent class.
2. Accessing Parent Class Constructor: The super keyword can be used to invoke the
parent class constructor from the child class.
3. Accessing Parent Class Variables: If a variable in the parent class is hidden by a
variable with the same name in the child class, the super keyword can be used to refer
to the parent class variable.
Key Uses of super:
1. To call the parent class constructor.
2. To call the parent class method.
3. To refer to parent class fields.
Explanation:
1. Calling Parent Constructor: The Dog class constructor calls the parent class
(Animal) constructor using super(name). This ensures the name variable in the parent
class is initialized properly.
2. Accessing Parent Class Method: In the sound() method of Dog, the super.sound() is
used to invoke the method in the Animal class, which is then followed by the child
class's own implementation of sound().
3. Accessing Parent Class Variable: The name variable in the parent class is accessed
directly, as it's inherited by the child class. If there was a hidden field in the child class
with the same name, super.name could be used to access the parent class's name.
Summary:
Page | 61
The super keyword is essential in inheritance for accessing parent class constructors,
methods, and variables, especially when there's a need to differentiate between parent
and child class members.
12. What is abstract class and abstract method? Explain with example. 7
Ans Abstract Class
An abstract class in Java is a class that cannot be instantiated on its own (i.e., you cannot
create an object of an abstract class directly). It serves as a blueprint for other classes. An
abstract class can contain both abstract methods (methods without implementation) and
concrete methods (methods with implementation). The main purpose of an abstract class is to
provide a common base with common functionality, while allowing subclasses to implement or
override specific behavior.
Abstract Method
An abstract method is a method declared in an abstract class (or an interface) that does not
have a body or implementation. It only has a method signature (method name, return type, and
parameters). Abstract methods must be implemented by subclasses of the abstract class.
Key Points:
An abstract class can have abstract methods and concrete methods.
If a class has one or more abstract methods, it must be declared as abstract.
Abstract methods must be implemented by the subclasses unless the subclass is also
abstract.
Example of Abstract Class and Abstract Method:
abstract class Animal {
public void eat() {
System.out.println("This animal eats food.");
}
public abstract void sound();
}
class Dog extends Animal {
public void sound() {
System.out.println("The dog barks.");
}
}
class Main {
public static void main(String[] args) {
Animal animal = new Animal();
Animal myDog = new Dog();
myDog.eat();
myDog.sound();
}
}
Explanation:
Page | 63
1. Abstract Class (Animal):
o Contains a concrete method eat() that provides a default implementation.
o Contains an abstract method sound() with no implementation.
2. Subclass (Dog):
o The Dog class extends Animal and provides an implementation for the abstract
method sound().
3. Main:
o You cannot create an object of the Animal class directly because it is abstract.
o Instead, we create an object of the Dog class and assign it to a variable of type
Animal. This allows us to call both the concrete eat() method and the
overridden sound() method of the Dog class.
Output:
This animal eats food.
The dog barks.
Why Use Abstract Classes and Methods?
Code Reusability: Abstract classes allow you to provide a common base
implementation, which can be reused and extended by subclasses.
Polymorphism: They enable polymorphic behavior, where a subclass can have its own
implementation of abstract methods, while still maintaining a common interface with
the abstract class.
Enforcing a Contract: Abstract methods enforce that subclasses must implement
certain methods, providing consistency and structure in your code.
13. Illustrate the usage of super keyword in Java with suitable example. Also explain the 10
dynamic method dispatch
Ans Usage of super Keyword in Java
The super keyword in Java is used to refer to the immediate parent class (superclass) of a class.
It can be used for the following purposes:
1. Accessing superclass methods
2. Accessing superclass constructors
3. Accessing superclass fields (when there is no ambiguity)
Example illustrating super Keyword:
class Animal {
String sound = "Animal makes sound";
Animal() {
System.out.println("Animal class constructor called");
}
public void makeSound() {
System.out.println("Animals make sounds");
}
}
class Dog extends Animal {
String sound = "Dog barks";
Dog() {
super();
System.out.println("Dog class constructor called");
}
@Override
public void makeSound() {
super.makeSound();
System.out.println("Dog barks loudly");
}
public void displaySound() {
System.out.println("Superclass sound: " + super.sound);
System.out.println("Subclass sound: " + this.sound);
}
}
public class SuperKeywordExample {
public static void main(String[] args) {
Page | 64
Dog dog = new Dog();
dog.makeSound();
dog.displaySound();
}
}
Explanation:
1. Accessing Superclass Method (super.makeSound()): In the makeSound() method of
the Dog class, super.makeSound() calls the makeSound() method from the Animal
class before executing the subclass method.
2. Calling Superclass Constructor (super()): The constructor of the Dog class calls the
constructor of the Animal class using super(). This is required if the parent class does
not have a no-argument constructor.
3. Accessing Superclass Field (super.sound): The super.sound is used in the
displaySound() method to print the sound field from the Animal class.
Output:
Animal class constructor called
Dog class constructor called
Animals make sounds
Dog barks loudly
Superclass sound: Animal makes sound
Subclass sound: Dog barks
Dynamic Method Dispatch:
Dynamic method dispatch is a mechanism in Java where a call to an overridden method is
resolved at runtime rather than compile time. This occurs when a subclass provides its own
version of a method that is already defined in the superclass.
In Java, method calls are resolved at runtime based on the object type, not the reference type.
This is why the actual method invoked is determined at runtime (dynamic method dispatch).
Example of Dynamic Method Dispatch:
class Animal {
public void makeSound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Cat meows");
}
}
public class DynamicMethodDispatchExample {
public static void main(String[] args) {
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.makeSound();
myCat.makeSound();
}
}
Explanation of Dynamic Method Dispatch:
Even though both myDog and myCat are of type Animal, the actual method that gets
called is determined by the object type at runtime, not the reference type.
At runtime, when myDog.makeSound() is called, the makeSound() method in the Dog
class is invoked, and similarly, when myCat.makeSound() is called, the makeSound()
method in the Cat class is invoked.
Page | 65
Output:
Dog barks
Cat meows
Conclusion:
super Keyword: Helps in accessing superclass methods, constructors, and fields.
Dynamic Method Dispatch: Allows Java to determine which overridden method to
call at runtime, providing runtime polymorphism.
14. Develop a JAVA program to create an interface Resizable with methods resizeWidth(int 10
width) and resizeHeight(int height) that allow an object to be resized. Create a class
Rectangle that implements the Resizable interface and implements the resize methods
Ans interface Resizable {
void resizeWidth(int width);
void resizeHeight(int height);
}
class Rectangle implements Resizable {
private int width;
private int height;
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
@Override
public void resizeWidth(int width) {
this.width = width;
System.out.println("Resized width to: " + width);
}
@Override
public void resizeHeight(int height) {
this.height = height;
System.out.println("Resized height to: " + height);
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void displayInfo() {
System.out.println("Rectangle: Width = " + width +
", Height = " + height);
}
}
public class ResizeDemo {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle(10, 5);
System.out.println("Original Rectangle Info:");
rectangle.displayInfo();
rectangle.resizeWidth(15);
rectangle.resizeHeight(8);
System.out.println("\nUpdated Rectangle Info:");
rectangle.displayInfo();
}
}
15. Develop a JAVA program to create an abstract class Shape with abstract methods 8
calculateArea() and calculatePerimeter(). Create subclasses Circle and Triangle that
extend the Shape class and implement the respective methods to calculate the area and
perimeter of each shape.
Ans abstract class Shape {
Page | 66
abstract double calculateArea();
abstract double calculatePerimeter();
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double calculateArea() {
return Math.PI * radius * radius;
}
@Override
double calculatePerimeter() {
return 2 * Math.PI * radius;
}
}
class Triangle extends Shape {
private double side1;
private double side2;
private double side3;
public Triangle(double side1, double side2, double side3)
{
this.side1 = side1;
this.side2 = side2;
this.side3 = side3;
}
@Override
double calculateArea() {
double s = (side1 + side2 + side3) / 2;
return Math.sqrt(s * (s - side1) * (s - side2) * (s
- side3));
}
@Override
double calculatePerimeter() {
return side1 + side2 + side3;
}
}
public class ShapeDemo {
public static void main(String[] args) {
Circle circle = new Circle(5.0);
Triangle triangle = new Triangle(3.0, 4.0, 5.0);
System.out.println("Circle Area: " +
circle.calculateArea());
System.out.println("Circle Perimeter: " +
circle.calculatePerimeter());
System.out.println("\nTriangle Area: " +
triangle.calculateArea());
System.out.println("Triangle Perimeter: " +
triangle.calculatePerimeter());
}
}
16. Define inheritance and list the different types of inheritance in Java 4
Ans Inheritance in Java
Inheritance is a mechanism in object-oriented programming (OOP) that allows a new class
(child class or subclass) to inherit the properties (fields) and behaviors (methods) of an existing
class (parent class or superclass). Inheritance promotes code reusability and establishes a
relationship between the parent and child classes.
In Java, inheritance allows the subclass to:
Page | 67
Access public and protected members (fields and methods) of the superclass.
Override methods of the superclass to provide specific functionality in the subclass.
Inherit constructors and fields from the superclass.
Types of Inheritance in Java
Java supports the following types of inheritance:
1. Single Inheritance:
o In single inheritance, a class (child class) can inherit from only one class
(parent class).
o This is the most common form of inheritance.
Example:
class Animal {
public void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("Dog barks");
}
}
2. Multilevel Inheritance:
o In multilevel inheritance, a class inherits from another class, and that class can
be further inherited by another class, creating a chain of inheritance.
o The chain can be of any length, but Java supports only one inheritance chain,
as Java does not support multiple inheritance directly (through classes).
Example:
class Animal {
public void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("Dog barks");
}
}
class Puppy extends Dog {
public void sound() {
System.out.println("Puppy whines");
}
}
3. Hierarchical Inheritance:
o In hierarchical inheritance, multiple classes inherit from a single parent class.
Several child classes can share the same parent class.
Example:
class Animal {
public void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
public void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
public void sound() {
System.out.println("Cat meows");
}
Page | 68
}
4. Multiple Inheritance (through Interfaces):
o Java does not support multiple inheritance through classes to avoid ambiguity
(e.g., the "Diamond Problem"). However, multiple inheritance is supported
through interfaces.
o A class can implement multiple interfaces, and each interface can declare
methods that the class must implement.
Example:
interface Animal {
void sound();
}
interface Bird {
void fly();
}
class Bat implements Animal, Bird {
public void sound() {
System.out.println("Bat makes a screeching sound");
}
public void fly() {
System.out.println("Bat flies");
}
}
5. Hybrid Inheritance:
o Hybrid inheritance is a combination of more than one type of inheritance. It
can involve single, multilevel, and hierarchical inheritance, but Java does not
directly support hybrid inheritance using classes. It can be implemented
using interfaces.
Example:
interface Animal {
void sound();
}
interface Bird {
void fly();
}
class Bat extends Animal implements Bird {
public void sound() {
System.out.println("Bat makes a screeching sound");
}
public void fly() {
System.out.println("Bat flies");
}
}
.
17. Compare and contrast method overloading and method overriding with suitable example 8
Ans
Comparison of Method Overloading and Method Overriding
Feature Method Overloading Method Overriding
Definition Defining multiple methods with A subclass provides a specific
the same name but different implementation of a method already
parameters in the same class. defined in the superclass.
Method Methods must have the same Methods must have the same name,
Signature name but different parameters same parameters, and same return
(number or type). type.
Binding Compile-time polymorphism Runtime polymorphism (dynamic
(static binding). The method to binding). The method to call is
call is determined at compile-time. determined at runtime based on the
object's type.
Page | 69
Purpose To perform similar tasks with To provide specific functionality in the
different inputs (parameters). subclass, replacing the method in the
parent class.
Inheritance Not required. Overloading can Requires inheritance. The method is
happen within the same class. overridden in the subclass.
Return Type Overloading does not consider The return type must be the same or
return type. Methods must differ covariant (i.e., subclass of the return
in parameters only. type in the parent class).
Example Method to add integers, floats, or
Method sound() in Animal class
doubles. overridden in Dog class.
Example of Method Overloading:
class Calculator {
public int add(int a, int b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
public double add(double a, double b) {
return a + b;
}
}
public class MethodOverloadingExample {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println("Sum of 2 integers"+calc.add(5,10));
System.out.println("Sumof3integers"+calc.add(5,10,15));
System.out.println("Sumof2doubles"+calc.add(5.5,10.5));
}
}
Output:
Sum of 2 integers: 15
Sum of 3 integers: 30
Sum of 2 dOoubles: 16.0
Example of Method Overriding:
class Animal {
public void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Dog barks");
}
}
public class MethodOverridingExample {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myDog = new Dog();
myAnimal.sound();
myDog.sound();
}
}
Output:
Animal makes sound
Dog barks
Page | 70
Module 04
Packages: Packages, Packages and Member Access, Importing Packages.
Exceptions: Exception-Handling Fundamentals, Exception Types, Uncaught Exceptions, Using try and catch,
Multiple catch Clauses, Nested try Statements, throw, throws, finally, Java’s Built-in Exceptions, Creating Your
Own Exception Subclasses, Chained Exceptions.
Page | 71
System.out.println("Hello from Person class in
package1");
}
}
Package 2: package2
package package2;
import package1.Person;
public class Main {
public static void main(String[] args) {
// Using the imported class directly
Person person = new Person();
person.greet();
}
}
Output:
Hello from Person class in package1
Wildcard Import
The wildcard * is used to import all classes from a package. It does not import sub-packages.
Example: Wildcard Import
Package 1: package1
package package1;
public class Person {
public void greet() {
System.out.println("Hello from Person class in
package1");
}
Page | 72
}
public class Employee {
public void job() {
System.out.println("Employee class in package1");
}
}
Package 2: package2
package package2;
import package1.*;
public class Main {
public static void main(String[] args) {
// Using classes from package1
Person person = new Person();
person.greet();
// Class definition
public class ClassName {
// Class members (fields, methods)
}
Steps to Add a New Class to a Package:
1. Create the Package (If not already created).
2. Declare the class within that package.
3. Compile and Run the classes, ensuring that the package structure is maintained.
project_folder/
├── company/
│ ├── Employee.java
│ ├── Manager.java
├── Main.java
Explanation:
1. Creating the Package: The package company; at the beginning of Employee.java and
Manager.java declares that these classes belong to the company package.
2. Accessing Classes: The Main.java file imports the classes Employee and Manager
from the company package using import company.Employee; and import
company.Manager;.
3. Inheritance: The Manager class extends Employee and uses the super keyword to call
the parent class constructor and methods.
03. What is package? How do we create it? Give the example to create and to access package. 8
Ans Package in Java
In Java, a package is a way of grouping related classes, interfaces, and sub-packages. Packages
provide a namespace to avoid name conflicts, help organize code, and control access to classes,
methods, and variables.
Use of packages?
Page | 74
1. Organize Code: Packages help to organize the classes and interfaces in a meaningful
way (e.g., grouping utility classes, database handling classes, etc.).
2. Avoid Name Conflicts: By using packages, you avoid conflicts between class names
by making class names unique within a namespace.
3. Access Control: Packages help control access to classes and members by specifying
access modifiers (e.g., public, protected, default).
Types of Packages in Java
1. Built-in Packages: Java provides a rich set of pre-defined packages (e.g., java.util,
java.io).
2. User-defined Packages: You can define your own packages to organize your own
classes and interfaces.
Creating a Package
To create a package in Java:
1. Use the package keyword at the top of the Java source file to specify the package
name.
2. The source code file must be saved in a directory that matches the package structure.
Steps to Create and Access a Package
1. Create a Package:
o The package is created using the package keyword, followed by the package
name.
2. Accessing Classes from the Package:
o To use the classes from the created package, you can either:
Use the import statement in the file where you want to use the
package.
Use the fully qualified class name (without import).
Page | 75
3. Run the program:
o Finally, run the Main class:
o java Main
Output:
Hello from the com.myapp.utility package!
Explanation:
1. Creating a Package:
o The package com.myapp.utility; statement at the top of Hello.java defines the
package name.
o The Hello class is placed in the com/myapp/utility/ folder to match the package
structure.
2. Accessing the Package:
o In Main.java, the import com.myapp.utility.Hello; statement is used to access
the Hello class from the package.
o You could also use the fully qualified name com.myapp.utility.Hello directly in
the Main class, but importing the class makes it easier.
04. What do you mean by a package? How do you use it in a Java program? Explain with a 8
program.
Ans What is a Package in Java?
A package in Java organizes related classes, interfaces, and sub-packages into namespaces. It
helps manage code efficiently by grouping similar functionality, avoiding class name conflicts,
and improving maintainability.
Types of Packages
1. Built-in Packages: Provided by Java API (e.g., java.util, java.io).
2. User-defined Packages: Created by developers for organizing custom classes.
Benefits
Namespace Management: Avoids naming conflicts.
Code Organization: Groups related classes logically.
Access Protection: Controls access using modifiers.
Reusability: Simplifies code sharing and usage.
Using Packages in Java
1. Declare a Package: Use the package keyword.
2. Import a Package: Use the import statement to use classes from another package.
Example Program
Step 1: Create a package shapes with a class Circle.
Circle.java
package shapes;
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
}
Step 2: Use the Circle class in another file.
Main.java
import shapes.Circle;
public class Main {
public static void main(String[] args) {
Circle circle = new Circle(5.0);
System.out.println("Area: " + circle.area());
}
}
Steps to Run
1. Compile Circle.java:
Page | 76
2. javac shapes/Circle.java
3. Compile Main.java:
4. javac Main.java
5. Run the program:
6. java Main
Output:
Area: 78.53981633974483
Page | 77
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double area() {
return Math.PI * radius * radius;
}
}
Main.java (using the shapes.Circle class):
import shapes.Circle;
public class Main {
public static void main(String[] args) {
Circle circle = new Circle(5.0);
System.out.println("Area of the circle: " +
circle.area());
}
}
package package2;
import package1.AccessExample;
public class TestAccess extends AccessExample {
public static void main(String[] args) {
AccessExample obj = new AccessExample();
System.out.println("Public field: " +
obj.publicField);
System.out.println("Protected field: " +
obj.protectedField);
System.out.println("Default field: " +
obj.defaultField);
System.out.println("Private field: " +
obj.privateField);
obj.showPublic();
obj.showProtected();
obj.showDefault();
obj.showPrivate();
}
}
07. Define an interface. Explain how to define and implement an interface with an example. 8
Ans Definition of an Interface in Java
An interface in Java is a blueprint for a class. It is a collection of abstract methods (methods
without a body) and static constants. Interfaces are used to achieve 100% abstraction (before
Java 8) and provide a way to specify behavior that implementing classes must follow.
Key features of an interface:
Methods in an interface are public and abstract by default.
Fields in an interface are public, static, and final (constants).
Page | 79
A class implements an interface using the implements keyword.
A class can implement multiple interfaces, supporting multiple inheritance.
Defining an Interface
To define an interface, use the interface keyword:
interface InterfaceName {
void method1();
void method2();
int CONSTANT = 10;
}
Implementing an Interface
A class implements an interface using the implements keyword. The class must provide
implementations for all abstract methods in the interface:
class ClassName implements InterfaceName {
public void method1() {
System.out.println("Method1 implementation");
}
public void method2() {
System.out.println("Method2 implementation");
}
}
Example Program
Step 1: Define an Interface
interface Animal {
void sound();
void eat();
}
Step 2: Implement the Interface
class Dog implements Animal {
public void sound() {
System.out.println("Dog barks");
}
public void eat() {
System.out.println("Dog eats bones");
}
}
Step 3: Use the Implementing Class
public class Main {
public static void main(String[] args) {
// Create an object of the Dog class
Animal myDog = new Dog();
Key Points
1. Interface as a Contract:
o An interface defines a set of methods that any implementing class must fulfill,
ensuring consistency in behavior.
2. Multiple Implementation:
o A class can implement multiple interfaces:
interface A { void methodA(); }
interface B { void methodB(); }
class C implements A, B {
Page | 80
public void methodA() {
System.out.println("MethodA implementation");
}
public void methodB() {
System.out.println("MethodB implementation");
}
}
3. Default Methods (Java 8):
o Interfaces can have default methods with a body:
interface Greet {
default void sayHello() {
System.out.println("Hello from the
interface!");
}
}
4. Static Methods (Java 8):
o Interfaces can have static methods:
interface MathOperations {
static int add(int a, int b) {
return a + b;
}
}
5. Functional Interfaces:
o An interface with a single abstract method is called a functional interface
(e.g., Runnable, Comparator).
o Example:
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}
Advantages of Interfaces
Achieve abstraction and define a clear contract for implementing classes.
Facilitate multiple inheritance, which is not possible with classes.
Enhance flexibility by allowing different classes to implement the same behavior.
Page | 81
variables can have any access
modifier.
Constructor Can have a constructor. Cannot have a constructor.
Access Abstract methods can be All methods are public by default.
Modifiers for protected, public, or package-
Methods private.
When to Use Use abstract classes when you Use interfaces to define a contract that
want to share code between can be implemented by unrelated
related classes or when a "is-a" classes.
relationship exists.
Performance Slightly faster because it uses Slightly slower due to additional
inheritance. method resolution overhead.
Example See below for examples. See below for examples.
Example of an Interface
interface Animal {
void sound();
void eat();
}
class Dog implements Animal {
public void sound() {
System.out.println("Dog barks");
}
public void eat() {
System.out.println("Dog eats bones");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.sound(); // Output: Dog barks
myDog.eat(); // Output: Dog eats bones
}
}
09. How do you define variables inside interface? List out the characteristics of such variables. 6
Ans In Java, variables declared in an interface have special characteristics. They are essentially
treated as constants. Here's how you define variables inside an interface:
Page | 82
interface MyInterface {
int VALUE = 10;
}
Characteristics of Variables in an Interface
1. public:
o Interface variables are always public by default.
o They can be accessed anywhere the interface is visible.
2. static:
o Interface variables are static, meaning they belong to the interface itself, not to
any instance of the implementing class.
o They can be accessed using the interface name, e.g., MyInterface.VALUE.
3. final:
o Interface variables are final, meaning their values cannot be changed after they
are assigned.
4. Constant by Nature:
o Since variables in interfaces are static and final, they are effectively constants.
Their value must be assigned at the time of declaration.
5. No Modifiers Needed:
o Even if you do not explicitly declare the variable as public, static, or final, Java
automatically applies these modifiers.
6. Accessible Without an Object:
o Because they are static, you don’t need to create an object of the implementing
class to access them.
Example
Defining and Accessing Variables in an Interface
interface MyInterface {
int MAX_VALUE = 100;
}
class Test implements MyInterface {
public void display() {
System.out.println("MAX_VALUE: " + MAX_VALUE);
}
}
public class Main {
public static void main(String[] args) {
Test test = new Test();
test.display();
System.out.println("Access through interface: " +
MyInterface.MAX_VALUE);
}
}
Page | 83
o Variables in an interface are always public and cannot have more restrictive
access modifiers like private or protected.
10. Define an exception. What are the key terms used in exception handling? Explain. 8
Ans An exception in Java is an event that occurs during the execution of a program and disrupts the
normal flow of instructions. Exceptions are objects that represent an error or an unexpected
behavior in a program.
For example:
Dividing by zero (ArithmeticException).
Accessing an invalid array index (ArrayIndexOutOfBoundsException).
Attempting to open a file that doesn’t exist (FileNotFoundException).
Java provides a robust mechanism to handle such exceptions, ensuring the program can recover
gracefully.
Page | 84
o Example: IOException, SQLException.
8. Unchecked Exceptions:
o Exceptions that occur at runtime and are not checked at compile-time.
o Example: ArithmeticException, NullPointerException.
Page | 85
Example of Nested try Block
public class NestedTryExample {
public static void main(String[] args) {
try {
System.out.println("Outer try block started");
try {
System.out.println("Inner try block started");
int result = 10 / 0;
System.out.println("Inner try block ends");
} catch (ArithmeticException e) {
System.out.println("Inner catchblockcaught"+e);
}
String str = null;
System.out.println(str.length());
} catch (NullPointerException e) {
System.out.println("Outer catch block caught: "+e);
}
System.out.println("Program continues after the nested
try-catch");
}
}
Explanation
1. Outer Try Block:
o The outer try block starts executing first.
o Inside the outer try block, there is an inner try block.
2. Inner Try Block:
o The inner try block attempts to execute the division operation 10 / 0, which
will throw an ArithmeticException.
o This exception is caught by the inner catch block.
o After catching the ArithmeticException, the program moves on to execute the
remaining code in the outer block.
3. Inner Catch Block:
o Catches and handles the ArithmeticException from the inner try block and
prints an appropriate message.
4. Code After Inner Try-Catch:
o After the inner try-catch block finishes, the outer try block continues
executing.
o It attempts to execute str.length(), which throws a NullPointerException
because str is null.
5. Outer Catch Block:
o The outer catch block catches the NullPointerException and prints the
message.
6. Program Continues:
o After both catch blocks execute, the program continues with the next
statements outside the try-catch blocks.
Output
Outer try block started
Inner try block started
Inner catch block caught: java.lang.ArithmeticException: / by
zero
Outer catch block caught: java.lang.NullPointerException:
Cannot invoke "String.length()" because "str" is null
Program continues after the nested try-catch
Page | 86
Fine-grained Exception Handling: You can handle exceptions at different levels and
in different parts of your code.
Flexibility: Provides flexibility to deal with various scenarios where different actions
are required depending on where the exception occurred.
12. Write a program which contains one method which will throw Illegal Access Exception and use 8
proper exception handles so that exception should be printed.
Ans public class IllegalAccessExceptionExample {
public static void accessRestrictedMethod() throws
IllegalAccessException {
boolean hasAccess = false;
if (!hasAccess) {
throw new IllegalAccessException("Access is
denied!");
}
System.out.println("Access granted.");
}
public static void main(String[] args) {
try {
accessRestrictedMethod();
} catch (IllegalAccessException e) {
System.out.println("Exception caught:"+
e.getMessage());
}
System.out.println("Program continues after handling
the exception.");
}
}
13. Write a note on: 8
i. Java’s built-in exception
ii. Uncaught Exceptions
Ans i. Java's Built-in Exceptions
Java provides a set of predefined exceptions to handle various errors that may occur during
the execution of a program. These built-in exceptions are part of Java’s exception handling
framework and are categorized as follows:
1. Checked Exceptions:
o These exceptions are checked at compile-time. The compiler ensures that the
exceptions are either caught in a try-catch block or declared in the method
signature using the throws keyword.
o Examples:
IOException: Thrown when an I/O operation fails (e.g., reading from a
file).
SQLException: Thrown when there is an error with SQL queries or
database access.
ClassNotFoundException: Thrown when a class is not found during
runtime.
2. Unchecked Exceptions (Runtime Exceptions):
o These exceptions are not checked at compile-time, meaning they can occur
due to logical errors or programming mistakes. These are inherited from
RuntimeException and can occur at any point in the program.
o These exceptions don’t require explicit handling, but it is good practice to
catch them when necessary.
o Examples:
NullPointerException: Thrown when an object reference is null and is
accessed.
ArrayIndexOutOfBoundsException: Thrown when trying to access an
invalid index in an array.
Page | 87
ArithmeticException: Thrown when an illegal arithmetic operation
(like division by zero) occurs.
3. Errors:
o Errors are serious issues that usually cannot be handled by the application.
These are inherited from the Error class and represent conditions that cannot be
reasonably recovered from.
o Examples:
OutOfMemoryError: Thrown when the JVM runs out of memory.
StackOverflowError: Thrown when there is a stack overflow due to
deep recursion.
Summary
Aspect Built-in Exceptions Uncaught Exceptions
Definition Predefined exceptions like Exceptions thrown that are not caught by any
IOException, catch block.
NullPointerException.
Page | 88
Handling Checked exceptions must be Uncaught exceptions propagate and cause
caught or declared. program termination unless handled.
Unchecked exceptions don’t
require explicit handling but
can be caught.
Types Includes checked Any exception that is not caught by a catch
exceptions, unchecked block is uncaught.
exceptions (runtime), and
errors.
Example IOException, Uncaught NullPointerException,
ArithmeticException, RuntimeException.
ClassNotFoundException.
Special Requires explicit handling Can be globally handled using
Handling via try-catch or throws. Thread.setDefaultUncaughtExceptionHandler().
14. How do you create your own exception class? Explain with a program. 7
Ans In Java, you can create your own exception class by extending one of the existing exception
classes. Typically, custom exceptions extend the Exception class for checked exceptions or the
RuntimeException class for unchecked exceptions.
Steps to Create a Custom Exception:
1. Extend an Exception Class: Your custom exception class should extend either
Exception (for checked exceptions) or RuntimeException (for unchecked exceptions).
2. Define Constructors: Provide constructors that allow you to pass custom messages or
cause information (like stack traces).
3. Optionally, Add Additional Methods: You can add additional fields or methods if
required.
Page | 89
}
}
public class CustomUncheckedExceptionExample {
public static void checkAge(int age) {
if (age < 18) {
throw new InvalidAgeException("Age is less than 18.
Invalid age.");
}
System.out.println("Age is valid.");
}
Output:
Caught exception: Age is less than 18. Invalid age.
15. Examine the various levels of access protections available for packages and their 10
implications with suitable examples.
Ans
Feature public protected default (package- private
private)
Access within Yes Yes Yes Yes
the same class
Access within Yes Yes Yes No
the same
package
Access by Yes Yes (even in No No
subclasses different
packages)
Access from Yes No No No
different
packages
Typical use For classes, When you For internal For
case methods, and want members implementation, encapsulating
variables that to be where members data, making
should be accessible should only be variables and
accessible within the accessible within methods
from package and the package accessible only
anywhere in by subclasses within the class
the program itself
Degree of Low (no Moderate High (only within Very high
encapsulation protection) (accessible to the package) (restricted to the
subclasses) class)
Explanation:
1. public: No access restrictions; members are accessible from anywhere.
2. protected: Accessible within the same package and by subclasses, including those in
different packages.
3. default (package-private): Only accessible within the same package, not from
outside.
Page | 90
4. private: The most restrictive, accessible only within the same class.
class AccessSpecifiersDemo {
public String publicVar = "Public Access";
protected String protectedVar = "Protected Access";
String defaultVar = "Default Access";
private String privateVar = "Private Access";
public void displayPublic() {
System.out.println("Public Method: " + publicVar);
}
protected void displayProtected() {
System.out.println("Protected Method: " +
protectedVar);
}
void displayDefault() {
System.out.println("Default Method: " + defaultVar);
}
private void displayPrivate() {
System.out.println("Private Method: " + privateVar);
}
public void showAllAccess() {
displayPublic();
displayProtected();
displayDefault();
displayPrivate();
}
}
public class TestAccess {
public static void main(String[] args) {
AccessSpecifiersDemo demo = new AccessSpecifiersDemo();
System.out.println(demo.publicVar);
demo.displayPublic();
System.out.println(demo.protectedVar);
demo.displayProtected();
System.out.println(demo.defaultVar);
demo.displayDefault();
demo.showAllAccess();
}
}
16. Build a Java program for a banking application to throw an exception where a person 10
tries to withdraw a person tries to withdraw the amount even though he/she has lesser
than minimum balance( Create a custom exception)
Ans class InsufficientBalanceException extends Exception {
public InsufficientBalanceException(String message) {
super(message);
}
}
class BankAccount {
private double balance;
private final double MIN_BALANCE = 500;
Page | 91
throw new InsufficientBalanceException("Cannot
withdraw! Minimum balance of " + MIN_BALANCE + " should be
maintained.");
}
balance -= amount;
System.out.println("Withdrawal successful! Remaining
balance: " + balance);
}
public double getBalance() {
return balance;
}
}
public class BankingApplication {
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
try {
account.withdraw(600);
} catch (InsufficientBalanceException e) {
System.out.println(e.getMessage());
}
}
}
17. Define Exception. Explain Exception handling mechanism provided in Java along with 10
syntax and example
Ans An exception in Java is an event that disrupts the normal flow of the program. It is an object
that represents an error or an unusual condition encountered during program execution.
Exception Handling Mechanism in Java:
Java provides a robust exception handling mechanism to handle runtime errors, allowing the
program to continue execution even when an exception occurs. It involves the following
components:
1. Try Block: The code that might throw an exception is placed inside the try block.
2. Catch Block: This block catches the exception and handles it appropriately.
3. Finally Block: This block always executes whether or not an exception occurred,
typically used for cleanup tasks.
4. Throw Statement: Used to explicitly throw an exception.
5. Throws Keyword: Used in method declarations to indicate that a method might throw
an exception.
Syntax:
try {
// Code that may throw an exception
} catch (ExceptionType e) {
// Code to handle the exception
} finally {
// Code to clean up (optional)
}
Example 1:
public class ExceptionHandlingExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Error: Division by zero");
} finally {
System.out.println("This will always execute");
}
}
}
Example 2:
Page | 92
public class ThrowExample {
public static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Age must be 18 or
older");
} else {
System.out.println("Age is valid");
}
}
18. Build a Java program to create a package ‘balance’ containing Account class with 10
displayBalance() method and import this package in another program to access method
of Account class
Ans Account.java
package balance;
public class Account {
private double balance;
public Account(double balance) {
this.balance = balance;
}
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("Deposited: " + amount);
} else {
System.out.println("Invalid amount.");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("Withdrawn: " + amount);
} else {
System.out.println("Insufficient balance.");
}
}
public void displayBalance() {
System.out.println("Balance: " + balance);
}
20. Write a program that contains one method that will throw an IllegalAccessException and 7
use proper exception handles so that the exception should be printed.
Ans public class IllegalAccessExample {
public static void checkAccess(boolean hasAccess) throws
IllegalAccessException {
Page | 94
if (!hasAccess) {
throw new IllegalAccessException("Access Denied:
You do not have permission to access this resource.");
}
System.out.println("Access Granted: You have permission
to access this resource.");
}
public static void attemptAccess(String username, boolean
hasAccess) {
try {
System.out.println("User: " + username + " is
attempting to access the resource...");
checkAccess(hasAccess);
} catch (IllegalAccessException e) {
System.out.println("Exception caught: " +
e.getMessage());
}
}
public static void main(String[] args) {
attemptAccess("John", false);
attemptAccess("Jane", true);
attemptAccess("Mike", false);
attemptAccess("Alice", true);
}
}
21. Explain the concept of importing packages in Java and provide an example 7
demonstrating the usage of the import statement.
Ans In Java, packages are used to organize classes, interfaces, and sub-packages. Java provides the
import statement to bring classes or entire packages into the scope of a program so that you can
use them without needing to reference their full package name. This helps to avoid repetition of
the full path of classes and makes code cleaner and more maintainable.
There are two types of imports:
1. Single Type Import: Import a specific class or interface from a package.
2. Wildcard Import: Import all classes from a package using a wildcard (*).
Syntax:
Single Type Import:
import packageName.ClassName;
Wildcard Import:
import packageName.*;
Example:
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Collections;
public class ImportExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayList<Integer> numbers = new ArrayList<>();
System.out.println("Enter 5 numbers:");
for (int i = 0; i < 5; i++) {
numbers.add(scanner.nextInt());
}
System.out.println("Original numbers: " + numbers);
Collections.sort(numbers);
System.out.println("Sorted numbers: " + numbers);
int max = Collections.max(numbers);
System.out.println("Maximum number: " + max);
int min = Collections.min(numbers);
System.out.println("Minimum number: " + min);
}
Page | 95
}
In this example:
The import java.util.Scanner; statement imports the Scanner class from the java.util
package.
The Scanner class is used to read input from the user. Without the import statement,
you would have to use the full path java.util.Scanner every time.
22. How do you create your own exception class? Explain with a program. 7
Ans To create your own exception class in Java, you can extend one of the existing exception
classes (like Exception or RuntimeException). This allows you to define custom exceptions
that can be thrown and caught just like built-in exceptions.
Steps to Create a Custom Exception Class:
1. Define the exception class: Inherit from the Exception or RuntimeException class.
2. Add constructors: Provide constructors to initialize the exception with custom error
messages or cause (optional).
3. Throw the exception: Use throw to trigger the exception when a specific condition is
met.
Example:
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
public class CustomExceptionExample {
public static void checkAge(int age) throws
InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age must be at least
18.");
}
System.out.println("Valid age: " + age);
}
public static void main(String[] args) {
try {
checkAge(15);
} catch (InvalidAgeException e) {
System.out.println("Exception: " + e.getMessage());
}
try {
checkAge(20);
} catch (InvalidAgeException e) {
System.out.println("Exception: " + e.getMessage());
}
}
}
Explanation:
1. Custom Exception (InvalidAgeException): The InvalidAgeException class extends
the Exception class. It takes a custom message and passes it to the superclass
constructor.
2. Method (checkAge): This method checks if the provided age is below 18. If so, it
throws the InvalidAgeException.
3. Exception Handling: In the main method, the checkAge method is called twice: once
with an invalid age (15) and once with a valid age (20). The exception is caught and
the message is printed.
Output:
Exception: Age must be at least 18.
Valid age: 20
Page | 96
23. Demonstrate the working of a nested try block with an example. 6
Ans A nested try block in Java is when one try block is placed inside another try block. This can be
useful when you need to handle multiple levels of exceptions in different parts of the code.
Syntax:
try {
// Outer try block
try {
// Inner try block
} catch (ExceptionType1 e) {
// Handle inner exception
}
} catch (ExceptionType2 e) {
// Handle outer exception
}
Example:
public class NestedTryExample {
public static void main(String[] args) {
try {
System.out.println("Outer try block starts");
try {
System.out.println("Inner try block starts");
int result = 10 / 0; // Division by zero
} catch (ArithmeticException e) {
System.out.println("Inner catch: " +
e.getMessage());
}
System.out.println("End of program");
}
}
Explanation:
1. The outer try block contains another try block inside it (nested).
2. The inner try block attempts to divide by zero, causing an ArithmeticException, which
is caught by the inner catch block.
3. After that, the outer block attempts to print the length of a null string, which causes a
NullPointerException, caught by the outer catch block.
4. This shows how multiple exceptions can be handled at different levels using nested try
blocks.
Output:
Outer try block starts
Inner try block starts
Inner catch: / by zero
Outer catch: Cannot invoke "String.length()" because "str" is
null
End of program
Page | 97
Module 05
Multithreaded Programming: The Java Thread Model, The Main Thread, creating a Thread, Creating Multiple
Threads, Using isAlive() and join(), Thread Priorities, Synchronization, Interthread Communication, Suspending,
Resuming, and Stopping Threads, Obtaining a Thread’s State.
Enumerations, Type Wrappers and Autoboxing: Enumerations (Enumeration Fundamentals, The values() and
valueOf() Methods), Type Wrappers (Character, Boolean, The Numeric Type Wrappers), Autoboxing (Autoboxing
and Methods, Autoboxing/Unboxing Occurs in Expressions, Autoboxing/Unboxing Boolean and Character Values).
N Questions/Answers Mark
o s
01 What do you mean by a thread? Explain the different ways of creating threads. 7
.
A A thread is a lightweight process that allows a program to perform multiple operations concurrently.
Each thread has its own program counter, stack, and local variables. Threads are commonly used in
situations where tasks need to be performed simultaneously or in the background, such as
downloading files, handling user input, or running multiple processes concurrently in an application.
In Java, threads are part of the java.lang package, and they allow the execution of multiple parts of a
program in parallel, utilizing multiple CPU cores efficiently.
Different Ways of Creating Threads in Java:
There are two main ways to create a thread in Java:
1. By Extending the Thread Class:
You can create a thread by extending the Thread class and overriding its run() method. After creating
the thread, you invoke the start() method to begin its execution.
Steps:
Extend the Thread class.
Override the run() method to define the code that the thread will execute.
Create an instance of the class and call the start() method.
Example:
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running.");
}
public static void main(String[] args) {
MyThread thread1 = new MyThread();
thread1.start(); // Starting the thread
}
}
2. By Implementing the Runnable Interface:
You can create a thread by implementing the Runnable interface. The Runnable interface contains a
single method run(), which is implemented by the class. After implementing the Runnable interface,
you pass an instance of the class to a Thread object and then start the thread.
Steps:
Implement the Runnable interface.
Define the run() method to specify the thread's code.
Create a Thread object and pass the Runnable object to it.
Start the thread by calling start().
Example:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running.");
}
public static void main(String[] args) {
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable); // Passing
Runnable to Thread
thread1.start(); // Starting the thread
}
}
Page | 98
Differences between Extending Thread and Implementing Runnable:
Aspect Extending Thread Implementing Runnable
Inheritance Can only extend Thread, so can't Can implement Runnable and
extend other classes. extend other classes.
Code Reusability Less reusable since it extends More reusable, can be used with any
Thread. Thread object.
Multiple Threads Difficult to create multiple threads Easy to create multiple threads of
of the same class. the same class.
Recommended Useful for simple cases. Preferred when a class already
Approach extends another class.
Which Approach to Use?
Extending Thread is simple but limits you to a single inheritance structure.
Implementing Runnable is more flexible and should be preferred when you need to
implement multiple threads or when the class is already extending another class.
Conclusion:
Threads allow concurrent execution of code, making programs more efficient.
You can create threads either by extending the Thread class or by implementing the
Runnable interface, depending on the needs of your application.
Page | 99
t1.join(); t2.join();
System.out.println("Final count: " + counter.getCount());
}
}
Explanation:
1. Synchronization of Methods: The increment() and decrement() methods are synchronized,
meaning that if one thread is executing one of these methods, no other thread can execute
either method on the same object at the same time.
2. Threads t1 and t2: These two threads increment and decrement the counter 1000 times each.
The synchronization ensures that no two threads can modify the counter at the same time,
preventing inconsistent values.
3. Output: After both threads have finished, the final count will be 0, as each increment is
paired with a decrement, and the operations are thread-safe.
2. Block Synchronization (Synchronized Block):
Instead of synchronizing the entire method, you can synchronize only a specific block of code within
a method. This allows for finer control over what needs to be synchronized, making it more efficient.
Example:
class Counter {
private int count = 0;
public void increment() {
synchronized (this) {
count++;
}
}
public void decrement() {
synchronized (this) {
count--;
}
}
public int getCount() {
return count;
}
}
public class SynchronizationExample {
public static void main(String[] args) throws
InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> { for (int i = 0; i < 1000;
i++) counter.increment(); });
Thread t2 = new Thread(() -> { for (int i = 0; i < 1000;
i++) counter.decrement(); });
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println("Final count: " + counter.getCount());
}
}
Explanation:
1. Synchronized Block: The increment() and decrement() methods have synchronized blocks
that control access to the count variable. By synchronizing only the critical part (modification
of the count), we avoid synchronizing the entire method, which improves performance.
2. Thread Safety: The synchronized blocks ensure that when one thread is incrementing or
decrementing the counter, no other thread can access the count variable simultaneously, thus
avoiding data inconsistency.
03 Discuss values() and value Of() methods in Enumerations with suitable examples. 6
.
A In Java, Enumerations (Enums) are a special type that represents a group of constants. The values()
and valueOf() methods are part of every enum class in Java by default, which makes it easy to work
with enums.
1. values() Method
Page | 100
The values() method returns an array of all the constants defined in the enum type, in the order they
are declared.
Return Type: T[] (Array of enum constants)
Usage: This method is useful when you want to get all the values of the enum.
Example:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}
Page | 101
public class EnumValueOfExample {
public static void main(String[] args) {
String input = "FUNDAY"; // Invalid day
try {
Day day = Day.valueOf(input);
System.out.println("The day is: " + day);
} catch (IllegalArgumentException e) {
System.out.println("Invalid day input: " + input);
}
}
}
Output:
Invalid day input: FUNDAY
Page | 104
Thread.sleep(1500); // Simulate time taken to
consume data
}
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
public class InterThreadCommunicationExample {
public static void main(String[] args) {
SharedData sharedData = new SharedData();
Producer producer = new Producer(sharedData);
Consumer consumer = new Consumer(sharedData);
producer.start();
consumer.start();
}
}
Explanation:
1. SharedData Class: This class holds the shared data (data) and a boolean (available) to track
if the data is available for consumption.
o produce() method: The Producer thread calls this method to produce data. If the data
is already available (i.e., the consumer has not consumed it), the producer waits until
the consumer consumes it and notifies the producer.
o consume() method: The Consumer thread calls this method to consume the data. If
no data is available, the consumer waits until the producer produces data and notifies
the consumer.
2. Producer Class: This thread produces data (numbers from 1 to 5) and notifies the consumer
after producing each item.
3. Consumer Class: This thread consumes the data produced by the producer and notifies the
producer after consuming each item.
4. Synchronization: Both produce() and consume() methods are synchronized to ensure only
one thread accesses the shared resource (data) at a time.
5. wait() and notify():
o The Producer thread waits if the data is already available (i.e., the consumer hasn't
consumed it yet).
o The Consumer thread waits if no data is available to consume.
Output (Order may vary due to thread execution timing):
Produced: 1
Consumed: 1
Produced: 2
Consumed: 2
Produced: 3
Consumed: 3
Produced: 4
Consumed: 4
Produced: 5
Consumed: 5
06 Explain auto-boxing/unboxing in expressions. 6
.
A Auto-boxing and Unboxing in Java
Auto-boxing and unboxing are automatic conversions between primitive types and their
corresponding wrapper classes in Java. Java provides wrapper classes for each primitive type (e.g.,
Integer, Double, Character) to treat primitives as objects when required.
Auto-boxing:
Auto-boxing is the automatic conversion of a primitive type to its corresponding wrapper class
object. This happens when a primitive value is assigned to a variable of its corresponding wrapper
class, or when a primitive is passed as an argument to a method that expects an object.
For example:
int to Integer
Page | 105
double to Double
Unboxing:
Unboxing is the reverse process, where an object of a wrapper class is automatically converted to its
corresponding primitive type. This happens when a wrapper class object is assigned to a variable of
the corresponding primitive type.
For example:
Integer to int
Double to double
Auto-boxing and Unboxing in Expressions
In expressions, auto-boxing and unboxing allow primitive values and their wrapper objects to be used
interchangeably, simplifying the code and improving readability.
Example Program Demonstrating Auto-boxing and Unboxing:
public class AutoBoxingUnboxingExample {
public static void main(String[] args) {
int a = 10;
Integer integerObject = a;
Integer b = new Integer(20);
int c = b;
Integer sum = integerObject + b;
System.out.println("Auto-boxed Integer Object: " +
integerObject);
System.out.println("Unboxed int Value: " + c);
System.out.println("Sum of auto-boxed and unboxed values: "
+ sum);
}
}
Explanation:
1. Auto-boxing:
o The primitive int a = 10; is automatically converted to an Integer object when
assigned to Integer integerObject = a;.
2. Unboxing:
o The Integer b = new Integer(20); object is automatically converted back to the
primitive type int when assigned to int c = b;.
3. Expression Example:
o In the expression Integer sum = integerObject + b;, auto-unboxing happens
automatically for both integerObject and b, allowing them to be added as primitives,
and the result is boxed back into an Integer object.
Output:
Auto-boxed Integer Object: 10
Unboxed int Value: 20
Sum of auto-boxed and unboxed values: 30.
Page | 106
public synchronized returnType methodName() {
// method body
}
2. Synchronized Blocks
A synchronized block is used to synchronize a specific section of code, rather than the entire method.
It allows more granular control over which part of the code should be synchronized.
Syntax:
synchronized (object) {
// critical section of code
}
Example: Synchronization Using Synchronized Methods
Consider the scenario where two threads are trying to update the balance of a bank account
simultaneously. Without synchronization, it might cause data inconsistency. We'll synchronize the
withdraw method to ensure that only one thread can withdraw money at a time.
class BankAccount {
private int balance = 1000;
public synchronized void withdraw(int amount) {
if (balance >= amount) {
System.out.println(Thread.currentThread().getName() + "
is going to withdraw " + amount);
balance -= amount;
System.out.println(Thread.currentThread().getName() + "
has withdrawn " + amount);
System.out.println("Balance: " + balance);
} else {
System.out.println("Insufficient balance for " +
Thread.currentThread().getName());
}
}
}
class UserThread extends Thread {
private BankAccount account;
public UserThread(BankAccount account) {
this.account = account;
}
public void run() {
account.withdraw(500); // Simulating a withdrawal of 500
}
}
public class SynchronizationExample {
public static void main(String[] args) {
BankAccount account = new BankAccount();
UserThread t1 = new UserThread(account);
UserThread t2 = new UserThread(account);
t1.start();
t2.start();
}
}
Explanation of the Example:
1. BankAccount Class:
o It has a withdraw() method, which is synchronized to ensure that only one thread can
access this method at a time.
o If the balance is sufficient, the withdrawal is processed and the balance is updated. If
not, an error message is displayed.
2. UserThread Class:
o This class represents the threads that will perform the withdrawal. It calls the
withdraw() method on the shared BankAccount object.
3. Synchronization:
Page | 107
o The withdraw() method is synchronized, so even if multiple threads try to access it
simultaneously, the synchronization ensures that only one thread can perform
thwithdrawal at any given time.
Synchronization Using Synchronized Blocks
In some cases, you may want to synchronize only a portion of a method, rather than the entire
method. This can be done using a synchronized block. Here's how we can modify the example to use
a synchronized block instead of synchronizing the entire method.
class BankAccount {
private int balance = 1000;
public void withdraw(int amount) {
synchronized (this) {
if (balance >= amount) {
System.out.println(Thread.currentThread().getName()
+ " is going to withdraw " + amount);
balance -= amount;
System.out.println(Thread.currentThread().getName()
+ " has withdrawn " + amount);
System.out.println("Balance: " + balance);
} else {
System.out.println("Insufficient balance for " +
Thread.currentThread().getName());
}
}
}
}
class UserThread extends Thread {
private BankAccount account;
public UserThread(BankAccount account) {
this.account = account;
}
public void run() {
account.withdraw(500);
}
}
public class SynchronizationExample {
public static void main(String[] args) {
BankAccount account = new BankAccount();
09 Develop a Java program for automatic conversation of wrapper class type into corresponding 8
. primitive type that demonstrates unboxing.
A public class UnboxingExample {
public static void main(String[] args) {
Integer intObj1 = new Integer(100);
Integer intObj2 = new Integer(200);
Double doubleObj1 = new Double(50.75);
Double doubleObj2 = new Double(25.25);
int num1 = intObj1;
int num2 = intObj2;
double num3 = doubleObj1;
double num4 = doubleObj2; \
Page | 108
System.out.println("The primitive value of intObj1 is: " +
num1);
System.out.println("The primitive value of intObj2 is: " +
num2);
System.out.println("The primitive value of doubleObj1 is: "
+ num3);
System.out.println("The primitive value of doubleObj2 is: "
+ num4);
int sum = num1 + num2;
double total = num3 + num4;
System.out.println("The sum of the integers is: " + sum);
System.out.println("The total of the doubles is: " +
total);
calculation
Integer numObj3 = new Integer(15);
Integer numObj4 = new Integer(25);
int diff = numObj3 - numObj4;
System.out.println("The difference between numObj3 and
numObj4 is: " + diff);
double result = num1 + num3;
System.out.println("The mixed result of int and double
unboxing is: " + result);
}
}
10 Summarize the type wrappers supported in Java. 6
.
A Wrapper Classes in Java
In Java, wrapper classes are used to convert primitive data types into objects and vice versa. They are
part of the java.lang package and are used for providing object functionality for primitive types.
Types of Wrapper Classes:
Primitive Type Wrapper Class Purpose
boolean Boolean Represents a boolean value (true or false).
byte Byte Represents an 8-bit signed integer value.
char Character Represents a single character.
short Short Represents a 16-bit signed integer value.
int Integer Represents a 32-bit signed integer value.
long Long Represents a 64-bit signed integer value.
float Float Represents a single-precision 32-bit floating point value.
double Double Represents a double-precision 64-bit floating point value.
Key Points:
1. Autoboxing and Unboxing: Java automatically converts primitive types to wrapper class
objects (autoboxing) and wrapper class objects to primitive types (unboxing).
2. Nullability: Wrapper classes can be set to null, unlike primitive types.
3. Utility Methods: Wrapper classes provide methods to convert strings to primitive types and
vice versa, such as parseInt() for Integer, parseDouble() for Double, etc.
4. Immutable: Wrapper classes are immutable, meaning their values cannot be changed after
initialization.
Why Use Wrapper Classes?
Object Representation: Wrapper classes allow primitive types to be used as objects.
Collections: Since collections (like ArrayList, HashMap, etc.) can only hold objects and not
primitives, wrapper classes are used to store primitive values in collections.
Utility Methods: Wrapper classes provide utility methods for parsing and converting
between primitive types and strings (e.g., Integer.parseInt(), Double.parseDouble()).
Autoboxing/Unboxing: Java supports autoboxing (automatic conversion of primitive to
wrapper class) and unboxing (automatic conversion of wrapper class to primitive type).
Autoboxing and Unboxing
Autoboxing: Automatic conversion of a primitive type to its corresponding wrapper class
object.
Page | 109
Unboxing: Automatic conversion of a wrapper class object to its corresponding primitive
type.
Example:
public class WrapperExample {
public static void main(String[] args) {
int num = 100;
Integer numWrapper = num;
Integer numObj = new Integer(200);
int numPrimitive = numObj;
String str = "1234";
int parsedValue = Integer.parseInt(str);
String strFromInt = Integer.toString(numPrimitive);
System.out.println("Original Number: " + num);
System.out.println("Wrapper Object: " + numWrapper);
System.out.println("Unboxed Value: " + numPrimitive);
System.out.println("Parsed Value: " + parsedValue);
System.out.println("String from Integer: " + strFromInt);
}
}
Important Methods in Wrapper Classes:
parse<Type>(): Converts a string to the corresponding primitive type (e.g.,
Integer.parseInt(), Double.parseDouble()).
valueOf(): Returns the wrapper class object for the given primitive value or string (e.g.,
Integer.valueOf()).
toString(): Converts the primitive value into a string representation (e.g., Integer.toString()).
Page | 110
2. Unboxing in Method Arguments: Wrapper objects are automatically unboxed when passed
to methods that expect a primitive type.
12 Develop a program to create a class MyThread in this class a constructor, call the base class 8
. constructor, using super and start the thread. The run method of the class starts after this. It
can be observed that both main thread and created child thread are executed concurrently.
A class MyThread extends Thread {
public MyThread(String name) {
super(name);
start();
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName()
+ " Count: "+ i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getN
ame() + "
Thread interrupted.");
}
}
}
}
Page | 111
System.out.println(Thread.currentThread().getName() + "
ThreadCount: " + i);
try {
Thread.sleep(500); // Sleep for 500 milliseconds
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName()
+ "Thread interrupted.");
}
}
}
}
13 Define Enumerations. Give an example. 8
.
A Enumerations in Java
An enumeration (enum) is a special Java type used to define collections of constants. An enum is a
way to define a set of named values that are constant and can be used to represent a fixed set of
related values.
Enums are a type-safe way to work with constants, ensuring that only valid values from the set are
used. They were introduced in Java 5 to provide a more robust alternative to using int or String
constants.
Key Features of Enumerations:
1. Enums are implicitly final and static.
2. Enums can have fields, methods, and constructors.
3. The values() method is automatically generated for every enum and returns an array of all
enum constants.
4. Enums are type-safe, meaning only the defined constants can be assigned to the enum
variable.
Example: Enum to represent Days of the Week
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class EnumExample {
public static void main(String[] args) {
Day today = Day.MONDAY;
System.out.println("Today is: " + today);
System.out.println("Days of the week:");
for (Day day : Day.values()) {
System.out.println(day);
}
}
}
Output:
Today is: MONDAY
Days of the week:
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
Explanation:
1. Enum Definition: The enum Day defines the seven days of the week as constants.
2. Usage: In the main method, the Day enum is used to assign the day MONDAY to the
variable today. Enums are type-safe, so you can only assign valid values (Day.MONDAY,
Day.TUESDAY, etc.) to the Day type.
3. values() Method: The values() method is automatically generated and returns all the
constants of the enum, which we use in a for-each loop to print all days.
Advantages of Enums:
Page | 112
1. Type-Safety: Ensures that only valid constants can be assigned.
2. Better Code Readability: Named constants improve readability and prevent mistakes
compared to using plain integers or strings.
3. Extensibility: Enums can have fields, methods, and constructors, making them versatile for
complex scenarios..
14 "Enumerations in Java are class types"-justify this statement with appropriate examples. 8
.
A In Java, enumerations (enums) are more than just a simple set of constants. They are treated as class
types, meaning they have all the properties of classes in Java. Enums are special classes that are used
to define a set of constants in a type-safe manner, but they also have the ability to hold fields,
methods, and constructors, just like a normal class.
Let's break down why enums are class types:
1. Enum Constants as Objects: Each constant in an enum is an instance of the enum type, just
like objects are instances of a class.
2. Enums Can Have Methods: Enums can have methods that are associated with the constants,
just like a regular class.
3. Enums Can Have Fields: Enums can have fields (instance variables) that hold values
specific to each constant.
4. Enums Can Have Constructors: Enums can define constructors to initialize the constants
with specific values.
Here's a more concise version of the previous examples:
Enum with Fields and Methods:
enum Day {
MONDAY("Start of the workweek"),
TUESDAY("Second day"),
WEDNESDAY("Midweek");
private String description;
Day(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
public class EnumExample {
public static void main(String[] args) {
for (Day day : Day.values()) {
System.out.println(day + ": " + day.getDescription());
}
}
}
Enum with Overridden Methods:
enum Operation {
ADD {
public double apply(double x, double y) { return x + y; }
},
SUBTRACT {
public double apply(double x, double y) { return x - y; }
};
1. isAlive() Method
The isAlive() method is used to check whether a thread is still alive or has completed its execution.
Syntax:
boolean isAlive()
Page | 115
Return Value:
o It returns true if the thread has been started and is still running or in a waiting state.
o It returns false if the thread has already finished execution or has not yet started.
Usage:
o This method can be useful when you need to check if a thread has completed its task
or is still running.
Example:
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(i);
try {
Thread.sleep(500); // Sleep for 500ms
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
while (thread.isAlive()) {
System.out.println("Thread is still running...");
Thread.sleep(300); // Sleep for 300ms and check again
}
System.out.println("Thread has finished execution.");
}
}
Explanation:
The program starts a new thread (MyThread), and in the main thread, we continuously check
if the thread is alive using the isAlive() method. Once the thread completes its task, the main
thread prints that the thread has finished execution.
2. join() Method
The join() method is used to pause the execution of the current thread until the thread on which it is
called has completed its execution.
Syntax:
void join() throws InterruptedException
Return Value:
o This method does not return anything. It simply pauses the calling thread until the
target thread completes.
Usage:
o It is used when you want the main thread (or another thread) to wait until a specific
thread has finished its execution before proceeding further.
Example:
class MyThread extends Thread {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(i);
try {
Thread.sleep(500); /
} catch (InterruptedException e) {
System.out.println(e);
}
Page | 116
}
}
}
public class ThreadExample {
public static void main(String[] args) throws
InterruptedException {
MyThread thread = new MyThread();
thread.start();
thread.join();
System.out.println("Thread has finished execution.");
}
}
Explanation:
The join() method makes the main thread wait for the thread to finish its execution before
proceeding. Once thread completes, the main thread prints that the thread has finished
execution.
19 What is the need of synchronization? Explain with an example how synchronization is implemented 8
. in JAVA.
A Need for Synchronization in Java
In Java, synchronization is essential when multiple threads access shared resources, and there is a
possibility of data inconsistency or corruption. When multiple threads access and modify the same
data simultaneously, it can lead to unpredictable results due to concurrent modifications.
Synchronization ensures that only one thread can access the critical section (the shared resource or
code block) at a time, thereby preventing thread interference and ensuring data consistency.
Why Synchronization is Needed:
1. Data Consistency: When multiple threads access shared resources, unsynchronized access
can lead to incorrect results.
2. Avoid Thread Interference: Multiple threads modifying shared data simultaneously can
result in unintended behavior.
3. Deadlock Prevention: Proper synchronization can help avoid situations where threads wait
indefinitely for each other, leading to a deadlock.
Need for Synchronization in Java
Synchronization is necessary when multiple threads access shared resources to avoid data
inconsistency and ensure thread safety. Without synchronization, threads can interfere with each
other, leading to unpredictable results.
Example of Synchronization in Java
Without Synchronization (Problematic Example):
class Account {
private int balance = 1000;
thread1.start();
thread2.start();
}
}
Without synchronization, both threads may access and modify the balance simultaneously, causing
inconsistencies.
With Synchronization (Fixed Example):
class Account {
private int balance = 1000;
public synchronized void withdraw(int amount) {
if (balance >= amount) {
balance = balance - amount;
System.out.println("Withdrawal successful! Current
balance: " + balance);
} else {
System.out.println("Insufficient funds.");
}
}
}
class BankThread extends Thread {
private Account account;
// Set priorities
t1.setPriority(Thread.MIN_PRIORITY);
t2.setPriority(Thread.NORM_PRIORITY);
t3.setPriority(Thread.MAX_PRIORITY);
// Start threads
t1.start();
t2.start();
t3.start();
}
}
Explanation:
t1 has the minimum priority (1).
t2 has the default priority (5).
t3 has the maximum priority (10).
The program displays the priority of each thread when it runs.
Output (Example):
Thread-0 with priority: 1
Thread-1 with priority: 5
Thread-2 with priority: 10
Thread Priority Values:
Thread.MIN_PRIORITY: 1
Thread.NORM_PRIORITY: 5
Thread.MAX_PRIORITY: 10
Note:
Thread priority is a hint to the JVM and OS scheduler. The actual thread scheduling may still vary
depending on the operating system's thread scheduling policies.
Page | 119
22 Explain how to achieve suspending, resuming and stopping threads with an example program. 8
.
A Suspending, Resuming, and Stopping Threads in Java
In Java, the Thread class has methods to manage the state of a thread, such as suspending, resuming,
and stopping threads. However, the methods suspend(), resume(), and stop() are deprecated because
they are unsafe for handling thread synchronization and can lead to inconsistent states. Instead, it's
recommended to use alternative approaches, like using flags or wait()/notify() methods.
Let's go over the concepts and provide an example:
Suspending a Thread:
The suspend() method was used to pause a thread's execution, but it was deprecated because
it doesn't allow proper synchronization, leading to potential deadlocks.
Resuming a Thread:
The resume() method was used to resume a suspended thread, but it was also deprecated for
similar reasons.
Stopping a Thread:
The stop() method was used to stop a thread, but it can leave resources in an inconsistent
state. It is also deprecated for the same reason.
Safe Way to Manage Threads:
A safe way to manage threads is by using a flag to control the suspension and resumption of threads.
We can use wait(), notify(), or notifyAll() methods for better control over threads.
Example of Suspending, Resuming, and Stopping Threads Using a Flag:
class MyThread extends Thread {
private boolean suspended = false;
private boolean stopped = false;
public void run() {
while (!stopped) {
synchronized (this) {
while (suspended) {
try {
wait(); // Suspend the thread
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
System.out.println(Thread.currentThread().getName() + "
is running");
try {
Thread.sleep(1000); // Simulating some work
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
public synchronized void suspendThread() {
suspended = true;
}
public synchronized void resumeThread() {
suspended = false;
notify();
}
public synchronized void stopThread() {
stopped = true;
}
}
public class ThreadManagementExample {
public static void main(String[] args) throws
InterruptedException {
MyThread t1 = new MyThread();
Page | 120
t1.start();
Thread.sleep(3000);
t1.suspendThread();
System.out.println("Thread suspended");
Thread.sleep(2000);
t1.resumeThread();
System.out.println("Thread resumed");
Thread.sleep(3000);
t1.stopThread();
System.out.println("Thread stopped");
}
}
.
Page | 121