Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
5 views

OOP_Java_QB Ans

The document outlines key concepts and principles of Object-Oriented Programming (OOP) in Java, including encapsulation, inheritance, polymorphism, and abstraction, along with practical examples. It also covers essential Java topics such as data types, operators, control statements, and provides sample programs for matrix addition and temperature conversion. Additionally, it discusses Java's platform independence through the 'Compile once, run anywhere' principle, emphasizing the role of bytecode and the Java Virtual Machine (JVM).

Uploaded by

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

OOP_Java_QB Ans

The document outlines key concepts and principles of Object-Oriented Programming (OOP) in Java, including encapsulation, inheritance, polymorphism, and abstraction, along with practical examples. It also covers essential Java topics such as data types, operators, control statements, and provides sample programs for matrix addition and temperature conversion. Additionally, it discusses Java's platform independence through the 'Compile once, run anywhere' principle, emphasizing the role of bytecode and the Java Virtual Machine (JVM).

Uploaded by

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

Note

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

Sl. Questions/ Answers Mark


No. s
01. Explain the following operations with example. (i)<< (ii)>> (iii)>>> (iv)& 8
An (i) << (Left Shift Operator)
s The << operator shifts the bits of a number to the left by a specified number of positions. Each left
shift multiplies the number by 2.
Syntax:
number << positions
Example:
int num = 5;
int result = num << 2;
System.out.println(result); // Output: 20
Explanation:
The binary representation of 5 (00000101) becomes 00010100 after shifting 2 bits to the left. This is
equivalent to 5×22=205 \times 2^2 = 205×22=20.

(ii) >> (Right Shift Operator)


The >> operator shifts the bits of a number to the right by a specified number of positions. It preserves
the sign bit for signed numbers (arithmetic shift).
Syntax:
number >> positions
Example:
int num = 20;
int result = num >> 2;
System.out.println(result); //Output: 5

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.

(iii) >>> (Unsigned Right Shift Operator)


The >>> operator shifts the bits of a number to the right, filling the leftmost bits with zeros regardless
of the sign bit (logical shift).
Syntax:
number >>> positions
Example:
int num = -20;
int result = num >>> 2;
System.out.println(result); //Output: 1073741819
Explanation:
The leftmost bits are filled with zeros. For negative numbers, this results in a large positive number
since the sign bit is not preserved.

(iv) & (Bitwise AND Operator)


The & operator performs a bitwise AND operation between two numbers. It returns 1 for each bit
position where both operands have 1; otherwise, it returns 0.
Syntax:
number1 & number2
Example:
int num1 = 5;
int num2 = 3;
int result = num1 & num2;
System.out.println(result); //Output: 1
Explanation:
The bitwise AND operation compares each bit of num1 and num2. Only the last bit is 1 in both
numbers, so the result is 1.

02. Explain Objected Oriented Principles 7


An Object-Oriented Programming (OOP) is a programming paradigm based on the concept of objects,
s which can contain data (fields, also called attributes or properties) and methods (functions that operate
on the data). OOP promotes better software design by organizing code into reusable and modular
pieces.
The four fundamental principles of OOP are:

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;

2. Non-Primitive Data Types


Page | 7
Non-primitive (or reference) data types are objects and are created by the programmer. They include
classes, interfaces, arrays, and enums.
Key Features of Non-Primitive Data Types
 Default value: null.
 Can store more complex data.
 Examples include String, ArrayList, and custom classes.
Example:
String str = "Hello, Java!";
int[] arr = {1, 2, 3};

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.

05. Develop a Java program to covert Celsius temperature to Fahrenheit 6


An import java.util.Scanner;
s public class CelsiusToFahrenheit {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter temperature in Celsius: ");
double celsius = scanner.nextDouble();
double fahrenheit = (celsius * 9 / 5) + 32;

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.

Key Components Enabling Platform Independence


1. Java Bytecode:
o Bytecode is a low-level, platform-independent representation of the program.
o It ensures the compiled code can be executed on any platform.
2. Java Virtual Machine (JVM):
o JVMs are platform-specific implementations that interpret or compile bytecode into
native instructions.
o While the JVM is platform-dependent, the bytecode remains the same, ensuring
portability.
3. Java Runtime Environment (JRE):
o The JRE includes the JVM and necessary libraries, providing a runtime environment
for Java applications.

Example: How It Works


1. Writing and Compiling Code:
Write Java code (e.g., HelloWorld.java):
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Compile it using javac:
javac HelloWorld.java
This generates a platform-independent bytecode file: HelloWorld.class.
2. Running Bytecode on Different Platforms:
o Run the HelloWorld.class file using java HelloWorld on:
 Windows: The JVM for Windows interprets the bytecode.
 Linux: The JVM for Linux interprets the same bytecode.
 macOS: The JVM for macOS interprets the same bytecode.
The output will be:
Hello, World!

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

2. Relational (Comparison) Operators


Compare two values and return a boolean result.
Operator Operation Example
== Equal to a == b
!= Not equal to a != b
> Greater than a>b
< Less than a<b
>= Greater than or equal a >= b
<= Less than or equal 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();

Right Shift (>>) and Unsigned Right Shift (>>>)


Both operators shift bits to the right, but they behave differently with negative numbers.

1. Right Shift (>>)


 Shifts bits to the right, filling the leftmost bit with the sign bit (preserves the number's sign).
 Positive numbers are filled with 0 on the left.
 Negative numbers are filled with 1 on the left.

2. Unsigned Right Shift (>>>)


 Shifts bits to the right, filling the leftmost bits with 0 irrespective of the sign.
 Converts the binary representation into a positive number if the original number is negative.

Examples
Example Code for >> and >>>:
public class ShiftOperators {
public static void main(String[] args) {
int num1 = 32; // Positive number
int num2 = -32; // Negative number

// Right shift operator (>>)


System.out.println("num1 >> 2: " + (num1 >> 2));

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

08. Explain different lexical issues in JAVA. 7


An Lexical issues in Java refer to the challenges or considerations related to how the Java compiler
s processes and interprets the source code into meaningful tokens. These issues typically involve the
rules of syntax, keywords, and identifiers in the language. Below are some common lexical issues in
Java:

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.

3. Identifier Naming Rules


 Identifiers must follow specific rules:
o Can contain letters, digits, underscores (_), and dollar signs ($).
o Cannot start with a digit.
o Cannot match keywords or literals.
 Example:
 int 2number = 5; // Error: Identifiers cannot begin with a digit
 Issue: Misnamed identifiers can cause compile-time 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.

10. Number Formats


 Java supports various number formats, including decimal, octal, hexadecimal, and binary.
 Errors can occur when using incorrect formats or prefixes.
 Example:
 int num = 0128; // Error: Invalid octal literal (8 is not valid
in octal)
 Issue: Misuse of prefixes (e.g., 0 for octal, 0x for hexadecimal, 0b for binary) causes errors.

11. Character Set Compatibility


 Java source code should use the UTF-16 character set.
 Using unsupported characters or incorrect encodings may cause issues.
 Example:
 char ch = '©'; // Works only with proper encoding
 Issue: Improper encoding settings may lead to unrecognizable characters.

12. Tokenizing Issues


 Tokenization divides code into meaningful components (tokens) for the compiler.
Page | 13
 Ambiguities or mistakes in spacing, delimiters, or syntax can confuse the tokenizer.
 Example:
 System.out.println("Hello, world!); // Error: String literal
not closed
 Issue: Missing or mismatched delimiters disrupt tokenization.

09. Explain different types of if statements in JAVA 6


An In Java, if statements are used for decision-making. They allow a program to execute a block of code
s based on whether a specified condition evaluates to true or false. Java provides several variations of
the if statement to handle different scenarios. Here's an explanation of the different types:

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

3. if-else if-else Ladder


Used to test multiple conditions. The first condition that evaluates to true will have its block executed,
and the rest will be skipped.
Syntax:
if (condition1) {
// Code to execute if condition1 is true
} else if (condition2) {
// Code to execute if condition2 is true
} else {
// Code to execute if none of the above conditions are true
}
Example:
int marks = 85;
if (marks >= 90) {
System.out.println("Grade: A+");
} else if (marks >= 75) {
System.out.println("Grade: A");
} else if (marks >= 60) {
Page | 14
System.out.println("Grade: B");
} else {
System.out.println("Grade: C");
}

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

6. if with Logical Operators


Combining multiple conditions using logical operators like && (AND), || (OR), and ! (NOT).
Syntax:
if (condition1 && condition2) {
// Code to execute if both conditions are true
}
if (condition1 || condition2) {
// Code to execute if at least one condition is true
}
if (!condition) {
// Code to execute if the condition is false
}
Example:
int age = 25;
boolean hasID = true;
if (age >= 18 && hasID) {
System.out.println("You are allowed to enter.");
} else {
System.out.println("Entry denied.");
}

10. Discuss different versions of for-loop with examples. 7


An The for loop in programming is a control structure that repeats a block of code for a specified number
s of iterations. Different languages offer variations of the for-loop to suit different use cases. Below, we
discuss various versions of the for-loop with examples in Java (as you are working with Java projects):

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

2. Enhanced for Loop (for-each Loop)


This loop is used to iterate over elements in a collection or array. It's simpler and eliminates the need
for an index variable.
Syntax:
for (dataType variable : arrayOrCollection) {
// Code to execute
}
Example:
int[] numbers = {10, 20, 30, 40, 50};
for (int num : numbers) {
System.out.println("Number: " + num);
}
Output:
Number: 10
Number: 20
Number: 30
Number: 40
Number: 50

3. Infinite for Loop


By omitting the condition, a for loop can run infinitely. This requires a break statement to terminate it.
Syntax:
for (;;) {
// Infinite loop
}
Example:
for (int i = 0; ; i++) {
if (i == 5) break; // Exit the loop
System.out.println("Infinite loop, iteration: " + i);
}
Output:
Infinite loop, iteration: 0
Infinite loop, iteration: 1
Infinite loop, iteration: 2
Infinite loop, iteration: 3
Infinite loop, iteration: 4

4. Nested for Loops


A for loop inside another for loop is called a nested loop. This is useful for working with
multidimensional data.

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

5. for Loop with Multiple Variables


You can initialize and update multiple variables in the for loop.
Example:
for (int i = 0, j = 5; i < j; i++, j--) {
System.out.println("i = " + i + ", j = " + j);
}
Output:
i = 0, j = 5
i = 1, j = 4
i = 2, j = 3

6. for Loop with Break and Continue


The break statement terminates the loop, while continue skips the current iteration.
Example:
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // Skip iteration when i = 3
}
if (i == 5) {
break; // Exit loop when i = 5
}
System.out.println("i = " + i);
}
Output:
i=1
i=2
i=4

7. for Loop for Arrays


Using the traditional or enhanced for-loop, you can traverse arrays.
Example (Traditional for Loop):
int[] arr = {1, 2, 3, 4};
for (int i = 0; i < arr.length; i++) {
System.out.println("Element at index " + i + " is " + arr[i]);
}
Example (Enhanced for Loop):
String[] names = {"Alice", "Bob", "Charlie"};
for (String name : names) {
System.out.println("Hello, " + name + "!");
}

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.

12. Write a program to sort the elements using for loop. 7


An import java.util.Scanner;
s public class SortArray {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the number of elements: ");
Page | 18
int n = scanner.nextInt();
int[] arr = new int[n];
System.out.println("Enter the elements:");
for (int i = 0; i < n; i++) {
arr[i] = scanner.nextInt();
}
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (arr[i] > arr[j]) {
// Swap arr[i] and arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println("Sorted array in ascending order:");
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
}
}
}
13. Explain different types of arrays with simple program. 7
An In Java, arrays are used to store multiple values of the same type in a single variable. There are different
s types of arrays, which include:

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};

// Access and print the elements


System.out.println("Single-Dimensional Array:");
for (int i = 0; i < numbers.length; i++) {
System.out.println("Element at index " + i + ": " +
numbers[i]);
}
}
}
Output:
Single-Dimensional Array:
Element at index 0: 10
Element at index 1: 20
Element at index 2: 30
Element at index 3: 40
Element at index 4: 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.

16. Explain different promotion rules in JAVA. 7


An In Java, promotion refers to the automatic conversion of a smaller data type to a larger one when
s necessary, to prevent data loss. This happens implicitly when performing operations involving
variables of different data types.
Java has a set of promotion rules that dictate how types are promoted during expressions involving
arithmetic, comparisons, and assignments.
Here are the different promotion rules in Java:
1. Byte to Short or Int
 Promotion to int: When performing arithmetic operations, a byte or short is promoted to an
int because they can't hold large enough values for many operations.
 Example:
byte b1 = 10, b2 = 20;
int result = b1 + b2; // byte values promoted to int for
addition
 Reason: byte and short are smaller than int, and Java promotes them to int to ensure that the
result fits the larger type.

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.

3. Widening Primitive Conversion

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

4. Promotion in Expressions Involving Mixed Types


 When operands of different types are used in an expression, Java promotes the smaller type to
the larger type to avoid data loss.
 Example:
byte b = 10;
double d = 20.5;
double result = b + d; // byte is promoted to double for the
operation
System.out.println(result); // Output: 30.5
 Reason: Java promotes byte to int and then promotes int to double to ensure no data is lost
when performing the operation.

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

6. Character Promotion in String Concatenation


 When performing string concatenation (+ operator), all operands are promoted to strings. If
the operand is a primitive type (like int, char, etc.), it is converted to its string representation.
 Example:
char c = 'A';
String result = "Value: " + c; // char 'A' is converted to
string
System.out.println(result); // Output: Value: A

7. Boolean and Promotion


 No Promotion for Boolean: Booleans do not undergo promotion in Java. You cannot promote
a boolean to any other type, nor can you perform arithmetic or logical operations involving
boolean with other types.
 Example:
boolean b = true;
// This is invalid, since booleans cannot be promoted or used
with other data types
// int result = b + 10; // Error

Promotion in Type Casting


 Explicit Casting: When Java cannot automatically promote a type, you can use explicit
casting to convert a type.
 Example:
double d = 10.5;
int i = (int) d; // Explicit casting from double to int
System.out.println(i); // Output: 10 (decimal part is lost)
Page | 23
Summary of Promotion Rules
Type Conversion Promoted To
byte, short, char int
int long, float, or double (depending on the operation)
long float or double
float double
char int (when involved in arithmetic)
byte, short, char, int, float double (in expressions with doubles)
String Concatenation String
Booleans Cannot be promoted or involved in arithmetic

Key Points to Remember:


 Java promotes smaller types to larger types in arithmetic expressions to avoid data loss.
 Widening conversion occurs automatically (e.g., byte to int).
 Explicit casting is required when you need to convert from a larger type to a smaller one (e.g.,
double to int).
 Java does not promote booleans, and they cannot be involved in arithmetic operations.

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.

Sl. No Questions/ Answers Marks


01. What are constructors? Explain two types of constructors with example. 8
Ans Constructors in Java
A constructor is a special type of method in Java that is used to initialize objects. It is
automatically called when an object of a class is created. The constructor has the same name as
the class and does not have a return type, not even void. Its primary purpose is to set initial
values for the object’s attributes or perform any setup operations.
Types of Constructors
Java has two main types of constructors:
1. Default Constructor (No-Argument Constructor)
2. Parameterized Constructor

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;
}

public void display() {


System.out.println("Car Model: " + model);
System.out.println("Car Year: " + year);
Page | 25
}
}
public class Main {
public static void main(String[] args) { constructor
Car car1 = new Car("Tesla Model 3", 2023);
car1.display();
}
}
Output:
Car Model: Tesla Model 3
Car Year: 2023
In this example:
 The Car class has a parameterized constructor that takes two arguments (model and
year) to initialize the object with specific values.
 When a Car object is created, the constructor assigns the values "Tesla Model 3" and
2023 to the model and year attributes, respectively.

Key Differences Between Default and Parametrized Constructors


Feature Default Constructor Parameterized Constructor
Arguments No arguments Takes one or more arguments
Initialization Initializes fields with default Initializes fields with values passed
values (e.g., 0, null) during object creation
Use Case Used when no specific values are Used when initial values are provided
required during object creation
Implicit or Implicitly provided by Java (if no Explicitly defined by the programmer
Explicit constructor is defined)

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.

02. Explain static variable and static methods in JAVA. 7


Ans In Java, the static keyword can be applied to variables and methods. It makes them belong to the
class itself rather than to any particular instance of the class. Here’s a detailed explanation of
static variables and static methods:
1. Static Variable
A static variable is a variable that is shared among all instances (objects) of a class. It is also
known as a class variable. Instead of each instance having its own copy of the variable, the
static variable is stored in a common memory location, and all instances of the class refer to the
same variable.
Key Points:
 Single Copy: A static variable is shared by all instances of the class. There is only one
copy of the static variable, regardless of how many objects are created from the class.
 Accessed Through Class or Object: Static variables can be accessed directly through
the class name or through an object reference.
 Initialization: Static variables are initialized only once, at the time the class is loaded
into memory.
Example of Static Variable:
class Counter {
static int count = 0;
public Counter() {
count++;
}
public void displayCount() {
System.out.println("Count: " + count);

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;
}

static int subtract(int a, int b) {


return a - b;
}
}

public class Main {


public static void main(String[] args) {
// Calling static methods without creating an object
int sum = MathOperations.add(5, 3);
int diff = MathOperations.subtract(5, 3);

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


System.out.println("Difference: " + diff);
}
}
Explanation:
 The methods add() and subtract() are static methods in the MathOperations class.
 You can call them directly using the class name (MathOperations.add() or
MathOperations.subtract()) without creating an instance of the class.
Page | 27
 Static methods are useful for utility functions, like mathematical operations, that do not
need to rely on the state of any particular object.

Key Differences Between Static Variables and Static Methods:


Feature Static Variable Static Method
Belongs to Class (shared by all objects) Class (can be called without an
object)
Memory Allocated once for the entire class Created once per class, shared
Allocation among objects
Access Can be accessed through the class Can only access static variables and
or objects methods
Example Use Storing class-wide values like Utility functions, like Math
Case counters operations

When to Use Static Variables and Methods:


 Static Variables: Use static variables when you want to keep track of class-wide data
(e.g., counting instances of a class, storing common settings).
 Static Methods: Use static methods for operations that don't depend on object state,
such as utility methods (like mathematical calculations or helper methods).

03. Explain use of this in JAVA with example program. 8


Ans The this Keyword in Java
The this keyword refers to the current object in a class. It is used to distinguish between instance
variables and parameters with the same name, call other methods, chain constructors, or pass the
current object as an argument.

Uses of this Keyword:


1. Referring to instance variables: When parameters have the same name as instance
variables.
class Student {
String name;
int age;

public Student(String name, int age) {


this.name = name; // Refers to the instance variable
this.age = age; // Refers to the instance variable
}
}
2. Invoking methods: Calls another method of the same object.
class Calculator {
int a, b;

public void add() {


System.out.println(a + b);
}

public void calculate() {


this.add(); // Calling the add() method
}
}
3. Constructor chaining: Calls one constructor from another within the same class.
class Employee {
String name;

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;

public void transferOwnership(Person p) {


System.out.println(this.name + " transfers ownership
to " + p.name);
}
}
Summary:
 Referring to instance variables: this.name = name
 Calling methods: this.add()
 Constructor chaining: this("Unknown")
 Passing current object: this.transferOwnership()

04. Explain memory allocation and use of garbage collector in JAVA. 8


Ans Memory Allocation in Java
In Java, memory allocation is divided into different regions of memory based on the life cycle
and type of data. The Java Memory Model (JMM) defines how memory is managed during the
execution of a Java program, and the JVM (Java Virtual Machine) takes care of it.
Java memory is generally divided into the following areas:
1. Heap Memory
o The Heap is where all objects (instances of classes) are stored. When you create
a new object using new, the memory is allocated from the heap.
o The heap is divided into two main parts:
 Young Generation: Newly created objects are placed in the young
generation. This region is further divided into:
 Eden Space: Where new objects are created.
 Survivor Space (S0 & S1): Where objects that survive garbage
collection are moved.
 Old Generation: Objects that have been alive long enough (survived
multiple garbage collection cycles) are promoted to the old generation.
o The heap is dynamic: it grows and shrinks based on the object creation and
garbage collection activities.
2. Stack Memory
o The Stack is where method calls, local variables, and references to objects are
stored.
o Each time a method is called, a new stack frame is created and pushed onto the
stack. The stack stores primitive data types (e.g., int, char) and references to
objects in the heap.
o Once the method execution is complete, its stack frame is removed, and the
memory is freed.
3. Method Area
o The Method Area is where the class definitions, method data, and constant pool
are stored. It contains class-level information like method code, static variables,
and other meta-data.
o All classes loaded by the JVM are stored in this area.
4. Program Counter (PC) Register
o The Program Counter Register keeps track of the current executing
instruction.
Garbage Collection in Java
Garbage Collection (GC) is the process of automatically identifying and reclaiming memory that
is no longer in use or is unreachable. Java has an automatic garbage collection system, which

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

public static void main(String[] args) {


int num = 10;
System.out.println("Before method call: " + num);

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

Key Differences Between Call by Value and Call by Reference:


Feature Call by Value Call by Reference
What is passed A copy of the actual value is passed to A reference (memory address) to
the method. the actual object is passed.
Effect on Changes made to the parameter inside Changes made to the object
original variable the method do not affect the original inside the method affect the
variable. original object.

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.

08. Explain nested and inner classes 8


Ans Nested Classes in Java
In Java, nested classes are classes defined within another class. There are two main types of
nested classes:
1. Inner Class
2. Static Nested Class

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.

2. Static Nested Class


A static nested class is a class defined within another class, but it is declared with the static
keyword. Static nested classes do not have access to instance variables and methods of the outer
class; they can only access static members of the outer class. They are not associated with an
instance of the outer class and can be instantiated without an outer class object.
Example of Static Nested Class:
class OuterClass {
static String staticOuterField = "Static Outer Class Field";
static class StaticNestedClass {
void display() {
System.out.println("Accessing from Static Nested
Class: " + staticOuterField);
}
}
}
public class Main {
public static void main(String[] args) { instance
OuterClass.StaticNestedClass nested = new
OuterClass.StaticNestedClass();
nested.display();
}
}
Output:
Accessing from Static Nested Class: Static Outer Class Field
Explanation:
 StaticNestedClass is a static class, so it can be instantiated without needing an instance
of the OuterClass.
 It has access to the static members of the outer class, such as staticOuterField.

Key Differences Between Inner Class and Static Nested Class:


Aspect Inner Class Static Nested Class
Access to Outer Can access both static and instance Can access only static members
Class members of the outer class
Instance Requires an instance of the outer class Can be instantiated without an
Requirement outer class instance
Use Case Used when the inner class needs to Used when the inner class only
interact with instance members of the needs static data from the outer
outer class class

3. Local Inner Class


A local inner class is a class defined within a method of the outer class. It can access final or
effectively final local variables of the method where it is defined.
Example of Local Inner Class:
class OuterClass {
void display() {
final String localVar = "Local Variable in Outer Class";

// Local Inner Class


class LocalInnerClass {
void show() {
System.out.println(localVar);
}
}

LocalInnerClass localInner = new LocalInnerClass();

Page | 36
localInner.show();
}
}

public class Main {


public static void main(String[] args) {
OuterClass outer = new OuterClass();
outer.display(); // Local inner class is used here
}
}
Output:
Local Variable in Outer Class
Explanation:
 The LocalInnerClass is defined within the display() method of the OuterClass and can
access the localVar local variable, which is declared as final (or effectively final).

4. Anonymous Inner Class


An anonymous inner class is a class without a name that is defined and instantiated in a single
expression. It is typically used to implement interfaces or extend classes in a concise manner.
Example of Anonymous Inner Class:
interface Greeting {
void greet();
}

public class Main {


public static void main(String[] args) {
// Anonymous inner class implementing the Greeting
interface
Greeting greeting = new Greeting() {
public void greet() {
System.out.println("Hello from Anonymous Inner
Class!");
}
};

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.

09. Distinguish between method overloading and method overriding. 8


Ans

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

Recursive Program to Find nth Fibonacci Number


public class Fibonacci {
public static int fibonacci(int n) {
if (n <= 1) {
return n;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
public static void main(String[] args) {
int n = 6; // Example: Find the 6th Fibonacci number
System.out.println("Fibonacci number at position " + n +
" is: " + fibonacci(n));
}
}
Output:
Fibonacci number at position 6 is: 8
Explanation:
 The fibonacci(int n) method is defined recursively.

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

public void display() { // Public method


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

2. protected Access Specifier:


 Visibility: The protected access specifier allows access to members within the same
package and by subclasses (including subclasses in different packages).
 Scope: It is more restrictive than public, but still allows for some level of accessibility.
 Usage: Use protected when you want to allow access within the package and also to
subclasses, even if they are in different packages.
Behavior:
 Class: A class cannot be declared protected. Only members (fields and methods) of the
class can be protected.
 Method: A protected method can be called within the same package or by subclasses.
 Field: A protected field can be accessed within the same package or by subclasses.
Example:
class Parent {
protected int num; // Protected field
}

class Child extends Parent {


public void display() {
System.out.println("Accessing protected field: " + num);
}

Page | 40
}

3. private Access Specifier:


 Visibility: The private access specifier restricts access to the same class only. Members
declared as private cannot be accessed outside their own class.
 Scope: It is the most restrictive access level.
 Usage: Use private when you want to encapsulate data and ensure that the field or
method is hidden from the outside world, providing controlled access through getters
and setters if necessary.
Behavior:
 Class: A class cannot be declared private. Only members of the class (fields and
methods) can be private.
 Method: A private method can only be accessed within the same class.
 Field: A private field can only be accessed within the same class.
Example:
class Example {
private int num; // Private field

private void display() { // Private method


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

4. Default (Package-Private) Access Specifier:


 Visibility: If no access specifier is provided (i.e., no keyword is used), it is called
package-private or default access. This means that the class members are accessible
only within the same package.
 Scope: More restrictive than protected, but allows access within the same package.
 Usage: Use default access when you want members to be accessible only within the
same package, but not by classes from other packages.
Behavior:
 Class: A class with default access is visible only within its package.
 Method: A method with default access can be accessed only within its package.
 Field: A field with default access can be accessed only within its package.
Example:
class Example {
int num; // Default (package-private) field

void display() { // Default (package-private) method


System.out.println("This is a default access method.");
}
}

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.

2. Old Generation (Tenured Generation):


The Old Generation stores objects that have existed for a long time and survived several
rounds of garbage collection in the Young Generation. These objects are typically larger and
have a longer lifetime.
Garbage Collection in Old Generation:
 Major GC (Full GC): When the Old Generation is full or needs garbage collection, a
Full GC or Major GC is triggered. This type of garbage collection is slower and
involves both the Old and Young Generations.
Page | 42
 Major GCs are more expensive in terms of performance because they involve scanning a
larger memory area and can stop the application for a longer time.
Typical Characteristics:
 Long-lived objects like application-level data (e.g., caches, connection pools, and
singleton objects) tend to be placed in the Old Generation.
 Garbage collection here is less frequent compared to the Young Generation because the
objects are expected to live longer.

3. Permanent Generation / Metaspace:


In older versions of Java (before Java 8), there was a Permanent Generation that held the
JVM metadata, such as class definitions, method definitions, and static fields. It was a part of the
heap but managed separately. The Permanent Generation could cause OutOfMemoryError if
it ran out of space, especially when there were too many loaded classes.
In Java 8 and later, the Permanent Generation was replaced by Metaspace, which is now
part of native memory (not the heap). Metaspace holds the JVM metadata (like classes and
methods), but it is not limited by a fixed size, unlike the Permanent Generation.
Garbage Collection in Metaspace:
 When class metadata is no longer in use, it is collected during a Full GC. Metaspace is
managed by the operating system's native memory allocator.
Typical Characteristics:
 This area holds the metadata of the classes, methods, and other structures used by the
JVM to run the program.
 It is generally not part of the heap and does not undergo frequent garbage collection.

Memory Management in Java:


 Heap Memory: The heap is where all objects in Java are stored. It is divided into Young
and Old generations for efficient garbage collection.
 Stack Memory: In addition to the heap, local variables and method call frames are
stored in the stack memory. The stack is not subject to garbage collection.

Garbage Collection Process Overview:


1. Young Generation (Minor GC):
o The Eden Space is full of new objects.
o Garbage collection is triggered and objects that are still referenced are moved to
the Survivor Spaces.
o If objects survive enough collections in Survivor Spaces, they are promoted to
the Old Generation.
2. Old Generation (Major/Full GC):
o When the Old Generation is full, a Full GC is triggered.
o This involves a longer, more expensive process of cleaning up both the Young
Generation and Old Generation.
3. Permanent Generation / Metaspace:
o In older JVM versions, garbage collection would also clean up the Permanent
Generation, but in Java 8+, it cleans up Metaspace during Full GC.

Summary Table of Generations in the Java Heap:


Generation Contains Type of Collection Common
Garbage Frequency Objects
Collection
Young Newly created Minor GC Frequent Local variables,
Generation objects, Eden Space, (short-lived temporary data
Survivor Spaces objects)
(S0, S1)
Old Generation Long-lived objects Major GC Infrequent Application-
(Full GC) (long-lived level data,
objects) cached data

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
}

// Main method (entry point)


public static void main(String[] args) {
ClassName obj = new ClassName("John", 25);
obj.display(); // Instance method
ClassName.staticMethod(); // Static method
}
}
Explanation:
 Instance Variables: Store object data (name, age).
 Constructor: Initializes object values.
 Methods: Define behaviors (instance or static).
 Static Method: Belongs to the class, can be called without an object.
 Main Method: Entry point to create and use objects.
Output:
Name: John
Age: 25
Static method
This structure defines the basic layout of a class in Java.

16. Outline the following keywords with an example:


i. this 6
ii. static
Ans i. this Keyword
The this keyword in Java is a reference variable used to refer to the current instance of a class. It
is primarily used in the following scenarios:
1. To refer to the current object.
2. To differentiate between instance variables and local variables when they have the same
name.
3. To invoke the current class constructor.
Example Program Using this Keyword:
class Person {
String name;
int age;
public Person(String name, int age) {
// Using 'this' to refer to the instance variables
this.name = name;
this.age = age;
}
public void display() {
System.out.println("Name: " + this.name);
System.out.println("Age: " + this.age);
}
}
public class Main {
public static void main(String[] args) {
// Creating an object of Person class
Person person1 = new Person("John", 25);
person1.display();
}
}
Output:
Name: John
Age: 25
Explanation:
 In the constructor of Person, the this keyword is used to refer to the current instance's
variables (name and age) to avoid confusion with the method parameters that have the
same names.
Page | 45
 In the display() method, this.name and this.age are used to explicitly refer to the instance
variables of the current object.

ii. static Keyword


The static keyword in Java is used for memory management. It can be applied to variables,
methods, blocks, and inner classes. Here’s how the static keyword is used:
1. Static Variables: Shared among all instances of a class. There is only one copy of a
static variable, no matter how many objects of the class are created.
2. Static Methods: Can be called without creating an instance of the class. A static method
can only access other static members (variables and methods) of the class.
3. Static Blocks: Used for static initialization of a class.
4. Static Classes: Nested classes can be declared static, meaning they don't need an
instance of the outer class.
Example Program Using static Keyword:
class Counter {
static int count = 0;
public Counter() {
count++;
}
public static void displayCount() {
System.out.println("Current count: " + count);
}
}
public class Main {
public static void main(String[] args) {
Counter obj1 = new Counter();
Counter obj2 = new Counter();
Counter obj3 = new Counter();
Counter.displayCount();
}
}
Output:
Current count: 3
Explanation:
 Static Variable: The count variable is static, meaning it is shared among all instances of
the Counter class. Each time a new object is created, the count is incremented.
 Static Method: The displayCount() method is static, so it can be called without creating
an instance of the Counter class.
 The displayCount() method prints the value of the count, which reflects the number of
objects created.

Key Differences Between this and static:

Aspect this Keyword static Keyword


Usage Refers to the current instance of the Defines class-level variables, methods,
class. or blocks.
Context Used in instance methods and Used in static methods, variables, and
constructors. blocks.
Access Cannot be used in static context (i.e., Can be accessed without creating an
static methods). object of the class.
Scope Refers to a specific instance. Shared among all instances of the class.
17. Develop a Java program to create a class called ‘Employee’ which contains ‘name’,
‘designation’, ‘empid’ and ‘basic salary’ as instance variables and read() and write() as 10
methods. Using the class, read and write five employee information from main() method.
Ans import java.util.Scanner;
class Employee {
// Instance variables
String name;

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.

Key Differences Between Default and Parameterized Constructors:


Aspect Default Constructor Parameterized Constructor
Parameters Does not take any parameters. Takes parameters to initialize the
object with specific 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();

// Creating object using parameterized constructor


Student student2 = new Student("Alice", 20);
student2.display();
}
}
Output:
Name: Unknown
Age: 18
Name: Alice
Age: 20
Explanation:
 The program demonstrates constructor overloading: one constructor initializes with
default values, and another initializes with values passed as arguments.

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.

Sl. No. Questions/Answers Marks


01. Which are the restrictions present for static declared methods? 8
Ans In Java, static methods have certain restrictions due to their nature of being associated with the
class itself rather than with specific instances of the class. Below are the key restrictions:
1. Cannot Access Instance Variables and Methods
 Static methods can only directly access other static variables and static methods.
They cannot directly access instance variables or instance methods (non-static
members) because instance variables and methods require an object of the class to be
accessed.
Example:
class Example {
int instanceVar = 10;
static int staticVar = 20;

static void staticMethod() {


System.out.println(instanceVar);
System.out.println(staticVar);
}
}
2. Cannot Use this or super Keywords
 In static methods, you cannot use the this keyword to refer to the current instance, nor
can you use the super keyword to refer to the parent class instance. Since static
methods belong to the class and not an instance, these references are invalid.
Example:
class Example {
static void staticMethod() {
System.out.println(this);
System.out.println(super);
}
}
3. Cannot Be Overridden (But Can Be Hiding)
 Static methods cannot be overridden in the same way that instance methods can.
They can be hidden by another static method with the same name in a subclass. This is
because static methods are resolved at compile time, and method resolution for static
methods depends on the reference type, not the object type.
Example:
class Parent {
static void staticMethod() {
System.out.println("Parent Static Method");
}
}

class Child extends Parent {


static void staticMethod() {
System.out.println("Child Static Method");
}
}

public class Main {


public static void main(String[] args) {
Parent p = new Child();
p.staticMethod(); // Output: Parent Static Method (not
Child)
Page | 50
}
}
4. Cannot Be Used to Access Instance Members
 Static methods cannot directly access instance members (variables and methods) of the
class because they are tied to the class itself and not to an instance of the class. To
access instance members from a static method, an object must be created.
Example:
class Example {
int instanceVar = 100;
static void staticMethod() { access instance variable
Example obj = new Example();
System.out.println(obj.instanceVar);
}
}
5. Cannot Be Used for Polymorphism
 Static methods cannot participate in polymorphism in the same way instance methods
do. They are resolved at compile-time based on the reference type, not the object type.
Example:
class Parent {
static void staticMethod() {
System.out.println("Parent static method");
}
}
class Child extends Parent {
static void staticMethod() {
System.out.println("Child static method");
}
}
public class Main {
public static void main(String[] args) {
Parent p = new Parent();
p.staticMethod();
Parent c = new Child();
c.staticMethod();
}
}
Summary of Restrictions:
 Cannot access instance variables/methods directly.
 Cannot use this or super keywords.
 Cannot be overridden (static methods can be hidden).
 Cannot access instance members without creating an object.
 Cannot participate in polymorphism like instance methods.

02. Explain how interface is used to achieve multiple Inheritances in Java. 7


Ans In Java, multiple inheritance refers to the ability of a class to inherit from more than one class.
Java does not support multiple inheritance through classes directly (to avoid ambiguity), but it
supports multiple inheritance through interfaces.
Using Interfaces for Multiple Inheritance:
Java allows a class to implement multiple interfaces. This way, a class can inherit behavior
from multiple sources, avoiding the problems associated with multiple inheritance in classes.
 An interface is a contract that defines a set of methods a class must implement, but it
does not provide the actual implementation.
 A class can implement multiple interfaces, thereby inheriting the abstract behavior
defined in those interfaces.
Example: Achieving Multiple Inheritance Through Interfaces
Step-by-Step Example:
interface Animal {
void eat();
}
Page | 51
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.");
}
}
public class Main {
public static void main(String[] args) {
Eagle eagle = new Eagle();
eagle.eat();
eagle.fly();
}
}
Output:
Eagle is eating.
Eagle is flying.
Explanation:
 Interfaces: Animal and Bird are interfaces that define the methods eat() and fly().
 Class Eagle: The Eagle class implements both the Animal and Bird interfaces, thus
inheriting the behaviors from both interfaces.
 The Eagle class provides concrete implementations of the methods eat() and fly(),
fulfilling the contract of both interfaces.
Key Points:
1. Multiple Inheritance: Java does not allow a class to inherit from more than one class,
but a class can implement multiple interfaces, thus achieving multiple inheritance.
2. Avoiding Ambiguity: Since interfaces only define abstract methods (until Java 8,
when default methods were introduced), there is no issue of ambiguity that can occur
with multiple inheritance in classes.
3. Default Methods (Java 8 and later): Java 8 introduced default methods in interfaces,
allowing interfaces to provide method implementations. This further improves
flexibility by allowing shared behavior across multiple classes.
Example with Default Methods:
interface Animal {
default void eat() {
System.out.println("Animal is eating");
}
}
interface Bird {
default void fly() {
System.out.println("Bird is flying");
}
}
class Eagle implements Animal, Bird {
public void eat() {
System.out.println("Eagle is eating");
}
public void fly() {
System.out.println("Eagle is soaring");
}
}
public class Main {
public static void main(String[] args) {
Eagle eagle = new Eagle();
eagle.eat(); // Overridden method
Page | 52
eagle.fly(); // Overridden method
}
}
Output:
Eagle is eating
Eagle is soaring
Conclusion:
 Multiple inheritance via interfaces allows a class to inherit behavior from multiple
sources.
 Interfaces only define the contract, and a class that implements them provides the
actual implementation.
 Java avoids the problems of traditional multiple inheritance (like method conflicts) by
allowing only interfaces to be inherited and not classes.
Let me know if you'd like more clarification!

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

public class Main {


public static void main(String[] args) {
Eagle eagle = new Eagle();
eagle.eat(); // From Animal interface
eagle.fly(); // From Bird interface
}
}
Output:
Eagle is eating.
Eagle is flying.
Explanation:
1. Interfaces:
o Animal interface defines the abstract method eat().
o Bird interface defines the abstract method fly().
2. Class Implementation:
Page | 53
o The Eagle class implements both the Animal and Bird interfaces, thereby
inheriting both the eat() and fly() methods.
o The class provides concrete implementations for both methods.
3. Multiple Inheritance:
o By implementing both interfaces, the Eagle class has inherited behaviors from
both Animal and Bird, which is an example of multiple inheritance through
interfaces.
Key Benefits of Using Interfaces for Multiple Inheritance:
1. Avoiding Ambiguity:
o Java does not allow multiple inheritance through classes to avoid the "diamond
problem" (ambiguity when two parent classes have methods with the same
name). However, interfaces do not have this problem because they only define
method signatures (abstract methods) without implementing them.
2. Flexibility:
o A class can implement any number of interfaces, allowing it to inherit behavior
from multiple sources, promoting flexibility in design.
3. Decoupling:
o Interfaces allow a class to adhere to multiple contracts, making it easier to
change or extend the class's behavior without affecting other parts of the
program.
Java 8 Features (Default Methods in Interfaces):
From Java 8, interfaces can contain default methods with method implementations. This
feature allows interfaces to provide default behavior, making them even more flexible in terms
of code reuse.
Example with Default Methods:
interface Animal {
default void eat() {
System.out.println("Animal is eating.");
}
}
interface Bird {
default void fly() {
System.out.println("Bird is flying.");
}
}
class Eagle implements Animal, Bird {
public void eat() {
System.out.println("Eagle is eating.");
}
public void fly() {
System.out.println("Eagle is soaring.");
}
}
public class Main {
public static void main(String[] args) {
Eagle eagle = new Eagle();
eagle.eat();
eagle.fly();
}
}
Output:
Eagle is eating.
Eagle is soaring.
Conclusion:
 Java uses interfaces to achieve multiple inheritance, as a class can implement multiple
interfaces.
 Interfaces define the methods that classes must implement, and by implementing
multiple interfaces, a class can inherit behavior from multiple sources.

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!

04. Write a java program to extend interface assuming suitable data. 8


Ans interface Person {
void setName(String name);
String getName();
}
interface Employee extends Person {
void setEmployeeId(int id);
int getEmployeeId();
}
class Manager implements Employee {
private String name;
private int employeeId;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setEmployeeId(int id) {
this.employeeId = id;
}
public int getEmployeeId() {
return employeeId;
}
}
public class Main {
public static void main(String[] args) {
Manager manager = new Manager();
manager.setName("John Doe");
manager.setEmployeeId(101);
System.out.println("Manager Name:”+ manager.getName());
System.out.println("Manager ID:"+
manager.getEmployeeId());
}
}
05. What is single level inheritance? Explain with suitable example. 7
Ans Single Level Inheritance in Java
Single Level Inheritance is a type of inheritance where a class (child or subclass) inherits
properties and methods from one parent class (superclass). The child class can reuse the code in
the parent class and can also add its own specific features.
In single-level inheritance, the subclass extends a single superclass.
Example of Single Level Inheritance:
class Animal {
// Instance variable
String name;
public Animal(String name) {
this.name = name;
}
public void speak() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
Page | 55
public Dog(String name) {
super(name);
}
public void speak() {
System.out.println(name + " barks");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.speak();
}
}
Output:
Buddy barks
Explanation:
1. Parent Class (Animal):
o Contains a variable name and a method speak().
2. Child Class (Dog):
o Inherits from the Animal class using the extends keyword.
o The Dog class constructor calls the parent class constructor using super(name).
o The speak() method in the Dog class overrides the parent class method to
provide specific behavior for dogs.
Key Points:
 In single-level inheritance, only one parent class is involved.
 The child class inherits attributes and methods from the parent class.

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.

07. Explain inheritance and polymorphism features of Java. 8


Ans Inheritance in Java
Inheritance is one of the fundamental concepts of object-oriented programming (OOP) and
allows a new class (child class) to inherit properties and behaviors (methods) from an existing
class (parent class). This helps in code reuse and establishes a relationship between the parent
and child classes.
Key Features of Inheritance:
1. Code Reusability: A child class can reuse the methods and fields of the parent class.
2. Method Overriding: A child class can override the methods of the parent class to
provide specific implementations.
3. Extending a Class: Inheritance is implemented using the extends keyword in Java.
Syntax:
class Parent {
public void show() {
System.out.println("Parent class method");
Page | 57
}
}
class Child extends Parent {
public void display() {
System.out.println("Child class method");
}
}
public class Main {
public static void main(String[] args) {
Child childObj = new Child();
childObj.show();
childObj.display();
}
}
Output:
Parent class method
Child class method
Explanation:
 The Child class extends the Parent class, inheriting the show() method.
 The child class can access both its own methods (display()) and the inherited method
(show()).

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.

Key Differences between Inheritance and Polymorphism:


Feature Inheritance Polymorphism
Definition A mechanism to inherit properties A mechanism to represent multiple
and methods from another class. forms of an object.
Purpose Reuse code and establish an "is-a" Allow one interface to represent
relationship. different types.
Types Single, Multiple, Multilevel Compile-time (Method Overloading),
Inheritance. Runtime (Method Overriding).
Achieved extends keyword for classes and Method Overloading and Method
By interfaces. Overriding.
Example class Dog extends Animal Method Overriding in a subclass.
08. Explain method overriding with suitable example. 7
Ans Method overriding in Java occurs when a subclass provides a specific implementation of a
method that is already defined in its superclass. The method in the subclass must have the
same signature (method name, return type, and parameters) as the method in the superclass.
The purpose of method overriding is to achieve runtime polymorphism, where the subclass
can define its own version of a method to be executed, even when the method is called using a
reference of the superclass type.
Key Points about Method Overriding:
1. The method in the subclass must have the same name, return type, and parameters as
the method in the superclass.
2. @Override annotation is optional but recommended, as it helps the compiler to verify
that you are correctly overriding the method.
3. The overridden method in the subclass can provide a different implementation of the
method defined in the superclass.
4. If a subclass does not override a method, the superclass method is called by default.
5. Access modifiers in the overridden method can be the same or more permissive than
the original method in the superclass (but not more restrictive).

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.

Example: Using super Keyword


class Animal {
String name;
public Animal(String name) {
this.name = name;
}
public void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void sound() {
super.sound();
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Bulldog");
dog.sound();
System.out.println("Dog's name is: " + dog.name);
}
}
Output:
Animal makes a sound
Dog barks
Dog's name is: Bulldog

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.

10. Write a single program to implement inheritance and polymorphism in java. 8


Ans 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 InheritancePolymorphismExample {
public static void main(String[] args) {
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.sound();
myCat.sound();
}
}
11. Explain concept of nesting of interface. 7
Ans In Java, nesting of interfaces refers to the practice of defining one interface inside another.
This concept allows you to group related interfaces together, improving organization and
making the code more modular and easier to understand.
There are two main types of nested interfaces:
1. Static Nested Interface:
o A static nested interface is an interface that is declared inside another class or
interface.
o Being static, it can be accessed without an instance of the outer class or
interface.
o It is typically used when the nested interface is closely related to the outer class
or interface but does not depend on its instance.
Example:
class OuterClass {
interface NestedInterface {
void display();
}
}
class ImplementingClass implements OuterClass.NestedInterface {
public void display() {
System.out.println("Display method implementation.");
}
}
2. Non-static Nested Interface (also called Inner Interface):
o A non-static nested interface is an interface declared inside a class and is
implicitly associated with an instance of the outer class.
o It cannot be accessed without creating an instance of the outer class.
Example:
class OuterClass {
Page | 62
interface NestedInterface {
void display();
}
}
class OuterClassImpl {
class InnerClass implements OuterClass.NestedInterface {
public void display() {
System.out.println("Display method
implementation.");
}
}
}
Benefits of Nesting Interfaces:
 Organization: Nesting interfaces helps group logically related interfaces together,
making the code more organized.
 Encapsulation: Nested interfaces can be hidden from the outside world if they are not
intended to be accessed externally.
 Code readability: By nesting interfaces within classes or other interfaces, the structure
of the code becomes clearer.

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.

Sl. No. Questions/ Answers Marks


01. Which are the ways to access package from another package? Explain with example. 8
Ans In Java, packages are used to group related classes and interfaces. To access classes, methods,
or variables from one package in another package, you need to follow some specific rules. Here
are the different ways to access classes from another package:
Ways to Access Classes from Another Package
1. Using Fully Qualified Name
2. Using import Statement
o Single-Class Import
o Package Import
o Wildcard Import

1. Using Fully Qualified Name


You can access a class in another package by specifying its full package name along with the
class name. This approach does not require the import statement.
Example: Using Fully Qualified Name
Package 1: package1
package package1;
public class Person {
public void greet() {
System.out.println("Hello from Person class in
package1");
}
}
Package 2: package2
package package2;
public class Main {
public static void main(String[] args) {
package1.Person person = new package1.Person();
person.greet();
}
}
Output:
Hello from Person class in package1
Employee class in package1

2. Using import Statement


Instead of using fully qualified names, Java allows you to import classes or entire packages
into your current class using the import statement. This makes the code cleaner and more
readable.
Types of import Statements:
 Single-Class Import: Import a specific class from another package.
 Package Import: Import all classes from a package.
 Wildcard Import: Import all classes from a package using *.
Single-Class Import
The single-class import allows you to import a specific class from another package.
Example: Single-Class Import
Package 1: package1
package package1;
public class Person {
public void greet() {

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

2.2. Package Import


You can import all the classes from a specific package by importing the package. However, you
need to be aware that this imports all classes within the package, and not any sub-packages.
Example: Package Import
Package 1: package1
package package1;
public class Person {
public void greet() {
System.out.println("Hello from Person class in
package1");
}
}
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) {
Person person = new Person();
person.greet();
Employee employee = new Employee();
employee.job();
}
}
Output:
Hello from Person class in package1
Employee 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();

Employee employee = new Employee();


employee.job();
}
}
Output:
Hello from Person class in package1
Employee class in package1

02. How to add new class to a package? Explain with an example. 8


Ans In Java, a package is used to group related classes and interfaces, providing modularity and
avoiding name conflicts. To add a new class to a package, you need to follow these steps:
1. Declare the package at the top of the class file using the package keyword.
2. Create the new class within the package.
Syntax to Declare a Class in a Package:
package packageName; // Declare the package

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

Example: Adding a New Class to a Package


Let’s create a package called company and add two classes: Employee and Manager.
Step 1: Create the Package and Class Employee
File: Employee.java
package company;
public class Employee {
String name;
int id;
public Employee(String name, int id) {
this.name = name;
this.id = id;
}
public void display() {
System.out.println("Employee Name: " + name);
System.out.println("Employee ID: " + id);
}
}
Step 2: Create Another Class Manager in the Same Package
File: Manager.java
Page | 73
package company;
public class Manager extends Employee {
String department;
public Manager(String name, int id, String department) {
super(name, id);
this.department = department;
}
public void display() {
super.display(); // Calling Employee's display method
System.out.println("Department: " + department);
}
}
Step 3: Create the Main Class to Use These Classes
File: Main.java
import company.Employee;
import company.Manager;
public class Main {
public static void main(String[] args) {
Employee emp = new Employee("John Doe", 101);
Manager mgr = new Manager("Jane Smith", 102, "HR");
emp.display();
mgr.display();
}
}
Directory Structure:

project_folder/
├── company/
│ ├── Employee.java
│ ├── Manager.java
├── Main.java

Step 4: Compile and Run:


1. Compile all the files:
2. javac company/Employee.java company/Manager.java Main.java
3. Run the program:
4. java Main
Output:
Employee Name: John Doe
Employee ID: 101
Employee Name: Jane Smith
Employee ID: 102
Department: HR

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

Example: Creating and Accessing a Package


1. Create a Package (e.g., com.myapp.utility)
 Step 1: Create a directory structure com/myapp/utility/ on your system.
 Step 2: Create a Java file with the package declaration in the utility folder.
File: Hello.java (in com/myapp/utility/ folder)
package com.myapp.utility;
public class Hello {
public void sayHello() {
System.out.println("Hello from the com.myapp.utility
package!");
}
}
2. Access the Package from Another Class
 Step 3: Create another Java file to access and use the class Hello from the package
com.myapp.utility.
File: Main.java (in the root directory or any other directory)
import com.myapp.utility.Hello;
public class Main {
public static void main(String[] args) {
Hello hello = new Hello();
hello.sayHello();
}
}
Steps to Compile and Run the Program
1. Compile the package:
o Navigate to the root directory where the com folder is located.
o Compile the Hello.java file by running the command:
o javac com/myapp/utility/Hello.java
2. Compile the Main Class:
o After compiling Hello.java, compile Main.java (from the root directory):
o javac Main.java

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

05. How do you import a package? Explain. 7


Ans To use classes and interfaces from a package in your program, you need to import them. The
import statement allows you to access the desired classes/interfaces from the package.
Types of Import in Java
1. Explicit Import:
o Import a specific class or interface from a package.
o Syntax:
o import package_name.ClassName;
o Example:
o import java.util.Scanner; // Importing only the Scanner class
2. Wildcard Import:
o Import all the classes and interfaces from a package using the *.
o Syntax:
o import package_name.*;
o Example:
o import java.util.*; // Imports all classes in java.util, like Scanner, ArrayList,
etc.
Example Program
Using an Explicit Import:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Enter your name:");
String name = scanner.nextLine();
System.out.println("Hello, " + name);
}
}
Using a Wildcard Import:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // Scanner
is part of java.util
System.out.println("Enter a number:");
int number = scanner.nextInt();
System.out.println("You entered: " + number);
}
}
Points to Remember:
1. If a class is in the java.lang package (e.g., String, Math, System), it does not need to be
imported because it is automatically available.
2. You cannot use the wildcard (*) to import classes from sub-packages; you must
explicitly import them.
o Example: import java.util.*; does not import classes from java.util.stream.
Example with User-defined Package
If you have a user-defined package (e.g., shapes), you can import it like this:
Circle.java (inside shapes package):
package shapes;
public class Circle {

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());
}
}

06. Write a note on access protection in Java. 8


Ans In Java, access protection (or access control) determines the visibility and accessibility of
classes, methods, fields, and constructors within a program. Java uses access modifiers to
implement access protection, ensuring proper encapsulation and safeguarding data from
unintended interference.

Access Modifiers in Java


Java provides four types of access levels using modifiers:
Modifier Class Package Subclass (Other Packages) Global (Other Packages)
public
protected
default
private
1. public:
o Accessible everywhere.
o No restriction on visibility.
o Example:
public class PublicExample {
public void show() {
System.out.println("Public method");
}
}
2. protected:
o Accessible within the same package and subclasses in other packages.
o Used to provide controlled access in inheritance.
o Example:
protected class ProtectedExample {
protected void show() {
System.out.println("Protected method");
}
}
3. Default (No Modifier):
o Accessible only within the same package.
o Known as package-private access.
o Example:
class DefaultExample {
void show() {
System.out.println("Default method");
}
}
Page | 78
4. private:
o Accessible only within the same class.
o Used to enforce the highest level of encapsulation.
o Example:
public class PrivateExample {
private void show() {
System.out.println("Private method");
}
}

Example Program Demonstrating Access Protection


package package1;
public class AccessExample {
public int publicField = 10;
protected int protectedField = 20;
int defaultField = 30; // No modifier
private int privateField = 40;
public void showPublic() {
System.out.println(“Public method”);
}
protected void showProtected() {
System.out.println("Protected method");
}
void showDefault() {
System.out.println("Default method");
}
private void showPrivate() {
System.out.println("Private method");
}
}

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();

// Call the methods


myDog.sound(); // Output: Dog barks
myDog.eat(); // Output: Dog eats bones
}
}

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.

08. Differentiate abstract base class and an interface. 8


Ans
Aspect Abstract Class Interface
Definition A class that can contain both A blueprint for a class that only
abstract methods (without a contains abstract methods (prior to
body) and concrete methods Java 8) and constants. From Java 8, it
(with a body). can also include default and static
methods.
Inheritance A class can inherit only one A class can implement multiple
abstract class (single interfaces (multiple inheritance).
inheritance).
Usage Used when classes share Used to define a contract for unrelated
common behavior and classes to implement.
properties.
Keywords Declared using the abstract Declared using the interface keyword.
keyword.
Method Types Can have both abstract and Can have abstract methods, default
concrete methods. methods (Java 8+), and static methods
(Java 8+).
Fields Can have instance variables Can have only public, static, and final
and constants. Instance fields (constants).

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 Abstract Class


abstract class Animal {
abstract void sound();
void eat() {
System.out.println("This animal eats food.");
}
}

class Dog extends Animal {


void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.sound();
myDog.eat();
}
}

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

Key Points About Interface Variables


1. Cannot Be Modified:
o Any attempt to change the value of an interface variable will result in a
compilation error.
o Example:
MyInterface.MAX_VALUE = 200;
2. Default Modifiers:
o You can explicitly specify the modifiers (public static final), but it’s redundant:
interface Example {
public static final int VALUE = 50; // Same as int
VALUE = 50;
}
3. Cannot Be Non-Static:
o Instance variables (non-static) are not allowed in interfaces.
4. No Access Control Beyond public:

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.

Key Terms in Exception Handling


1. Exception:
o An object created when an error occurs. It contains information about the error
(e.g., type, message, location).
o Hierarchy of exceptions in Java:
 Throwable is the base class.
 Two main subclasses:
 Error: Represents serious problems (e.g.,
OutOfMemoryError), not typically handled by applications.
 Exception: Represents conditions that applications might
handle.
2. Try Block:
o A block of code where exceptions are anticipated and can occur.
o Example:
try {
int result = 10 / 0; // Exception occurs here
}
3. Catch Block:
o A block of code used to handle the exception.
o Executes when an exception is thrown in the corresponding try block.
o Example:
catch (ArithmeticException e) {
System.out.println("Cannot divide by zero.");
}
4. Finally Block:
o A block of code that is always executed, regardless of whether an exception
was thrown or caught.
o Used to perform cleanup activities (e.g., closing files, releasing resources).
o Example:
finally {
System.out.println("Cleanup code executed.");
}
5. Throw:
o Used to explicitly throw an exception.
o Example:
throw new ArithmeticException("Custom message");
6. Throws:
o Used in method declarations to indicate that a method might throw exceptions.
o Example:
public void readFile() throws IOException {
// Method code
}
7. Checked Exceptions:
o Exceptions that are checked at compile-time.
o Must be either handled in a try-catch block or declared using throws.

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.

Example of Exception Handling


public class ExceptionExample {
public static void main(String[] args) {
try {
int num = 10 / 0;
System.out.println("This line will not be
executed.");
} catch (ArithmeticException e) {
System.out.println("Exception caught: " +
e.getMessage());
} finally {
System.out.println("Finally block executed.");
}
}
}
Output:
Exception caught: / by zero
Finally block executed.

Flow of Exception Handling


1. Java executes the code inside the try block.
2. If no exception occurs, the catch block is skipped, and control moves to the finally
block (if present).
3. If an exception occurs:
o The try block stops executing.
o Control moves to the appropriate catch block.
o The finally block executes after the catch block.

Key Advantages of Exception Handling


 Separates Error-Handling Code: Keeps the error-handling logic separate from the
normal logic.
 Improves Program Reliability: Helps prevent unexpected crashes.
 Propagates Errors: Allows errors to be propagated up the call stack.
 Clean Resource Management: Ensures resources like files and connections are
properly closed.
11. Demonstrate working of nested try block with an example. 8
Ans Working of Nested try Blocks in Java
In Java, you can have a nested try block, where a try block is placed inside another try block.
This allows you to handle exceptions at different levels and provides more flexibility in
managing errors within a specific section of code.
A nested try block is useful when you need to handle exceptions that may arise from specific
parts of a complex block of code.
Syntax of Nested try Block
try {
// Outer try block code
try {
// Inner try block code
} catch (ExceptionType1 e1) {
// Inner catch block
}
} catch (ExceptionType2 e2) {
// Outer catch block
}

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

Advantages of Nested try Blocks

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.

ii. Uncaught Exceptions


An uncaught exception occurs when an exception is thrown, but there is no code to catch it
(i.e., no catch block is present to handle the exception). This results in the propagation of the
exception up the call stack until it reaches the main method or any other method capable of
handling it. If not caught, the exception causes the program to terminate abruptly.
Handling Uncaught Exceptions
 UncaughtExceptionHandler:
o Java provides the Thread.setDefaultUncaughtExceptionHandler() method,
which allows you to specify a global handler for uncaught exceptions. This
handler will handle any uncaught exceptions thrown by any thread in the
program.
Example of Uncaught Exception
public class UncaughtExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (Exception e) {
System.out.println("Caught: " + e.getMessage());
}
}
}
In the above example, if there was no catch block to handle the exception, the exception would
be uncaught and would cause the program to terminate with a stack trace. If the exception
occurs in the main method and isn't caught anywhere, the program ends with an error message.
Global Handling with UncaughtExceptionHandler
public class UncaughtExceptionHandlerExample {
public static void main(String[] args) {
Thread.setDefaultUncaughtExceptionHandler((thread,e)->{
System.out.println("Uncaught exception: " +
e.getMessage());
});
throw new RuntimeException("This is an uncaught
exception!");
}
}
Output:
Uncaught exception: This is an uncaught exception!
By setting a default handler, you can manage uncaught
exceptions globally, ensuring the program doesn't terminate
unexpectedly and providing a mechanism for handling uncaught
exceptions in a centralized way.

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.

Example of a Custom Checked Exception


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 is less than 18.
Invalid age.");
}
System.out.println("Age is valid.");
}

public static void main(String[] args) {


try {
checkAge(15);
} catch (InvalidAgeException e) {
System.out.println("Caught exception: " +
e.getMessage());
}
}
}
Output:
Caught exception: Age is less than 18. Invalid age.

Example of a Custom Unchecked Exception


class InvalidAgeException extends RuntimeException {
public InvalidAgeException(String message) {
super(message);

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

public static void main(String[] args) {


try {
checkAge(15);
} catch (InvalidAgeException e) {
System.out.println("Caught exception: " +
e.getMessage());
}
}
}

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;

public BankAccount(double balance) {


this.balance = balance;
}
public void withdraw(double amount) throws
InsufficientBalanceException {
if (balance - amount < MIN_BALANCE) {

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

public static void main(String[] args) {


try {
checkAge(15);
} catch (ArithmeticException e) {
System.out.println(e.getMessage());
}
}
}

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

public void transfer(Account target, double amount) {


if (amount > 0 && amount <= balance) {
balance -= amount;
target.deposit(amount);
System.out.println("Transferred " + amount);
} else {
System.out.println("Transfer failed.");
}
}
}
Page | 93
TestAccount.java
import balance.Account;
public class TestAccount {
public static void main(String[] args) {
Account account1 = new Account(1000.50);
Account account2 = new Account(500.75);
account1.displayBalance();
account2.displayBalance();
account1.deposit(200);
account1.withdraw(150);
account1.displayBalance();
account1.transfer(account2, 300);
account1.displayBalance();
account2.displayBalance();
account2.deposit(100);
account2.displayBalance();
}
}
19. Define package. Explain the steps involved in creating a user-defined package with an 7
example
Ans A package in Java is a namespace that organizes a set of related classes and interfaces.
Packages help in avoiding name conflicts, improving maintainability, and controlling access.
Steps to Create a User-Defined Package:
1. Create a Package: Use the package keyword to define a package.
2. Create Classes in the Package: Define classes or interfaces inside the package.
3. Compile the Package: Compile the classes in the package.
4. Import the Package: Use the import statement to use the classes in the package in
other programs.
Example:
Step 1: Create a package shapes.
package shapes;

public class Circle {


private double radius;

public Circle(double radius) {


this.radius = radius;
}

public double calculateArea() {


return Math.PI * radius * radius;
}
}
Step 2: Create another program to use the package shapes.
import shapes.Circle;

public class TestShapes {


public static void main(String[] args) {
Circle circle = new Circle(5.0);
System.out.println("Area of Circle: " +
circle.calculateArea());
}
}

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());
}

String str = null;


System.out.println(str.length()); // Null pointer
exception
} catch (NullPointerException e) {
System.out.println("Outer 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.

02 What is the need of synchronization? Explain with an example how synchronization is 7


. implemented in JAVA.
A Need for Synchronization in Java:
In a multithreaded environment, multiple threads may attempt to access and modify shared resources
(like variables, data structures, etc.) at the same time. If these threads are not properly controlled, it
can lead to data inconsistency and race conditions, where the outcome of operations depends on the
order of execution, which is unpredictable.
Synchronization in Java is used to ensure that only one thread at a time can access a shared resource,
preventing data corruption and ensuring thread safety. By synchronizing critical sections of the code,
Java ensures that only one thread can execute a particular piece of code at a time.
How Synchronization is Implemented in Java:
Synchronization can be achieved in Java in two primary ways:
1. Method Synchronization
2. Block Synchronization (Synchronized Block)
1. Method Synchronization:
You can synchronize an entire method by adding the synchronized keyword to its definition. This
ensures that only one thread can execute the synchronized method at a time.
Example:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized void decrement() {
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();

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;
}

public class EnumValuesExample {


public static void main(String[] args) {
Day[] days = Day.values();

for (Day day : days) {


System.out.println(day);
}
}
}
Output:
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
In this example, Day.values() returns all the days of the week as an array, and we print them one by
one.
2. valueOf() Method
The valueOf() method returns the enum constant that matches the given name (case-sensitive). If the
constant with the specified name does not exist, it throws an IllegalArgumentException.
 Return Type: T (Enum constant)
 Usage: This method is useful when you want to convert a string to its corresponding enum
constant.
Example:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

public class EnumValueOfExample {


public static void main(String[] args) {
String input = "MONDAY";

Day day = Day.valueOf(input);


System.out.println("The day is: " + day);
}
}
Output:
The day is: MONDAY
In this example, Day.valueOf(input) converts the string "MONDAY" to
its corresponding Day enum constant.
Handling Invalid Input with valueOf()
If an invalid value is passed to valueOf(), it will throw an IllegalArgumentException. You can handle
this exception using a try-catch block.
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

04 What is multithreading? Write a program to create multiple threads in JAVA. 7


.
A What is Multithreading in Java?
Multithreading is a feature in Java that allows concurrent execution of two or more parts (threads)
of a program to maximize CPU utilization. Each part of the program is called a thread, and it runs
independently, but shares the same resources, such as memory, with other threads.
Multithreading is used to perform multiple operations simultaneously. It is particularly useful for
tasks that are independent and can be run in parallel, such as running background tasks, improving
performance, and handling multiple user requests simultaneously.
Types of Threads in Java:
1. User Threads: These are the threads created by the application and typically run until
completion.
2. Daemon Threads: These are service threads that run in the background and are terminated
automatically when all user threads finish execution (e.g., garbage collection threads).
Creating Threads in Java:
In Java, threads can be created in two ways:
1. By implementing the Runnable interface
2. By extending the Thread class
Below is an example using both approaches to create multiple threads.
Example Program to Create Multiple Threads:
class MyRunnable implements Runnable {
private String threadName;

public MyRunnable(String name) {


threadName = name;
}
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + " - " + i);
try {
Thread.sleep(500); // Pause for 500ms
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
class MyThread extends Thread {
private String threadName;

public MyThread(String name) {


threadName = name;
}
Page | 102
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(threadName + " - " + i);
try {
Thread.sleep(500); // Pause for 500ms
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
public class MultiThreadingExample {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable("Runnable Thread");
Thread thread1 = new Thread(runnable);
MyThread thread2 = new MyThread("Thread Class");
thread1.start();
thread2.start();
}
}
Explanation:
1. MyRunnable Class: This class implements the Runnable interface. The run() method
contains the code that will be executed by the thread. The thread sleeps for 500ms after
printing the message, simulating some work.
2. MyThread Class: This class extends the Thread class. It overrides the run() method to define
the task the thread will perform.
3. Main Class (MultiThreadingExample): The main() method creates two threads:
o One thread is created by implementing the Runnable interface (thread1).
o Another thread is created by extending the Thread class (thread2).
Both threads are started using the start() method, which invokes the run() method.
Output (Order may vary due to concurrent execution):
Runnable Thread - 1
Thread Class - 1
Runnable Thread - 2
Thread Class - 2
Runnable Thread - 3
Thread Class - 3
Runnable Thread - 4
Thread Class - 4
Runnable Thread - 5
Thread Class - 5
05 Explain with an example how inter-thread communication is implemented in JAVA. 7
.
A Inter-Thread Communication in Java
Inter-thread communication in Java refers to the ability of two or more threads to communicate with
each other. It is primarily used in situations where one thread needs to wait for a certain condition or
event in another thread before continuing execution.
Java provides three key methods for inter-thread communication:
1. wait(): Tells the current thread to release the lock and enter the waiting state until another
thread sends a notification.
2. notify(): Wakes up one of the threads that are waiting on the object.
3. notifyAll(): Wakes up all the threads that are waiting on the object.
These methods are used within a synchronized block or method. Only the thread that holds the lock
on the object can call these methods.
Key Concepts:
 wait(): Causes the current thread to wait until another thread sends a signal using notify() or
notifyAll().
 notify(): Wakes up a single thread that is waiting for the object's monitor.
Page | 103
 notifyAll(): Wakes up all the threads that are waiting for the object's monitor.
Example of Inter-Thread Communication:
In this example, we'll have two threads:
1. A Producer thread that produces data.
2. A Consumer thread that consumes data.
The Producer thread will produce data and notify the Consumer thread, while the Consumer thread
will wait until the Producer provides data.
class SharedData {
private int data;
private boolean available = false;
public synchronized void produce(int data) throws
InterruptedException {
while (available) {
wait(); // Wait if data is already available
}
this.data = data;
available = true;
System.out.println("Produced: " + data);
notify(); // Notify consumer that data is available
}
public synchronized int consume() throws InterruptedException {
while (!available) {
wait(); // Wait if no data is available
}
available = false;
System.out.println("Consumed: " + data);
notify(); // Notify producer that data can be produced
again
return data;
}
}
class Producer extends Thread {
private SharedData sharedData;

public Producer(SharedData sharedData) {


this.sharedData = sharedData;
}
public void run() {
try {
for (int i = 1; i <= 5; i++) {
sharedData.produce(i);
Thread.sleep(1000); // Simulate time taken to
produce data
}
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
class Consumer extends Thread {
private SharedData sharedData;
public Consumer(SharedData sharedData) {
this.sharedData = sharedData;
}
public void run() {
try {
for (int i = 1; i <= 5; i++) {
sharedData.consume();

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.

07 Define a thread. Also discuss the different ways of creating a thread. 6


.
A Same as 1
08 How synchronization can be achieved between threads in Java? Explain with an example. 6
.
A Synchronization in Java
Synchronization in Java is a mechanism that ensures that only one thread can access a resource or
critical section at a time, preventing data inconsistency and race conditions. It is essential in multi-
threaded programs when multiple threads share common resources (like variables, objects, files, etc.).
Synchronization can be achieved in two primary ways:
1. Synchronized Methods
2. Synchronized Blocks
1. Synchronized Methods
A synchronized method is a method that is used by only one thread at a time. It ensures that only one
thread can execute the method at any given moment.
Syntax:

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();

UserThread t1 = new UserThread(account);


UserThread t2 = new UserThread(account);
t1.start();
t2.start();
}
}

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

11 Explain Autoboxing/Unboxing that others in expressions and operators. 6


.
A Autoboxing and Unboxing in Java
Autoboxing and unboxing are Java's automatic conversion between primitive types and their
corresponding wrapper classes. This mechanism allows the seamless use of primitive types in
contexts that require objects, such as in collections, while still retaining the ability to perform
arithmetic operations directly with primitive types.
Autoboxing:
Autoboxing refers to the automatic conversion of a primitive type into its corresponding wrapper
class object.
For example:
 int becomes Integer
 char becomes Character
 double becomes Double
Unboxing:
Unboxing refers to the automatic conversion of a wrapper class object into its corresponding
primitive type.
For example:
 Integer becomes int
 Character becomes char
 Double becomes double
Autoboxing and Unboxing in Expressions and Operators
Java automatically applies autoboxing and unboxing when working with expressions or operators that
involve both primitive types and wrapper class objects.
Examples:
1. Autoboxing with Arithmetic Operators: When you perform operations with wrapper class
objects and primitive types, Java automatically unboxes the wrapper object to its primitive
type.
Integer intObj = 10;
int result = intObj + 5;
System.out.println("Result: " + result);
o intObj is unboxed to int, and the result of intObj + 5 is computed as 15.

Page | 110
2. Unboxing in Method Arguments: Wrapper objects are automatically unboxed when passed
to methods that expect a primitive type.

public static void addNumbers(int num1, int num2) {


System.out.println(num1 + num2);
}
public static void main(String[] args) {
Integer a = 10;
Integer b = 20;
addNumbers(a, b);
}
3. Autoboxing in Collections: Java's collections (like ArrayList) work with objects, so
autoboxing allows you to store primitive values in collections without explicitly converting
them.
List<Integer> list = new ArrayList<>();
list.add(10); // Autoboxing occurs here (int -> Integer)
list.add(20);
int sum = 0;
for (Integer num : list) {
sum += num; // Unboxing occurs here (Integer -> int)
}
System.out.println("Sum: " + sum);
4. Autoboxing in Expressions with Mixed Types: Java allows operations with a mix of
wrapper classes and primitive types. It automatically unboxes the wrapper objects for
arithmetic operations.
Integer x = 5;
int y = 10;
Integer z = x + y;
System.out.println(z);

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

public class ThreadConcurrentExample {


public static void main(String[] args) {
MyThread myThread = new MyThread("Child Thread");
for (int i = 1; i <= 5; i++) {

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; }
};

public abstract double apply(double x, double y);


}

public class EnumExample {


public static void main(String[] args) {
System.out.println("Add: " + Operation.ADD.apply(5, 3));
}
}
Page | 113
Explanation:
 First Example: The Day enum defines constants with descriptions and a method to retrieve
the description.
 Second Example: The Operation enum overrides the apply() method to perform different
operations like addition and subtraction.

15 Write a note on ordinal() and compareTo() methods. 8


.
A ordinal() and compareTo() Methods in Java Enums
In Java, enum types provide some special methods that are useful for working with their constants.
Two of the commonly used methods are ordinal() and compareTo(). These methods are
automatically available for all enum types because enums implicitly extend the Enum class.
1. ordinal() Method
The ordinal() method returns the position of an enum constant in the enum declaration. It returns an
integer value that represents the order in which the constant is declared. The ordinal value starts from
0 for the first constant, 1 for the second, and so on.
Syntax:
int ordinal()
Example:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

public class EnumExample {


public static void main(String[] args) {
System.out.println("Ordinal of MONDAY: " +
Day.MONDAY.ordinal());
System.out.println("Ordinal of WEDNESDAY: " +
Day.WEDNESDAY.ordinal());
}
}
Output:
Ordinal of MONDAY: 0
Ordinal of WEDNESDAY: 2
Explanation:
 The ordinal() method returns the position of the enum constant. For example, MONDAY is
the first constant, so it has an ordinal value of 0, while WEDNESDAY has an ordinal value of
2 because it's the third constant in the declaration.
2. compareTo() Method
The compareTo() method is used to compare the current enum constant with another enum constant
of the same type. It compares the ordinal values of the constants and returns:
 A negative integer if the current constant is less than the other constant.
 Zero if the current constant is equal to the other constant.
 A positive integer if the current constant is greater than the other constant.
Syntax:
int compareTo(E o)
Where E is the type of the enum.
Example:
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;
}

public class EnumExample {


public static void main(String[] args) {
Day today = Day.MONDAY;
Day tomorrow = Day.TUESDAY;

System.out.println("Comparing MONDAY with TUESDAY: " +


today.compareTo(tomorrow));
Page | 114
}
}
Output:
Comparing MONDAY with TUESDAY: -1
Explanation:
 The compareTo() method compares the ordinal values of the enum constants. Since
MONDAY is declared before TUESDAY, the method returns a negative value (-1), indicating
that MONDAY is less than TUESDAY.

16 What are wrapper classes? Explain with examples. 8


.
A Same as 10
17 Write a JAVA program to create two threads, one displays "computer science" and another displays 8
. "information science" five times.
A class ComputerScienceThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Computer Science");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
class InformationScienceThread extends Thread {
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println("Information Science");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
public class Main {
public static void main(String[] args) {
ComputerScienceThread thread1 = new
ComputerScienceThread();
InformationScienceThread thread2 = new
InformationScienceThread();
thread1.start();
thread2.start();
}
}
18 With syntax, explain use Of is Alive( ) and join( ) methods. 8
.
A isAlive() and join() Methods in Java
In Java, the isAlive() and join() methods are used to manage and control the execution flow of
threads. These methods are part of the Thread class and provide mechanisms for checking the status
of a thread and synchronizing threads, respectively.

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

public class ThreadExample {


public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();

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;

public 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;

public BankThread(Account account) {


this.account = account;
}
public void run() {
account.withdraw(500);
Page | 117
}
}
public class Main {
public static void main(String[] args) {
Account account = new Account();
BankThread thread1 = new BankThread(account);
BankThread thread2 = new BankThread(account);

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;

public BankThread(Account account) {


this.account = account;
}
public void run() {
account.withdraw(500);
}
}
public class Main {
public static void main(String[] args) {
Account account = new Account();
BankThread thread1 = new BankThread(account);
BankThread thread2 = new BankThread(account);
thread1.start();
thread2.start();
}
}
With synchronization, only one thread can access the withdraw() method at a time, ensuring thread
safety.
Types of Synchronization:
1. Method-Level: Using synchronized on the method.
2. Block-Level: Synchronizing specific blocks of code.
3. Static Synchronization: Synchronizing static methods or blocks.
Conclusion:
Synchronization ensures safe access to shared resources in a multithreaded environment, preventing
race conditions and ensuring data consistency.

20 Explain with an example how inter thread communication is implemented in JAVA 8


.
A Same as 5
Page | 118
21 What is meant by thread priority? How to assign and get the thread priority? 8
.
A Thread Priority in Java
Thread priority determines the relative importance of a thread. It helps the operating system decide
which thread to execute first when multiple threads are competing for CPU time. A thread with a
higher priority may get more CPU time than one with a lower priority.
Java provides a priority system for threads, which is an integer value between
Thread.MIN_PRIORITY (1) and Thread.MAX_PRIORITY (10), with Thread.NORM_PRIORITY
(5) being the default value.
Assigning Thread Priority
You can assign a priority to a thread using the setPriority(int priority) method. The argument passed
to setPriority() should be between Thread.MIN_PRIORITY (1) and Thread.MAX_PRIORITY (10).
Getting Thread Priority
To get the priority of a thread, you can use the getPriority() method, which returns the current priority
of the thread.
Example:
class MyThread extends Thread {
public void run() {
System.out.println(Thread.currentThread().getName() + "
with priority: " + Thread.currentThread().getPriority());
}
}

public class ThreadPriorityExample {


public static void main(String[] args) {
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();

// 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

You might also like