0% found this document useful (0 votes)
17 views119 pages

Document From Bujji

The document covers fundamental concepts in Java, including command line arguments, static vs. instance variables, and the differences between assignment and equality operators. It also explains Object-Oriented Programming principles, various operators, data types, casting, and variable scope. Each section provides definitions, examples, and distinctions to enhance understanding of Java programming.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views119 pages

Document From Bujji

The document covers fundamental concepts in Java, including command line arguments, static vs. instance variables, and the differences between assignment and equality operators. It also explains Object-Oriented Programming principles, various operators, data types, casting, and variable scope. Each section provides definitions, examples, and distinctions to enhance understanding of Java programming.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 119

Unit-I

Part-A
1.Explain how command line arguments work in Java.
Command line arguments in Java provide a way to pass information to your program when
it's launched. This data can be accessed within your Java application and used to modify its
behavior.
 args: The main method in Java has a parameter String[] args, which holds the
command-line arguments.
 args.length: This gives the number of arguments passed.
 Looping through args: You can iterate over the args array to process each argument
individually.

2.Write the difference between static variables and instance


variables in Java?
Static Variables

 Definition: Declared with the static keyword within a class but outside any method or
constructor.
 Memory Allocation: Allocated once per class, shared among all instances of the class.
 Access: Can be accessed directly using the class name without creating an instance.
For example, ClassName.staticVariable.
 Use Case: Used for constants or data that is common to all instances (e.g., a counter
for the number of objects created from a class).
Instance Variables

 Definition: Declared inside a class but outside any method, constructor, or block,
without the static keyword.
 Memory Allocation: Allocated each time a new instance of the class is created.
 Access: Accessed through objects; each object has its own copy of the instance
variable. For example, objectName.instanceVariable.
 Use Case: Used for data that is unique to each instance of the class (e.g., attributes
like name, age, etc. for an Employee class).
3.What is the difference between = and == in Java
The difference between = and == in Java is essential to understand for avoiding common
pitfalls in coding:
= (Assignment Operator)
Purpose: Used to assign a value to a variable.
Example:
int a = 10; // Assigns the value 10 to the variable a
Usage: Assigns the value on the right to the variable on the left.
== (Equality Operator)
Purpose: Used to compare two values for equality.
Example:
int a = 10;
int b = 10;
if (a == b) {
System.out.println("a and b are equal");
}
Usage: Checks if the two operands on either side are equal.

4.What is the ternary operator, and how is it used in Java?


The ternary operator in Java, also known as the conditional operator, is a shorthand way to
write simple if-else statements. It uses the ? and : symbols to evaluate a condition and return
one of two values based on that condition.
Syntax:
condition ? value_if_true : value_if_false;
example, the condition a > b is false, so the ternary operator returns b. The variable max is
assigned the value of b, which is 20.
The ternary operator is a concise and readable way to handle simple conditional logic. It
keeps your code clean and succinct when dealing with straightforward decisions.

5.Differentiate between while and do-while loops.


while Loop
Syntax:
while (condition) {
// code to be executed
}
 Condition Check: The condition is checked before the execution of the loop's
body.
 Execution Guarantee: The loop may not execute at all if the condition is false
initially.
do-while Loop
Syntax:
do {
// code to be executed
} while (condition);
 Condition Check: The condition is checked after the execution of the loop's body.
 Execution Guarantee: The loop will execute at least once, regardless of whether
the condition is true or false initially.
6.How do the break and continue statements control loop
execution in Java?
break Statement
The break statement is used to terminate a loop or switch statement prematurely. When
encountered, it causes the program to exit the loop or switch statement immediately and
proceed with the next statement after the loop.
continue Statement
The continue statement is used to skip the current iteration of a loop and proceed to the next
iteration. When encountered, the loop continues with the next iteration, bypassing any code
below the continue statement within the current loop iteration.

PART:B

1.What are the key principles of Object-Oriented Programming? Explain each briefly.
Answer:
Object means a real world entity such as pen, chair, table etc.Object-Oriented
Programming is a methodology or paradigm to design a program using classes and
objects. It simplifies the software development and maintenance by providing some
concepts:

o Object
o Class
o Inheritance
o Polymorphism
o Abstraction
o Encapsulation

Object:

Any entity that has state and behaviour is known as an object.


For example, a chair, pen, table, keyboard, bike, etc. It can be
physical or logical.

An Object can be defined as an instance of a class. An object


contains an address and takes up some space in memory.
Objects can communicate without knowing the details of
each other's data or code.

Example: A dog is an object because it has states like colour, name, breed, etc. as well as
behaviours like wagging the tail, barking, eating, etc.

Class:

Collection of objects is called class. It is a logical entity.

A class can also be defined as a blueprint from which


you can create an individual object. Class doesn't
consume any space.

Inheritance:

When one object acquires all the properties and


behaviours of parent object i.e. known as inheritance. It
provides code reusability. It is used to achieve runtime
polymorphism.

Polymorphism:

When one task is performed by different ways i.e.


known as polymorphism. For example: to convince the
customer differently ,to draw something e.g. shape or
rectangle etc.

In java, we use method overloading and method


overriding to achieve polymorphism.
Another example can be to speak something e.g. cat
speaks meow, dog barks woof etc.
Abstraction:

Hiding internal details and showing functionality is known as


abstraction. For example: Withdraw money from ATM Machine,
we don't know the internal processing.

In java, we use abstract class and interface to achieve abstraction.

Encapsulation:

Binding(or wrapping)code and data together into a single unit is known


as encapsulation. For example: capsule, it is wrapped with different
medicines.

A java class is the example of encapsulation. JavaBeans is the fully encapsulated class
because all the data members are private here.

2.Explain Different operators with examples.


the different operators in Java and see them in action:

1. Arithmetic Operators
Used for basic mathematical operations.
Addition (+):
int a = 5;
int b = 3;
int sum = a + b; // sum is 8
Subtraction (-):
int diff = a - b; // diff is 2
Multiplication (*):
int product = a * b; // product is 15
Division (/):
int quotient = a / b; // quotient is 1
Modulus (%):
int remainder = a % b; // remainder is 2

2. Relational Operators
Used for comparison between two values.
Equal to (==):
boolean isEqual = (a == b); // isEqual is false
Not equal to (!=):
boolean isNotEqual = (a != b); // isNotEqual is true
Greater than (>):
boolean isGreater = (a > b); // isGreater is true
Less than (<):
boolean isLess = (a < b); // isLess is false
Greater than or equal to (>=):
boolean isGreaterOrEqual = (a >= b); // isGreaterOrEqual is true

Less than or equal to (<=):


boolean isLessOrEqual = (a <= b); // isLessOrEqual is false
3. Logical Operators
Used for logical operations, mostly with boolean values.
AND (&&):
boolean result = (a > 0 && b > 0); // result is true
OR (||):
result = (a > 0 || b < 0); // result is true
NOT (!):
result = !(a > 0); // result is false
4. Bitwise Operators
Used for operations on individual bits.
AND (&):
int bitwiseAnd = a & b; // bitwiseAnd is 1 (binary: 0101 & 0011 = 0001)
OR (|):
int bitwiseOr = a | b; // bitwiseOr is 7 (binary: 0101 | 0011 = 0111)
XOR (^):
int bitwiseXor = a ^ b; // bitwiseXor is 6 (binary: 0101 ^ 0011 = 0110)
5. Assignment Operators
Used to assign values to variables.
Simple assignment (=):
int c = 5; // assigns 5 to c
Addition assignment (+=):
c += 2; // c is now 7 (equivalent to c = c + 2)
Subtraction assignment (-=):
c -= 2; // c is now 5 (equivalent to c = c - 2)
6. Unary Operators
Operate on a single operand.
Unary plus (+) and minus (-):
int positive = +a; // positive is 5
int negative = -a; // negative is -5
Increment (++):
int increment = ++a; // increment is 6, a is 6 (pre-increment)
Decrement (--):
int decrement = --a; // decrement is 5, a is 5 (pre-decrement)
7. Conditional (Ternary) Operator
A shorthand way to write simple if-else statements.

Syntax:
int max = (a > b) ? a : b; // max is 5

These are the foundational operators in Java that you'll use to manipulate data and control
the flow of your programs.

3.a.What are the different data types available in Java? Classify them into primitive
and non-primitive types.
Datatype specifies the size and types of values that a variable hold.Java is rich in it’s data
types.
Primitive Data Types: A primitive data type specifies the size and type of variable values,
andithas no additional methods.

Thereareeight primitivedatatypesinJava:

Data Size Description


Type
Byte 1 byte Storeswholenumbersfrom-128to127
Short 2 bytes Storeswholenumbersfrom-32,768to32,767
Int 4 bytes Storeswholenumbersfrom-2,147,483,648to2,147,483,647
Long 8 bytes Stores whole numbers from -9,223,372,036,854,775,808
to9,223,372,036,854,775,807
Float 4 bytes Storesfractionalnumbers.Sufficientforstoring6to7decimaldigits
double 8 bytes Storesfractionalnumbers.Sufficientforstoring15decimaldigits
boolean 1 bit Storestrueorfalsevalues
Char 2 bytes Storesasinglecharacter/letterorASCIIvalues

Note1:Note that you should end the value of float with an "f"
Note2:Note that you should end the value of double with a"d"

Example:
Intnum =5;
float num1 = 5.99f;

double num3=5.7896d;

Charch='D';
boolean status = true;
Stringname="sai";
System.out.println("Value inside integer type variable " + num);System.out.println("Value
inside float type variable " + num1);
System.out.println("Value inside double type variable " +
num1);System.out.println("Value inside character type variable " +
ch);System.out.println("Value inside boolean type variable " +
status);System.out.println("Valueinsidestring typevariable"+name);

Non-PrimitiveDataTypes:
Non-primitivedatatypesarecalledreference types becausetheyrefertoobjects.
Themaindifferencebetween primitiveandnon-primitivedatatypesare:
1. Primitive types are predefined (already defined) in Java. Non-primitive
types are created by the programmer and is not defined by Java
(exceptforString).
2. Non-primitive types can be used to call methods to perform certain
operations,whileprimitivetypes cannot.
3. A primitivetype has always a value,while non-primitive types can be
null.
4. A primitive type starts with a lowercase letter, while non-primitive
typesstartswith an uppercaseletter.
5. The size of a primitive type depends on the data type, while non-
primitivetypeshaveall the samesize.

6. Examples of non-primitive types are Strings, Arrays, Classes,


Interface,etc.
String:The String data type is used to store a sequence of characters (text). String
valuesmustbesurrounded by double quotes:

Example:
String greet = "Hello World";

System.out.println(greet);

Note: A String in Java is actually a non-primitive data type, because it refers to an


object.The String object has methods that areusedto perform certain operation son strings.

b.Explain implicit and explicit casting with an example.


Implicit Casting (Widening)
Implicit casting, also known as widening, occurs automatically when converting a smaller
data type to a larger data type. Since there is no data loss, the conversion happens without
any explicit instructions from the programmer.

Example:
int num = 100;
double doubleNum = num; // Implicit casting from int to double
System.out.println("Double value: " + doubleNum); // Outputs: 100.0

Explicit Casting (Narrowing)


Explicit casting, or narrowing, involves converting a larger data type to a smaller data type.
This process can potentially lead to data loss, so it requires explicit instructions from the
programmer using a cast operator.
Example:
double doubleNum = 100.99;
int num = (int) doubleNum; // Explicit casting from double to int
System.out.println("Integer value: " + num); // Outputs: 100

Key Differences:
Implicit Casting:
 No need for explicit conversion.
 Happens automatically when converting a smaller data type to a larger one.
 Safe and no data loss.

Explicit Casting:
 Requires explicit conversion using the cast operator.
 Happens when converting a larger data type to a smaller one.
 Potential for data loss.

4. Explain the scope of various types of variables in java.

The scope of a variable refers to the region of the code where the variable is accessible and
can be used. The scope of a variable is determined by where the variable is declared. Java
has several types of variable scopes, including:

1. Local Variable Scope:

A local variable is declared within a method, constructor, or block (such as an `if` statement
or a loop). Its scope is limited to the block in which it is declared.
Local variables are accessible only within the method, constructor, or block where they are
defined. Once the method or block exits, the local variable is no longer accessible, and its
memory is reclaimed.
Example:
public void myMethod() {
int localVar = 10; // local variable
if (localVar > 5) {
int blockVar = 20; // local variable within an if block
System.out.println(blockVar);
}
// System.out.println(blockVar); // Error: blockVar cannot be resolved
}

2. Instance Variable Scope:

An instance variable is declared inside a class but outside of any method, constructor, or
block. It is associated with an instance of the class (i.e., an object).

Instance variables are accessible to all methods, constructors, and blocks within the class.
They can be accessed directly by other methods of the same instance or using the object
reference.
Example:
public class MyClass {
private int instanceVar; // instance variable
public void setInstanceVar(int value) {
this.instanceVar = value; // Accessing instance variable
}
public int getInstanceVar() {
return this.instanceVar; // Accessing instance variable
}
}
3. Class Variable Scope:
A class variable, also known as a static variable, is declared with the `static` keyword inside
a class but outside of any method, constructor, or block. It is shared among all instances of
the class.
Class variables are accessible to all methods, constructors, and blocks within the class. They
can also be accessed directly using the class name.

Example:
public class MyClass {
public static int classVar; // class variable

public static void setClassVar(int value) {


MyClass.classVar = value; // Accessing class variable
}

public static int getClassVar() {


return MyClass.classVar; // Accessing class variable
}
}

4. Parameter Variable Scope:


Parameters are variables passed to methods, constructors, or blocks. They are declared in the
method or constructor signature.
Parameters are accessible only within the method or constructor where they are declared.

Example:
public void myMethod(int param) { // param is a parameter variable
System.out.println(param); // Accessing parameter variable
}

Key Points to Remember:

- Shadowing: Variables declared in a narrower scope (e.g., a local variable in a method)


can shadow variables with the same name in a broader scope (e.g., instance variables).
When this happens, the variable in the narrower scope takes precedence.
- Initialization: Local variables must be initialized before use, while instance and class
variables are automatically initialized with default values if not explicitly initialized.

- Access Modifiers: The scope also interacts with access modifiers (`public`, `protected`,
`private`, and package-private) that control the visibility of class members outside their
class.

Understanding variable scope is crucial for managing data access and ensuring that variables
are used correctly within their intended context in Java.

5.
a. Discuss the operator precedence and associativity in java with examples
The operator precedence represents how two expressions are bind together. In an
expression, it determines the grouping of operators with operands and decides how an
expression will evaluate.

While solving an expression two things must be kept in mind the first is a precedence and
the second is associativity.

Precedence
Precedence is the priority for grouping different types of operators with their operands. It is
meaningful only if an expression has more than one operator with higher or lower
precedence. The operators having higher precedence are evaluated first. If we want to
evaluate lower precedence operators first, we must group operands by using parentheses and
then evaluate.

Advertisement
Associativity
We must follow associativity if an expression has more than two operators of the same
precedence. In such a case, an expression can be solved either left-to-right or right-to-
left, accordingly.

Java Operator Precedence Table


The following table describes the precedence and associativity of operators used in Java.

Precedence Operator Type Associativity

() Parentheses
15 [] Array subscript Left to Right
· Member selection

++ Unary post-increment
14 Right to left
-- Unary post-decrement

++ Unary pre-increment
-- Unary pre-decrement
+ Unary plus
13 - Unary minus Right to left
! Unary logical negation
~ Unary bitwise complement
(type) Unary type cast

* Multiplication
12 / Division Left to right
% Modulus

+ Addition
11 Left to right
- Subtraction

Bitwise left shift


<< Bitwise right shift with sign
10 >> extension Left to right
>>> Bitwise right shift with zero
extension

9 < Relational less than Left to right


<= Relational less than or equal
> Relational greater than
>= Relational greater than or
instanceof equal
Type comparison (objects
only)

== Relational is equal to
8 Left to right
!= Relational is not equal to

7 & Bitwise AND Left to right

6 ^ Bitwise exclusive OR Left to right

5 | Bitwise inclusive OR Left to right

4 && Logical AND Left to right

3 || Logical OR Left to right

2 ?: Ternary conditional Right to left

= Assignment
+= Addition assignment
-= Subtraction assignment
1 Right to left
*= Multiplication assignment
/= Division assignment
%= Modulus assignment

Note: Larger the number higher the precedence.

Java Operator Precedence Example


Let's understand the operator precedence through an example. Consider the following
expression and guess the answer.

1. 1 + 5 * 3

You might be thinking that the answer would be 18 but not so. Because the multiplication (*)
operator has higher precedence than the addition (+) operator. Hence, the expression first
evaluates 5*3 and then evaluates the remaining expression i.e. 1+15. Therefore, the answer
will be 16.

Let's see another example. Consider the following expression.

2. x + y * z / k

In the above expression, * and / operations are performed before + because of precedence. y
is multiplied by z before it is divided by k because of associativity.

b) Describe the role of the static keyword in Java? Explain with an example
program.
The static keyword in Java is used to indicate that a particular member (variable, method, or
nested class) belongs to the class itself, rather than instances of the class. Here's the
breakdown:
Static Variables

 Role: Shared among all instances of a class. If one instance modifies the static
variable, the change is reflected across all instances.
 Use Case: Often used for constants or to keep track of state shared by all objects.
Static Methods

 Role: Can be called without creating an instance of the class. Typically used for utility
or helper methods that don't depend on instance variables.
 Use Case: Useful for operations that don't require any data from an instance of the
class.

Static Blocks
 Role: Used for static initialization of a class. Executed when the class is loaded.
 Use Case: Often used for initializing static variables.

Example Program
Here's an example that demonstrates the use of static variables and methods:

public class StaticExample {


static int count = 0; // Static variable
// Static method
public static void incrementCount() {
count++;
}
public static void main(String[] args) {
// Accessing static method and variable without creating an instance
StaticExample.incrementCount();
System.out.println("Count after first increment: " + StaticExample.count);
StaticExample.incrementCount();
System.out.println("Count after second increment: " + StaticExample.count);
}
}

Explanation:
 Static Variable: count is shared among all instances of StaticExample. Since it is
static, we can access it using the class name.
 Static Method: incrementCount() modifies the static variable count. We call it directly
using the class name.

6.Explain the looping statements with examples.


The different types of looping statements in Java and see them in action:
1. for Loop
The for loop is used when you know exactly how many times you want to iterate through a
block of code.
Syntax:
for (initialization; condition; increment/decrement) {
// code to be executed
}
Example:
for (int i = 0; i < 5; i++) {
System.out.println("Iteration " + i);
}
2. while Loop
The while loop is used when you want to repeat a block of code as long as a condition is true.
Syntax:
while (condition) {
// code to be executed
}
Example:
int i = 0;
while (i < 5) {
System.out.println("Iteration " + i);
i++;
}
3. do-while Loop
The do-while loop is similar to the while loop, but it guarantees that the block of code will be
executed at least once.
Syntax:
do {
// code to be executed
} while (condition);

Example:
int i = 0;
do {
System.out.println("Iteration " + i);
i++;
} while (i < 5);
4. for-each Loop
The for-each loop is used to iterate over elements in an array or a collection.
Syntax:
for (type element : array/collection) {
// code to be executed
}
Example:
int[] numbers = {1, 2, 3, 4, 5};
for (int num : numbers) {
System.out.println("Number: " + num);
}
Key Differences:

 for Loop: Best when the number of iterations is known beforehand.


 while Loop: Best when the number of iterations is not known and depends on a
condition.
 do-while Loop: Guarantees at least one iteration, useful for menu-driven programs.
 for-each Loop: Ideal for iterating over arrays or collections without using an index

7.
a.Differentiate the primitive data types and wrapper classes in Java.
In Java, primitive data types and wrapper classes serve different purposes and have distinct
characteristics. Here’s a detailed explanation of their differences:

Primitive Data Types:

1. Definition: Primitive data types are the basic data types provided by Java. They are not
objects and are used to store simple values.
2. Types: Java has eight primitive data types:
- `byte` (8-bit integer)
- `short` (16-bit integer)
- `int` (32-bit integer)
- `long` (64-bit integer)
- `float` (32-bit floating-point)
- `double` (64-bit floating-point)
- `char` (16-bit Unicode character)
- `boolean` (true or false)
3. Characteristics:
- Efficiency: Primitive types are more efficient in terms of memory and performance since
they are stored directly in memory locations and do not involve the overhead of objects.
- Default Values: Each primitive type has a default value (e.g., `0` for numeric types,
`false` for `boolean`, and `'\u0000'` for `char`).
- Operations: Arithmetic and logical operations on primitive types are performed directly
by the CPU.

4. Usage: Primitive types are often used when performance is critical or when simple values
need to be stored and manipulated.

Wrapper Classes:

1. Definition: Wrapper classes are part of the `java.lang` package and provide an object
representation for each primitive data type. They allow primitives to be used in contexts that
require objects, such as collections.

2. Types: Each primitive type has a corresponding wrapper class:


- `byte` → `Byte`
- `short` → `Short`
- `int` → `Integer`
- `long` → `Long`
- `float` → `Float`
- `double` → `Double`
- `char` → `Character`
- `boolean` → `Boolean`

3. Characteristics:
- Object-Oriented: Wrapper classes allow primitives to be treated as objects. They provide
methods to perform operations, such as parsing strings into numbers or converting numbers
to binary strings.
- Default Values: Wrapper classes have a default value of `null` if they are not initialized.
- Boxing and Unboxing: Java supports automatic conversion between primitives and their
corresponding wrapper objects. This process is called autoboxing (primitives to wrapper
objects) and unboxing (wrapper objects to primitives).

4. Usage:
- Collections: Wrapper classes are used in Java collections (e.g., `ArrayList`, `HashMap`)
since collections can only store objects.
- Utility Methods: They provide utility methods for converting and manipulating data. For
example, `Integer.parseInt(String s)` can convert a string to an integer.

Key Differences:

- Memory and Performance: Primitive types are more memory-efficient and faster because
they are stored directly in memory, while wrapper classes involve additional overhead for
object management and boxing/unboxing operations.

- Default Values: Primitives have predefined default values, while wrapper class instances
default to `null`.
- Use in Collections: Primitive types cannot be used directly in Java collections, while
wrapper classes can.

- Utility Methods: Wrapper classes offer methods and constants that can be useful for
conversions and other operations, which primitives do not have.

In summary, primitives are fundamental and efficient for basic data storage, while wrapper
classes offer object-oriented features and compatibility with Java's object-based APIs and
collections.

b) Write a Java program that checks if a number is even or odd using if -else
statement
Java program to check if a number is even or odd using an if-else statement:

import java.util.Scanner;
public class EvenOddChecker {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter a number: ");
int number = scanner.nextInt();
if (number % 2 == 0) {
System.out.println(number + " is even.");
} else {
System.out.println(number + " is odd.");
}
scanner.close();
}
}
Explanation:


Scanner: Used to read input from the user.

if-else statement: Checks if the number is divisible by 2 (number % 2 == 0). If true,
the number is even; otherwise, it’s odd.
Output:
Prints whether the number is even or odd.

8.
a.What does the final keyword signify when used with variables, methods, and classes in
Java?

The final keyword is used to signify that something cannot be modified after it is initially
assigned. Its use with variables, methods, and classes has distinct implications:

1. Final Variables

When a variable is declared with the final keyword, its value cannot be changed once it has
been initialized. For primitive data types, this means that the value is constant after
assignment. For reference types (objects), it means that the reference itself cannot be
changed, though the object it points to can still be modified if its class is mutable.

Example:

Public class Final VariableExample {


Public static void main(String[] args) {
Final intx=10; // x cannot be changed after this assignment
// x = 20; // Error: cannot assign a value to final variable x

final List<String> list = newArrayList<>();


list.add("Hello"); // Allowed: modifying the object’s state
// list = new ArrayList<>(); // Error: cannot assign a new value to final reference
}
}

2. Final Methods

When a method is declared as final, it cannot be overridden by subclasses. This is used to


prevent a method from being changed or extended by subclasses, ensuring that the behavior
of the method remains consistent and secure.

Example:

Public class BaseClass {


Public final void display() {
System.out.println("Display from BaseClass");
}
}

Public class SubClass extends BaseClass {


// This would cause a compile-time error
// public void display() {
// System.out.println("Display from SubClass");
// }
}
3. Final Classes

When a class is declared as final, it cannot be subclassed or extended. This means that no
other class can inherit from a final class. Declaring a class as final is a way to ensure that its
implementation remains unchanged and to prevent the creation of subclasses.

Example:

Public final class FinalClass {


// Class definition
}

// This would cause a compile-time error


// public class SubClass extends FinalClass {
// }
Key Points

 Immutable Objects: Declaring a class as final can be used to create immutable


objects, where neither the class itself can be extended nor its fields (when declared as
final) can be modified after construction.
 Security and Design: Using final for methods and classes can be a design choice to
enforce security or to ensure that certain methods or classes are used exactly as
intended without alteration.
 Performance: The final keyword can also have performance implications. For
instance, final methods and variables may allow the JVM to perform certain
optimizations, such as in lining methods.

The final keyword in Java is a versatile tool used to enforce immutability and prevent
modification. It ensures that variables cannot be reassigned, methods cannot be overridden,
and classes cannot be subclassed.

b.How does the switch statement work in Java? Provide an example that uses switch to
select a day of the week.

Switch statements are similar to if-else-if statements. The switch statement contains multiple
blocks of code called cases and a single case is executed based on the variable which is
being switched. The switch statement is easier to use instead of if-else-if statements. It also
enhances the readability of the program.

Points to be noted about switch statement:

o The case variables can be int, short, byte, char, or enumeration. String type is also
supported since version 7 of Java
o Cases cannot be duplicate
o Default statement is executed when any of the case doesn't match the value of
expression. It is optional.
o Break statement terminates the switch block when the condition is satisfied.
It is optional, if not used, next case is executed.
o While using switch statements, we must notice that the case expression will be of the
same type as the variable. However, it will also be a constant value.

The syntax to use the switch statement is given below.

switch (expression){
case value1:
statement1;
break;
.
.
.
case valueN:
statementN;
break;
default:
default statement;
}

Consider the following example to understand the flow of the switch statement.

Student.java

public class Student implements Cloneable {


public static void main(String[] args) {
int num = 2;
switch (num){
case 0:
System.out.println("number is 0");
break;
case 1:
System.out.println("number is 1");
break;
default:
System.out.println(num);
}
}
}

Output:

While using switch statements, we must notice that the case expression will be of the same
type as the variable. However, it will also be a constant value. The switch permits only int,
string, and Enum type variables to be used.

Provide an example that uses switch to select a day of the week.

import java.util.Scanner;

public class DayOfWeekSelector {


public static void main(String[] args) {
// Create a Scanner object to read input from the user
Scanner scanner = new Scanner(System.in);

// Prompt the user to enter a number between 1 and 7


System.out.print("Enter a number (1-7) to select a day of the week: ");
int dayNumber = scanner.nextInt();

// Use a switch statement to determine the day of the week


String dayName;
switch (dayNumber) {
case 1:
dayName = "Sunday";
break;
case 2:
dayName = "Monday";
break;
case 3:
dayName = "Tuesday";
break;
case 4:
dayName = "Wednesday";
break;
case 5:
dayName = "Thursday";
break;
case 6:
dayName = "Friday";
break;
case 7:
dayName = "Saturday";
break;
default:
dayName = "Invalid input. Please enter a number between 1 and 7.";
break;
}

// Print the name of the day or the error message


System.out.println("The day of the week is: " + dayName);

// Close the scanner


scanner.close();
}
}
UNIT-II

PART:A

1.Write the purpose of the this keyword in Java

The this keyword in Java serves multiple essential purposes, providing a way for an object to
refer to itself within instance methods or constructors.
Here’s why it’s useful:
 Distinguishing Instance Variables:When local variables and instance variables have
the same name, this helps differentiate between them.
 Calling Other Constructors:this can be used to call another constructor within the
same class, promoting constructor chaining.
 Returning the Current Class Instance:Often used in method chaining, where methods
return the current object to allow successive method calls on the same instance.
 this is a versatile keyword that enhances clarity, maintains consistency, and supports
more sophisticated object-oriented design patterns in Java.
2.Define constructor and how does it differ from a regular method?
Constructor
A constructor in Java is a special method that is called when an object of a class is
instantiated. It initializes the new object and sets up its initial state.

Characteristics:

 Name: The constructor's name must be the same as the class name.
 No Return Type: Constructors do not have a return type, not even void.
 Automatic Invocation: Constructors are automatically called when a new instance of
the class is created using the new keyword.
Differences from a Regular Method:
Purpose:

 Constructor: Initializes the object.


 Method: Defines behavior or actions.
Name:

 Constructor: Must be the same as the class.


 Method: Any valid name.
Return Type:

 Constructor: None.
 Method: Must specify a return type or be void.
Invocation:

 Constructor: Automatically when an instance is created.


 Method: Called explicitly by the programmer.
3.How do you pass arguments by value and by reference in Java?
In Java, all arguments are passed by value, meaning a copy of the argument's value is passed
to the method. This can sometimes be confused with passing by reference because objects
and their references work a bit differently. Let me break it down:
Passing by Value
Primitives: When you pass a primitive data type (like int, char, etc.), a copy of the value is
passed to the method. Changes to the parameter inside the method do not affect the original
value.
Objects: Pass by Value of Reference
When you pass an object, what gets passed is the value of the reference to the object. This
means the method receives a copy of the reference, allowing it to modify the object’s state
but not the reference itself.
4.What is a recursive method, and when should it be used?
A recursive method in Java is a method that calls itself to solve a problem. This technique
divides a problem into smaller, more manageable sub-problems of the same type.
 Base Case: The condition under which the recursion stops, preventing infinite loops.
 Recursive Case: The part where the method calls itself with a modified parameter,
moving towards the base case.
When to Use Recursion:
 Divide and Conquer Problems: Problems that can be divided into smaller, similar sub-
problems, like mergesort or quicksort.
 Tree Traversals: Navigating hierarchical data structures, like file systems or
organization charts.
 Dynamic Programming: Problems where sub-problems overlap, like computing
Fibonacci numbers.
5.What is the purpose of declaring a class as final?
Declaring a class as final in Java means that the class cannot be subclassed. Here’s why you
might do this:
Purposes of final Classes:

 Security: Prevents inheritance to ensure critical classes aren't altered or extended in


unintended ways.
 Immutability: Often used for immutable classes, where the state of an object cannot
change after it's created (e.g., String class).
 Performance: The JVM can optimize method calls since it knows the class hierarchy
won't change.
6.What happens when you assign one object to another in Java?
When you assign one object to another in Java, what actually gets copied is the reference to
the object, not the object itself. This means both variables point to the same object in
memory. Any changes made to the object through one reference will be reflected when
accessing the object through the other reference.
 Reference Copying: MyObject obj2 = obj1; doesn’t create a new object. It makes obj2
refer to the same object as obj1.
 Shared State: Modifications through one reference (obj2.value = 20;) affect the object
accessed via the other reference (obj1.value).

PART:B
1.Demonstrate the access modifiers in Java with example programs.

Access modifiers help to restrict the scope of a class, constructor, variable, method, or data
member. It provides security, accessibility, etc to the user depending upon the access
modifier used with the element. Let us learn about Java Access Modifiers, their types, and
the uses of access modifiers in this article.

Types of Access Modifiers in Java

There are four types of access modifiers available in Java:

1. Default – No keyword required


2. Private
3. Protected
4. Public

1. Default Access Modifier

When no access modifier is specified for a class, method, or data member – It is said to be
having the default access modifier by default. The data members, classes, or methods that
are not declared using any access modifiers i.e. having default access modifiers are
accessible only within the same package.

In this example, we will create two packages and the classes in the packages will be having
the default access modifiers and we will try to access a class from one package from a class
of the second package.
Program 1:
// Java program to illustrate default modifier
packagep1;
// Class Geek is having Default access modifier
classGeek
{
voiddisplay()
{
System.out.println("Hello World!");
}
}

Program 2:
Java
// Java program to illustrate error while
// using class from different package with
// default modifier
packagep2;
importp1.*;

// This class is having default access modifier


classGeekNew
{
publicstaticvoidmain(Stringargs[])
{
// Accessing class Geek from package p1
Geekobj=newGeek();

obj.display();
}
}

Output:
Compile time error

2. Private Access Modifier

The private access modifier is specified using the keyword private. The methods or data
members declared as private are accessible only within the class in which they are
declared.
 Any other class of the same package will not be able to access these members.
 Top-level classes or interfaces can not be declared as private because
o private means “only visible within the enclosing class”.
o protected means “only visible within the enclosing class and any subclasses”
Hence these modifiers in terms of application to classes, apply only to nested classes and
not on top-level classes
In this example, we will create two classes A and B within the same package p1. We will
declare a method in class A as private and try to access this method from class B and see
the result.

// Java program to illustrate error while


// Using class from different package with

// Private Modifier
packagep1;

// Class A
classA{
privatevoiddisplay()
{
System.out.println("GeeksforGeeks");
}
}

// Class B
classB{
publicstaticvoidmain(Stringargs[])
{
Aobj=newA();
// Trying to access private method
// of another class
obj.display();
}
}

Output:
error: display() has private access in A
obj.display();

3. Protected Access Modifier

The protected access modifier is specified using the keyword protected.

The methods or data members declared as protected are accessible within the same
package or subclasses in different packages.
In this example, we will create two packages p1 and p2. Class A in p1 is made public, to
access it in p2. The method display in class A is protected and class B is inherited from
class A and this protected method is then accessed by creating an object of class B.

Program 1:
// Java Program to Illustrate
// Protected Modifier
packagep1;

// Class A
publicclassA{
protectedvoiddisplay()
{
System.out.println("GeeksforGeeks");
}
}

Program 2:

// Java program to illustrate


// protected modifier
packagep2;

// importing all classes in package p1


importp1.*;

// Class B is subclass of A
classBextendsA{
publicstaticvoidmain(Stringargs[])
{
Bobj=newB();
obj.display();
}
}

Output:
GeeksforGeeks

4.Public Access modifier

The public access modifier is specified using the keyword public.


 The public access modifier has the widest scope among all other access modifiers.
 Classes, methods, or data members that are declared as public are accessible from
everywhere in the program. There is no restriction on the scope of public data members.

Program 1:
// Java program to illustrate
// public modifier
packagep1;
publicclassA
{
publicvoiddisplay()
{
System.out.println("GeeksforGeeks");
}
}

Program 2:
packagep2;
importp1.*;
classB{
publicstaticvoidmain(Stringargs[])
{
Aobj=newA();
obj.display();
}
}

Output:
GeeksforGeeks

Important Points:
 If other programmers use your class, try to use the most restrictive access level that
makes sense for a particular member. Use private unless you have a good reason not to.
 Avoid public fields except for constants.

2.
a. Explain the concept of classes and objects in Object-Oriented Programming (OOP).

ANSWER:

Class:
A Java class is the template from which objects are created. It is a blueprint for an object. A
class is created using the keyword class.

Classes can contain methods, which are actions that the class can perform, and fields, which
are variables that contain data used by the class. When we create a new object, we create an
instance of a class.

Declaring a class:

The name of the class should be followed by the keyword class. The body of the class is
enclosed within curly braces {}. All the data members and member functions of the class are
declared inside the body of the class.

Syntax

To declare a class in Java, use the following format:

access_modifier class ClassName {


// class body
}

Code example

Let's look at the example of the Java class below:

publicclass Person {
// fields
String name;

// methods
voidprintName() {
System.out.println(name);
}
}

This Java class has the name Person. The keyword public is an access modifier, which
determines who can access this class. In this case, the class is accessible by any other class.
Inside the body of the class, we can declare fields and methods.

Fields:

Fields are variables that contain data. In the example above, we have a field named name.
Fields are usually declared at the top of the class before any methods.

Methods:

Methods are functions that perform actions. In the example above, we have a method
named printName(), which prints the value of the name field to the screen. Methods are
usually declared after the fields in a class.

Creating an object:
To use a class, we need to create an instance of the class. To do this, we use the
keyword new. For example, if we want to create an instance of the Person class, we would
use the following code:

Person myObj =newPerson();

This creates an object called myObj, which is an instance of the Person class.

Accessing the fields and methods of an object:

We can then access the fields and methods of this object using the dot notation, like this:

myObj.name = "John Doe";


myObj.printName();

This set the name field to "John Doe" and then call the printName() method, which print the
value of the name field to the screen.

class Person {
// fields
String name;

// methods
voidprintName() {
System.out.println(name);
}
}
class Main {
publicstaticvoidmain( String args[] ) {
Person myObj =newPerson();
myObj.name ="John Doe";
myObj.printName();
}
}

 In the code above, we create a class named Person that has a field name and a
method printName().
 In the main() method, we create an object of the class and assign a value to the name
field.
 Finally, we invoke the printName() method on the object to print the value of the
name.

b) Discuss about arguments passing by value and reference with an example.

ANSWER:

In Java, all arguments are passed by value, which means that when a method is called, a copy
of the argument’s value is passed. This can sometimes be confused with passing by reference
because of how objects and their references work. Here’s the breakdown:
Passing by Value

Primitives: When you pass a primitive data type to a method, a copy of the value is passed.
Changes to the parameter inside the method do not affect the original value.

Example with Primitives:

public class PassByValueExample {

public static void main(String[] args) {

int a = 5;

modifyPrimitive(a);

System.out.println("After modifyPrimitive: " + a); // a remains 5

public static void modifyPrimitive(int num) {

num = 10; // This change is local to the method

Output:

After modifyPrimitive: 5

Objects: Pass by Value of Reference

When you pass an object to a method, what gets passed is the value of the reference to the
object (not the actual object itself). This means the method can change the object’s state but
cannot change the object’s reference.

Example with Objects:

class MyObject {

int value

MyObject(int value) {

this.value = value;

}
public class PassByValueExample {

public static void main(String[] args) {

MyObject obj = new MyObject(5);

modifyObject(obj);

System.out.println("After modifyObject: " + obj.value); // obj.value is 10

public static void modifyObject(MyObject o) {

o.value = 10; // This change affects the original object

Output:

After modifyObject: 10

Key Points:

 Primitives: The method gets a copy of the actual value.


 Objects: The method gets a copy of the reference, and can thus modify the object’s
state.

3.Define nested classes and explain their types (static nested classes and inner classes).
ANSWER:

Inner class refers to the class that is declared inside class or interface.

There are certain advantages associated with inner classes are as follows:

 Making code clean and readable.


 Private methods of the outer class can be accessed, so bringing a new dimension and
making it closer to the real world.
 Optimizing the code module.

Types of Inner Classes

There are basically four types of inner classes in java.


1. Nested Inner Class
2. Method Local Inner Classes
3. Static Nested Classes
4. Anonymous Inner Classes

Type 1: Nested Inner Class

It can access any private instance variable of the outer class. Like any other instance
variable, we can have access modifier private, protected, public, and default modifier. Like
class, an interface can also be nested and can have access specifiers.

Example 1A

// Java Program to Demonstrate Nested class

// Class 1
// Helper classes
classOuter{

// Class 2
// Simple nested inner class
classInner{

// show() method of inner class


publicvoidshow()
{

// Print statement
System.out.println("In a nested class method");
}
}
}

// Class 2
// Main class
classMain{

// Main driver method


publicstaticvoidmain(String[]args)
{

// Note how inner class object is created inside


// main()
Outer.Innerin=newOuter().newInner();

// Calling show() method over above object created


in.show();
}
}

Output
In a nested class method
Note: We can not have a static method in a nested inner class because an inner class is
implicitly associated with an object of its outer class so it cannot define any static method
for itself. For example, the following program doesn’t compile. But Since JAVA Version 16
we can have static members in our inner class also.

Example 1B

// Java Program to Demonstrate Nested class


// Where Error is thrown

// Class 1
// Outer class
classOuter{

// Method defined inside outer class


voidouterMethod()
{

// Print statement
System.out.println("inside outerMethod");
}

// Class 2
// Inner class
classInner{

// Main driver method


publicstaticvoidmain(String[]args)
{

// Display message for better readability


System.out.println("inside inner class Method");
}
}
}
Output:

An interface can also be nested and nested interfaces have some interesting properties. We
will be covering nested interfaces in the next post.

Type 2: Method Local Inner Classes


Inner class can be declared within a method of an outer class which we will be illustrating
in the below example where Inner is an inner class in outerMethod().

Example 1
// Java Program to Illustrate Inner class can be
// declared within a method of outer class

// Class 1
// Outer class
classOuter{

// Method inside outer class


voidouterMethod()
{

// Print statement
System.out.println("inside outerMethod");

// Class 2
// Inner class
// It is local to outerMethod()
classInner{

// Method defined inside inner class


voidinnerMethod()
{

// Print statement whenever inner class is


// called
System.out.println("inside innerMethod");
}
}

// Creating object of inner class


Innery=newInner();

// Calling over method defined inside it


y.innerMethod();
}
}

// Class 3
// Main class
classGFG{

// Main driver method


publicstaticvoidmain(String[]args)
{
// Creating object of outer class inside main()
// method
Outerx=newOuter();

// Calling over the same method


// as we did for inner class above
x.outerMethod();
}
}

Output
inside outerMethod
inside innerMethod

Method Local inner classes can’t use a local variable of the outer method until that local
variable is not declared as final. For example, the following code generates a compiler
error.
Note: “x” is not final in outerMethod() and innerMethod() tries to access it.

Example 2
Java
classOuter{
voidouterMethod(){
intx=98;
System.out.println("inside outerMethod");
classInner{
voidinnerMethod(){
System.out.println("x= "+x);
}
}
Innery=newInner();
y.innerMethod();
}
}
classMethodLocalVariableDemo{
publicstaticvoidmain(String[]args){
Outerx=newOuter();
x.outerMethod();
}
}

Output
inside outerMethod
x= 98
Note: Local inner class cannot access non-final local variable till JDK 1.7. Since JDK 1.8,
it is possible to access the non-final local variable in method local inner class.
But the following code compiles and runs fine (Note that x is final this time)
Example 3
Java
classOuter{
voidouterMethod(){
finalintx=98;
System.out.println("inside outerMethod");
classInner{
voidinnerMethod(){
System.out.println("x = "+x);
}
}
Innery=newInner();
y.innerMethod();
}
}
classMethodLocalVariableDemo{
publicstaticvoidmain(String[]args){
Outerx=newOuter();
x.outerMethod();
}
}

Output
inside outerMethod
x = 98
The main reason we need to declare a local variable as a final is that the local variable lives
on the stack till the method is on the stack but there might be a case the object of the inner
class still lives on the heap.

Method local inner class can’t be marked as private, protected, static, and transient but can
be marked as abstract and final, but not both at the same time.

Type 3: Static Nested Classes

Static nested classes are not technically inner classes. They are like a static member of
outer class.

Example

// Java Program to Illustrate Static Nested Classes

// Importing required classes


importjava.util.*;

// Class 1
// Outer class
classOuter{
// Method
privatestaticvoidouterMethod()
{

// Print statement
System.out.println("inside outerMethod");
}

// Class 2
// Static inner class
staticclassInner{

publicstaticvoiddisplay()
{

// Print statement
System.out.println("inside inner class Method");

// Calling method inside main() method


outerMethod();
}
}
}

// Class 3
// Main class
classGFG{

// Main driver method


publicstaticvoidmain(Stringargs[])
{

// Calling method static display method rather than an instance of that class.
Outer.Inner.display();
}
}

Output
inside inner class Method
inside outerMethod

Type 4: Anonymous Inner Classes

Anonymous inner classes are declared without any name at all. They are created in two
ways.
 As a subclass of the specified type
 As an implementer of the specified interface
Way 1: As a subclass of the specified type

Example:
Java
// Java Program to Illustrate Anonymous Inner classes
// Declaration Without any Name
// As a subclass of the specified type

// Importing required classes


importjava.util.*;

// Class 1
// Helper class
classDemo{

// Method of helper class


voidshow()
{
// Print statement
System.out.println(
"i am in show method of super class");
}
}

// Class 2
// Main class
classFlavor1Demo{

// An anonymous class with Demo as base class


staticDemod=newDemo(){
// Method 1
// show() method
voidshow()
{
// Calling method show() via super keyword
// which refers to parent class
super.show();

// Print statement
System.out.println("i am in Flavor1Demo class");
}
};

// Method 2
// Main driver method
publicstaticvoidmain(String[]args)
{
// Calling show() method inside main() method
d.show();
}
}

Output
i am in show method of super class
i am in Flavor1Demo class

In the above code, we have two classes Demo and Flavor1Demo. Here demo act as a super-
class and the anonymous class acts as a subclass, both classes have a method show(). In
anonymous class show() method is overridden.

The benefits of using inner classes in Java are:

 Encapsulation: Inner classes can access private variables and methods of the outer
class. This helps to achieve encapsulation and improves code readability.
 Code Organization: Inner classes allow you to group related code together in one
place. This makes your code easier to understand and maintain.
 Better Access Control: Inner classes can be declared as private, which means that
they can only be accessed within the outer class. This provides better access control
and improves code security.
 Callbacks: Inner classes are often used for implementing callbacks in event-driven
programming. They provide a convenient way to define and implement a callback
function within the context of the outer class.
 Polymorphism: Inner classes can be used to implement polymorphism. You can
define a class hierarchy within the outer class and then create objects of the inner
classes that implement the different subclasses.
 Reduced Code Complexity: Inner classes can reduce the complexity of your code
by encapsulating complex logic and data structures within the context of the outer
class.

4.Discuss the purpose of this keyword in Java with its usage with example.
ANSWER:

The this keyword is a reference variable that refers to the current object. It is primarily used
to differentiate between instance variables and parameters, access class methods, and for
constructor chaining. Here are the main scenarios in which this is used:

1. Distinguishing Instance Variables from Parameters

When the parameter name is the same as the instance variable name, this helps to clarify that
you are referring to the instance variable.
Example:

java
Copy code
publicclassDog {
private String name;

publicDog(String name) {
this.name = name; // 'this.name' refers to the instance variable
}
}

In this example, this.name refers to the instance variable name, while the parameter name is
the one passed to the constructor.

2. Accessing Class Methods

You can use this to call methods of the current object. This can be particularly useful when
method names might be ambiguous.

Example:

java
Copy code
publicclassDog {
publicvoidbark() {
System.out.println("Woof!");
}

publicvoidperformAction() {
this.bark(); // Calls the bark method of the current object
}
}

3. Constructor Chaining

this can be used to call one constructor from another constructor in the same class. This is
known as constructor chaining, which allows you to reuse constructor code.

Example:

java
Copy code
publicclassDog {
private String name;
private String breed;

publicDog(String name) {
this(name, "Unknown"); // Calling another constructor
}
publicDog(String name, String breed) {
this.name = name;
this.breed = breed;
}
}

In this example, the first constructor calls the second constructor using this(name,
"Unknown").

4. Returning the Current Object

You can return the current object from a method using this, which can be useful in method
chaining.

Example:

java
Copy code
publicclassDog {
private String name;

public Dog setName(String name) {


this.name = name;
returnthis; // Returns the current object
}
}

// Usage
Dogdog=newDog().setName("Buddy");

5.Explain different types of Constructors and constructor overloading with an


example.
ANSWER:

A constructor is a special method that is called when an object of a class is created. Its
primary role is to initialize the newly created object, setting its initial state by assigning
values to its fields.

Key Features of Constructors

1. Same Name as Class: A constructor must have the same name as the class.
2. No Return Type: Constructors do not have a return type, not even void.
3. Can Be Overloaded: You can have multiple constructors in a class with different
parameter lists, which is known as constructor overloading.
Role of Constructors in Object Initialization

Constructors are crucial for initializing an object’s state when it is created. They allow you to
set initial values for instance variables and perform any setup necessary before the object is
used.

Example of a Constructor:

publicclassDog {
String name;
String breed;

// Constructor
publicDog(String name, String breed) {
this.name = name; // Initialize instance variables
this.breed = breed;
}
}

// Creating an object
DogmyDog=newDog("Buddy", "Golden Retriever");

In this example, when myDog is created, the constructor initializes its name and breed fields.

Overloaded Constructors

Constructor overloading allows a class to have more than one constructor, each with a
different parameter list. This enables you to create objects in different ways, depending on the
arguments passed.

Example of Overloaded Constructors:

publicclassDog {
String name;
String breed;
int age;

// Constructor with two parameters


publicDog(String name, String breed) {
this.name = name;
this.breed = breed;
this.age = 0; // Default age
}

// Constructor with three parameters


publicDog(String name, String breed, int age) {
this.name = name;
this.breed = breed;
this.age = age; // Initialize age
}
}

// Creating objects using different constructors


Dogdog1=newDog("Buddy", "Golden Retriever"); // Calls the first constructor
Dogdog2=newDog("Max", "Beagle", 3); // Calls the second constructor

6.
a.Discuss the concept of method overloading in Java.
ANSWER:

Method overloading in Java is a feature that allows a class to have more than one method
with the same name, provided that the methods have different parameter lists. This means
that the methods can differ in the number of parameters, the types of parameters, or both.
Method overloading enhances the readability and usability of the code.

Key Characteristics of Method Overloading

1. Same Method Name: All overloaded methods share the same name.
2. Different Parameter Lists: They must have different parameter types, numbers, or
both. The return type can be different, but it alone does not differentiate overloaded
methods.
3. Compile-Time Polymorphism: Method overloading is a compile-time
polymorphism, meaning the method to be invoked is determined at compile time
based on the method signatures.

Benefits of Method Overloading

1. Improved Code Readability: Using the same name for related methods makes the
code easier to read and understand.
2. Enhanced Flexibility: It allows methods to handle different types and numbers of
inputs, making the code more versatile.
3. Simplified Maintenance: Having a unified method name can simplify code
maintenance and refactoring.

Example of Method Overloading

Here’s an example that illustrates method overloading:

publicclassMathOperations {

// Overloaded method to add two integers


publicintadd(int a, int b) {
return a + b;
}

// Overloaded method to add three integers


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

// Overloaded method to add two doubles


publicdoubleadd(double a, double b) {
return a + b;
}
}

// Usage
publicclassMain {
publicstaticvoidmain(String[] args) {
MathOperationsmath=newMathOperations();

// Calling overloaded methods


System.out.println(math.add(5, 10)); // Calls the first method
System.out.println(math.add(5, 10, 15)); // Calls the second method
System.out.println(math.add(5.5, 10.5)); // Calls the third method
}
}

Rules for Method Overloading

1. Different Parameter Types: Overloaded methods must have at least one parameter
that differs in type.
2. Different Number of Parameters: Overloaded methods can have a different number
of parameters, regardless of their types.
3. Return Type: The return type alone is not sufficient to overload methods; the
parameter list must differ.

b.Discuss the concept of method overriding in Java.


ANSWER:

Method Overriding in Java

Method overriding is a feature in Java that allows a subclass (child class) to provide a
specific implementation of a method that is already defined in its superclass (parent class).
This allows the subclass to modify or extend the behavior of that method while maintaining
the same method signature (name, return type, and parameters).

Key Characteristics of Method Overriding

1. Same Method Signature: The overridden method in the subclass must have the same
name, return type, and parameter list as the method in the superclass.
2. Inheritance: Method overriding can only occur in a class hierarchy. The subclass
must inherit from the superclass.
3. Dynamic Polymorphism: Method overriding is a way to achieve runtime
polymorphism in Java. The method that gets executed is determined at runtime based
on the object type.
4. Use of the @Override Annotation: While not required, it is a good practice to use
the @Override annotation above the overridden method. This helps in verifying that
the method is indeed overriding a superclass method, providing compile-time
checking.

Example of Method Overriding

Here’s an example demonstrating method overriding:

classAnimal {
publicvoidsound() {
System.out.println("Animal makes a sound");
}
}

classDogextendsAnimal {
@Override
publicvoidsound() { // Overriding the sound method
System.out.println("Dog barks");
}
}

classCatextendsAnimal {
@Override
publicvoidsound() { // Overriding the sound method
System.out.println("Cat meows");
}
}

publicclassMain {
publicstaticvoidmain(String[] args) {
AnimalmyDog=newDog();
AnimalmyCat=newCat();
myDog.sound(); // Output: Dog barks
myCat.sound(); // Output: Cat meows
}
}

Benefits of Method Overriding

1. Polymorphism: Method overriding allows a method to behave differently based on


the object invoking it, enabling polymorphic behavior.
2. Flexibility and Extensibility: Subclasses can provide specific implementations of
methods, enhancing flexibility and making it easier to extend and maintain the code.
3. Code Reusability: By inheriting from a superclass and overriding its methods, you
can reuse existing code while tailoring it to the needs of the subclass.

Rules for Method Overriding

1. Access Modifiers: The overriding method must have the same or a more accessible
visibility modifier. For example, a protected method in the superclass can be
overridden as protected or public in the subclass, but not as private.
2. Return Type: The return type of the overriding method must be the same as, or a
subtype of, the return type declared in the original overridden method (this is known
as covariant return types).
3. Non-static Methods: Only instance methods can be overridden; static methods
cannot be overridden (they can be hidden).
4. Final Methods: A method declared as final in the superclass cannot be overridden in
any subclass.
5. Abstract Methods: If the superclass has an abstract method, the subclass must
provide an implementation for that method unless the subclass is also abstract.

7.
Define recursive methods and discuss their use cases.
ANSWER:

Recursive Methods

A recursive method is a method that calls itself in order to solve a problem. This technique
is often used to break down complex problems into simpler subproblems. Each recursive call
works toward a base case, which stops the recursion to prevent infinite loops.

Key Characteristics of Recursive Methods

1. Base Case: A condition under which the recursion stops. This prevents the method
from calling itself indefinitely.
2. Recursive Case: The part of the method where the function calls itself with modified
arguments, gradually moving toward the base case.

Example of a Recursive Method

Here’s a simple example that calculates the factorial of a number using recursion:

publicclassFactorial {

// Recursive method to calculate factorial


publicintfactorial(int n) {
// Base case
if (n == 0) {
return1;
}
// Recursive case
return n * factorial(n - 1);
}

publicstaticvoidmain(String[] args) {
Factorialfact=newFactorial();
intresult= fact.factorial(5); // 5! = 5 * 4 * 3 * 2 * 1 = 120
System.out.println("Factorial: " + result);
}
}

Use Cases of Recursive Methods

1. Mathematical Calculations: Recursion is commonly used for problems such as


calculating factorials, Fibonacci numbers, and powers of numbers.
o Example: Calculating Fibonacci numbers can be elegantly expressed with
recursion.
2. Tree Traversals: Recursive methods are ideal for traversing tree structures, such as
binary trees. Each node can be processed recursively.
o Example: Depth-first search (DFS) on trees.
3. Graph Algorithms: Many graph algorithms, like depth-first search (DFS) and
backtracking algorithms, can be implemented using recursion.
o Example: Solving mazes or puzzles like the N-Queens problem.
4. Sorting Algorithms: Some sorting algorithms, such as quicksort and mergesort,
utilize recursion to sort elements.
o Example: Mergesort divides the array into halves recursively until single
elements are sorted, then merges them back together.
5. Dynamic Programming: Recursive methods are often used in dynamic programming
solutions to solve problems like the knapsack problem or longest common
subsequence.
o Example: Memoization is used alongside recursion to optimize these
problems.

Advantages of Recursion

 Simplicity: Recursive solutions can be simpler and more intuitive than their iterative
counterparts, making them easier to write and understand.
 Reduced Code Size: Recursive methods can lead to shorter code because the same
logic can be expressed in fewer lines.

Disadvantages of Recursion

 Performance: Recursive methods can lead to high memory usage due to call stack
growth, especially if the recursion depth is significant.
 Risk of Stack Overflow: If the base case is not defined correctly or the recursion
goes too deep, it can lead to a stack overflow error.
8.Explain the roles of final and static keywords when applied to methods.
ANSWER:

The final and static keywords serve distinct purposes when applied to methods. Here’s a
detailed explanation of their roles:

final Keyword

When a method is declared as final, it cannot be overridden by subclasses. This has several
implications:

Roles of final Methods

Prevent Modification: Marking a method as final ensures that its implementation remains
unchanged in any subclass. This is useful for methods that provide essential functionality that
should not be altered.

1. Security: By preventing overriding, final methods can help maintain the integrity of a
class’s behavior, particularly in sensitive or critical sections of code.
2. Performance Optimization: The Java compiler can make certain optimizations for
final methods since it knows they cannot be overridden.

Example:

classBaseClass {
publicfinalvoiddisplay() {
System.out.println("This method cannot be overridden.");
}
}
classSubClassextendsBaseClass {
// The following would cause a compile-time error:
// public void display() {
// System.out.println("Attempting to override.");
// }
}

static Keyword

When a method is declared as static, it belongs to the class rather than any instance of the
class. This means that it can be called without creating an instance of the class.
Roles of static Methods

1. Class-Level Accessibility: Static methods can be called on the class itself, without
needing an object. This is useful for utility or helper methods that don't rely on
instance variables.
2. Memory Management: Since static methods are associated with the class, they can
help save memory by not requiring an instance of the class for invocation.
3. No Access to Instance Variables: Static methods cannot access instance variables or
instance methods directly. They can only access static variables and methods.
4. Method Overriding: Static methods can be hidden but not overridden. If a static
method in a subclass has the same name and parameters as a static method in the
superclass, it is considered hidden, not overridden.

Example:

classUtility {
publicstaticvoidprintMessage() {
System.out.println("This is a static method.");
}
}
// Calling a static method
Utility.printMessage(); // No need to create an instance of Utility
UNIT-III
1.What is a dynamic array, and how can you change the size of an array dynamically in Java?

Dynamic array

A dynamic array is an array with a big improvement: automatic resizing. One limitation of arrays
is that they're fixed size, meaning you need to specify the number of elements your array will
hold ahead of time. A dynamic array expands as you add more elements. So you don't need to
determine the size ahead of time.

Dynamic Change of Array Size

Java allows us to change the array size dynamically during the execution of the program. In this process
the array destroyed along with the values of elements. In the following program, the array contains 5
elements. It is again defined with 10 elements with the same array name.

2. How can arrays be used as vectors in Java?

• Similar to Arrays, vectors are another kind of data structure that is used for storing
information.
• Using vector, we can implement a dynamic array.
• The following are the vector constructors:
• Vector() creates a default vector having an initial size of 10.
• Vector(int size) creates a vector whose initial capacity is specified by size.
• Example
Vector vec = new Vector(5); // declaring with initial size of 5
• Vector(int size, int incr) creates a vector with initial capacity specified by size and
increment is specified by incr.
• The increment is the number of elements added in each reallocation cycle.
3.What is the universal superclass in Java, and why is it called that?
Universal Super Class : “ Object ” Class
 Object class is a special class and it is at the top of the class hierarchy tree.
 It is the parent class or super class of all in Java.
 Hence, it is called Universal super class.
 Object is at the root of the tree and every other class can be directly or indirectly
derived from the Object class.
4. How can you prevent a class from being inherited in Java?
To prevent inheritance, use the keyword "final" when creating the class. The designers of the
String class realized that it was not a candidate for inheritance and have prevented it from being
extended.

5.What are default methods in interfaces, and why are they used?

• The enhancement in Java 8 allowing the interface to have full definition of default methods and static
methods that are implicitly inherited by the class implementing the interface.

• Java allows only one super class, by using default methods in interface java allows that interface
behaves just like an abstract super-class.

• New functionality can be added to the interface, which is inherited by classes implementing the
interface.

6.How can interfaces inherit from other interfaces?

Interfaces can inherit from one or more interfaces. The derived interface inherits the members from its
base interfaces. A class that implements a derived interface must implement all members in the derived
interface, including all members of the derived interface's base interfaces.
PART-B

1.a. Define an array. How can we initialize arrays? Explain.

An array is a structure consisting of a group of elements of the same type. When a large number of data
values of the same type are to be processed, it can be done efficiently by declaring an array of the data
type.

The complete data gets represented by a single object with a single name in the computer memory. An
array is a sequence of objects of the same data type. The type of data that the array holds becomes the
type of the array, which is also called base type of the array.

If the array elements have values in whole numbers, that is, of type int, the type of array is also int. If it
is a sequence of characters, the type of array is char;

If it is an array of floating point numbers of type float, the type of array is also float.An array can hold
objects of a class but cannot be a mixture of different data types.
initialization of Arrays: An array may be initialized by mentioning the values in braces and separated by
commas.

For example, the array pencils may be initialized as below:

int pencils [] = {4, 6, 8, 3};

b.Write a Java program to perform Binary search.

import java.util.Scanner;
class BinarySearch
{
public static void main(String args[])
{
boolean b =false;
int[] array = {15, 20, 43, 45, 76, 80, 86, 88, 90, 94, 96, 98};
int length= array.length;
Scanner in = new Scanner(System.in);
System.out.println("Enter the number which you want to search");
int key = in.nextInt();
int beginning,end,mid;
beginning =0;
end = length-1;
while( beginning <=end)
{
if(beginning == end && array[end]!=key)
{
System.out.println("Your number is not in the array");
break;
}
mid = (beginning +end )/2;
if(array[mid]==key)
{
System.out.println("Your number is in the array at index = " + mid);
break;
}
else if(array[mid]<key)
beginning = mid+1;
else
end = mid-1;
}
}
}
Output:
C:\>javac BinarySearch.java
C:\>java BinarySearch
Enter the number which you want to search
45
Your number is in the array at index = 3
C:\>java BinarySearch
Enter the number which you want to search
96
Your number is in the array at index = 10
C:\>java BinarySearch
Enter the number which you want to search
783
Your number is not in the array

2.

a. Explain declaration, initialization and accessing elements in two–dimensional array.

Two-dimensional Arrays

• An array may hold other arrays as its elements.

• If the elements of an array are one-dimensional arrays, the array becomes a two-dimensional array.

• A two-dimensional array is treated as an array of arrays, and each of these arrays may have a different
number of elements.

E.g. Matrices are two-dimensional arrays.

• List of telephone numbers is another such example.

• A two-dimensional array may be defined as:

int telNumber [][] = new int [5][10];

• The array will contain 5 numbers each having 10 digits.

• A two-dimensional array may as well be defined and initialized as

int arrayB [ ][ ] = {{11, 12, 13 }, {7, 6, 4}};

• The two-dimensional array may as well be declared as

int arrayC [][] = new int[2][3]{{1,2,3}. {4.5.6},{7,8,9}}


Example: TwoDimArray.java

class TwoDimArray

public static void main(String[] args)

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

for(int[] y : num2D)

for(int x : y)

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

System.out.println();

Output:

C:\ >javac TwoDimArray.java

C:\ >java TwoDimArray

123

456

789

b. Write a Java program to perform matrix multiplication.

import java.util.Scanner;

public class MatrixMultiplicationExample {

public static void main(String args[]) {


int row1, col1, row2, col2;
Scanner s = new Scanner(System.in);
// Input dimensions of First Matrix: A
System.out.print("Enter number of rows in first matrix: ");
row1 = s.nextInt();

System.out.print("Enter number of columns in first matrix: ");


col1 = s.nextInt();

// Input dimensions of second matrix: B


System.out.print("Enter number of rows in second matrix: ");
row2 = s.nextInt();

System.out.print("Enter number of columns in second matrix: ");


col2 = s.nextInt();

// Requirement check for matrix multiplication


if (col1 != row2) {
System.out.println("Matrix multiplication is not possible");
return;
}

int a[][] = new int[row1][col1];


int b[][] = new int[row2][col2];
int c[][] = new int[row1][col2];

// Input the values of matrices


System.out.println("\nEnter values for matrix A : ");
for (int i = 0; i < row1; i++) {
for (int j = 0; j < col1; j++) a[i][j] = s.nextInt();
}
System.out.println("\nEnter values for matrix B : ");
for (int i = 0; i < row2; i++) {
for (int j = 0; j < col2; j++) b[i][j] = s.nextInt();
}

// Perform matrix multiplication


// Using for loop
System.out.println("\nMatrix multiplication is : ");
for (int i = 0; i < row1; i++) {
for (int j = 0; j < col2; j++) {
// Initialize the element C(i,j) with zero
c[i][j] = 0;

// Dot product calculation


for (int k = 0; k < col1; k++) {
c[i][j] += a[i][k] * b[k][j];
}

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


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

Output;
Enter number of rows in first matrix: 3
Enter number of columns in first matrix: 2
Enter number of rows in second matrix: 2
Enter number of columns in second matrix: 4

Enter values for matrix A :


12
34
56

Enter values for matrix B :


7 8 9 10
11 12 13 14

Matrix multiplication is :
29 32 35 38
65 72 79 86
101 112 123 134

3.a. Write short notes on Interfaces and functional interfaces in Java.

INTERFACE;

• An interface also introduces a new reference type.

• An interface represents an encapsulation of constants, classes, interfaces, and one or more abstract
methods that are implemented by a class.

• An interface does not contain instance variables.

• An interface cannot implement itself; it has to be implemented by a class.

• The methods in an interface have no body.

• Only headers are declared with the parameter list that is followed by a semicolon.

• The class that implements the interface has to have full definitions of all the abstract methods in the
interface.
• An interface can be implemented by any number of classes with their own definitions of the methods
of the interface

Functional Interfaces

• In Java SE8, a new package java.util.function on functional interfaces has been introduced for writing
Lambda functions.

• Functional interfaces are interfaces with one abstract method.

• They are also called SAM or single abstract method type.

• However, a functional interface can have more than one static and default methods.

• By adding the above annotation, it can be helpful in detecting compile time errors.

• If the functional interface contains more than one abstract method, the compiler will throw an error.

b.Demonstrate the Nested Interfaces using an example program.

Nested Interfaces

• An interface may be declared as a member of a class or in another interface.

• In the capacity of a class member, it can have the attributes that are applicable to otherclassmembers.

• In other cases, an interface can only be declared as public or with default (no-access modifier) access
Example: NestedInterface.java
interface OuterX
{
int x = 10;
public interface InnerY
{
int y = 20;
}
}
class A implements OuterX, OuterX.InnerY
{
void display()
{
System.out.println("Class-A Method : x = "+ x + " y = " + y);
}
}
class NestedInterface
{
public static void main(String args[])
{
//calling class-A method
A objA = new A();
objA.display();
}
}
Output:
C:\ >javac NestedInterface.java
C:\ >java NestedInterface
Class-A Method : x = 10 y = 20

4.

a) Write a java program to sort the elements of an array in descending order.


1. public class SortDsc {
2. public static void main(String[] args) {
3. //Initialize array
4. int [] arr = new int [] {5, 2, 8, 7, 1};
5. int temp = 0;
6.
7. //Displaying elements of original array
8. System.out.println("Elements of original array: ");
9. for (int i = 0; i < arr.length; i++) {
10. System.out.print(arr[i] + " ");
11. }
12.
13. //Sort the array in descending order
14. for (int i = 0; i < arr.length; i++) {
15. for (int j = i+1; j < arr.length; j++) {
16. if(arr[i] < arr[j]) {
17. temp = arr[i];
18. arr[i] = arr[j];
19. arr[j] = temp;
20. }
21. }
22. }
23.
24. System.out.println();
25.
26. //Displaying elements of array after sorting
27. System.out.println("Elements of array sorted in descending order: ");
28. for (int i = 0; i < arr.length; i++) {
29. System.out.print(arr[i] + " ");
30. }
31. }
32. }
Output:

Elements of original array:


52871
Elements of array sorted in descending order:
87521

b) What is meant by dynamic method dispatch? Explain with a program.

Dynamic Method Dispatch

It is a mechanism by which runtime polymorphism is achieved for overridden method in Java.

It is implemented through super class reference. A super class reference can refer to an object of its
subclass.

A base class pointer can refer to derived class object. There may be many subclasses inherited from
a super class.

Each subclass has its own version or definition of the overridden method.

The dynamic method dispatch chooses the right version of the method corresponding to the object
reference.

In the method, first a reference variable of super class is created.

The value of subclass object is assigned to the variable and the overridden method is called by the
super class reference.

1. class Animal {
2. void makeSound() {
3. System.out.println("Generic Animal Sound");
4. }
5. }
6. class Dog extends Animal {
7. @Override
8. void makeSound() {
9. System.out.println("Bark");
10. }
11. }
12. class Cat extends Animal {
13. @Override
14. void makeSound() {
15. System.out.println("Meow");
16. }
17. }
18. public class DynamicMethod {
19. public static void main(String[] args) {
20. Animal[] animals = {new Dog(), new Cat()};
21. for (Animal animal : animals) {
22. animal.makeSound();
23. }
24. }
25. }
Output:

Bark
Meow

5.

a.What is inheritance? List out the advantages of Inheritance. Discuss the types

of Inheritance supported by Java.

Introduction

Inheritance is the backbone of object-oriented programming (OOP).

It is the mechanism by which a class can acquire properties and methods of another

class.

Using inheritance, an already tested and debugged class program can be reused for some other
application.

Super class This is the existing class from which another class, that is, the subclass is enerally
derived.

In Java, several derived classes can have the same super class.

Subclass A class that is derived from another class is called subclass.

In Java, a subclass can have only one super class


Advantages of Inheritance

• It allows the reuse of already developed and debugged class program without any modification.

• It allows a number of subclasses to fulfil the needs of several subgroups.

• A large program may be divided into suitable classes and subclasses that may be developed by
separate teams of programmers.

Java supports several types of inheritance

 Single inheritance: A class inherits features from a single superclass.


 Multilevel inheritance: A class inherits from a derived class, creating a "grandparent-parent-
child" relationship.
 Hierarchical inheritance: Multiple classes inherit from a single superclass.
 Hybrid inheritance: A combination of two or more types of inheritance, such as single,
multilevel, and hierarchical.

6.
a.Discuss the advantages of the Interface.

Advantages of Interfaces in Java


The advantages of using interfaces in Java are as follows:
 Without bothering about the implementation part, we can achieve the security of the
implementation.
 In Java, multiple inheritances are not allowed, however, you can use an interface to make
use of it as you can implement more than one interface.

Multiple Inheritance in Java Using Interface


Multiple Inheritance is an OOPs concept that can’t be implemented in Java using classes. But
we can use multiple inheritances in Java using Interface. let us check this with an example.

There are certain features added to Interfaces in JDK 8 update mentioned below:
1. Prior to JDK 8, the interface could not define the implementation. We can now add
default implementation for interface methods. This default implementation has a special
use and does not affect the intention behind interfaces.
2. Suppose we need to add a new function to an existing interface. Obviously, the old
code will not work as the classes have not implemented those new functions. So with
the help of default implementation, we will give a default body for the newly added
functions. Then the old codes will still work.

b. b) Differentiate between Interface and Abstract class. When Interface is

preferred over Abstract class.

7.

a) Explain the significance of ‘Super’ keyword with an example.

Super keyword in Java helps create a bridge between child and parent class. Today in this blog,
we will discuss the super keyword in detail and will critically examine the super keyword in Java

Super keyword in Java is a reference variable used to refer to the immediate parent
class(superclass) object. The super keyword in Java is used when we want to acquire a
superclass member and use it in a derived class. When an instance of the child class is created,
an instance of the superclass is also created.

The super keyword in Java is used in the following scenarios


 super can be used to refer to a variable of the immediate parent class
 super can be used to invoke the immediate parent class method.
 super() can be used to access the immediate parent class constructor.

class ParentClass{
int num = 120;
}

/*
sub class childClass extending parentClass
*/
class ChildClass extends ParentClass{
int num = 100;

void display(){
// Printing the num without use of super keyword
System.out.println("Value of Num in child class: " + num);

// Printing the num with use of super keyword


System.out.println("Value of Num in parent class: " + super.num);
}
}

public class Main{


public static void main(String[] args){
ChildClass a = new ChildClass();
a.display();
}
}

You can also try this code with Online Java Compiler
Run Code

Output
Value of Num in child class: 100
Value of Num in parent class: 120

b) Write a java program to find the minimum and maximum value present in an array.

// Java program to find minimum (or maximum)


// element in an array.
import java.io.*;

class GFG {

static int getMin(int arr[], int n)


{
int res = arr[0];
for (int i = 1; i < n; i++)
res = Math.min(res, arr[i]);
return res;
}

static int getMax(int arr[], int n)


{
int res = arr[0];
for (int i = 1; i < n; i++)
res = Math.max(res, arr[i]);
return res;
}

// Driver code
public static void main(String[] args)
{
int arr[] = { 12, 1234, 45, 67, 1 };
int n = arr.length;
System.out.println("Minimum element of array: " + getMin(arr, n));
System.out.println("Maximum element of array: " + getMax(arr, n));
}
}

Output
Minimum element of array: 1
Maximum element of array: 1234

8.
a)Explain the concept of arrays of varying lengths and arrays as vectors.

variable length arrays (VLAs) are also known as runtime-sized or variable-sized arrays. The
size of such arrays is defined at run-time.
Variably modified types include variable-length arrays and pointers to variable-length arrays.
Variably changed types must be declared at either block scope or function prototype scope.
Variable length arrays are a feature where we can allocate an auto array (on stack) of variable
size. It can be used in a typedef statement. C supports variable-sized arrays from the C99
standard. For example, the below program compiles and runs fine in C.
Syntax of VLAs in C
void fun(int size)
{
int arr[size];
// code
}

b) Write a Java program to find the area and perimeter of square and circle using
interface.
interface Shape {
double calculateArea();
double calculatePerimeter();
}

class Circle implements Shape {


double radius;

Circle(double radius) {
this.radius = radius;
}
public double calculateArea() {
return Math.PI * radius * radius;
}

public double calculatePerimeter() {


return 2 * Math.PI * radius;
}
}

class Square implements Shape {


double side;

Square(double side) {
this.side = side;
}

public double calculateArea() {


return side * side;
}

public double calculatePerimeter() {


return 4 * side;
}
}

public class Main {


public static void main(String[] args) {
Shape circle = new Circle(5);
Shape square = new Square(4);

System.out.println("Circle area: " + circle.calculateArea());


System.out.println("Circle perimeter: " + circle.calculatePerimeter());

System.out.println("Square area: " + square.calculateArea());


System.out.println("Square perimeter: " + square.calculatePerimeter());
}
}
Unit-IV

Part-a

1. Describe the Object class and its importance in Java.

The Object class in Java is the grandparent of all classes. Every class you create
implicitly inherits from Object, which means it contains some essential methods that
are universally available.

Key Methods:

equals(Object obj): Checks if two objects are the same.

hashCode(): Returns a hash code value for the object. Useful in hashing-based
collections like HashMap.

toString(): Returns a string representation of the object, which you can override to
provide a custom string output.

clone(): Creates a shallow copy of the object.

finalize(): Called by the garbage collector when the object is being cleaned up, but
using this method is generally discouraged.

2. Explain the concept of access control in the context of packages.

Access control in Java packages is all about defining what can be accessed from where,
providing a layer of protection and organization. It helps in encapsulating and
safeguarding the data. There are four levels of access control in Java:

Public: Members (fields, methods, etc.) declared as public are accessible from any other
class. If a class is public, it can be accessed from any other class irrespective of the
package it resides in.

Protected: Members declared as protected can be accessed within the same package
and by subclasses, even if they are in different packages. It offers a balance between
visibility and encapsulation.

Default (Package-Private): If no access modifier is specified, the member is accessible


only within the same package. This is also known as package-private access.

Private: Members declared as private are accessible only within the class they are
declared in. This is the most restrictive level of access control.
3. Write the differences between checked and unchecked exceptions?

Checked and unchecked exceptions in Java are categorized based on the compile-time
checking they undergo:

Checked Exceptions:

Compile-Time Checked: The compiler ensures that these exceptions are handled, either
with a try-catch block or by declaring them with a throws clause.

Examples: IOException, SQLException, FileNotFoundException.

Unchecked Exceptions:

Runtime Checked: These exceptions are not checked at compile time. They only get
checked at runtime.

Examples: NullPointerException, ArrayIndexOutOfBoundsException,


ArithmeticException.

4. How does the finally block work, and when should it be used?

The finally block in Java is a part of exception handling and is used to ensure that a
specific block of code executes regardless of whether an exception occurs or not. It's
often used for cleanup activities, such as closing resources (e.g., files, database
connections) that need to be executed no matter what happens in the try or catch blocks.

5. What is the Java I/O API, and what is its significance?

The Java I/O API, short for Input/Output API, is a collection of classes and interfaces that
allow programs to read from and write to different data sources (like files, networks, and
other types of I/O streams).
Significance:

Flexibility: The API allows handling various data formats and I/O devices in a uniform
manner.

Performance: Buffered streams enhance performance by reducing the number of


read/write operations.

Error Handling: With exception mechanisms in place, it ensures robust handling of I/O
errors.

Scalability: Supports both blocking and non-blocking I/O operations, making it suitable
for a range of applications from simple file handling to complex network
communications.
6. How can you read and write text files using Java I/O classes?

Reading and writing text files in Java is pretty straightforward, thanks to the FileReader
and FileWriter classes for basic I/O operations, and BufferedReader and BufferedWriter
for more efficient, buffered I/O.

FileReader and FileWriter are used to read and write characters to a file.

BufferedReader and BufferedWriter provide efficient reading and writing by buffering the
input and output.

The try-with-resources statement ensures that resources (like file streams) are closed
automatically.

Part b

1.
a) How to define a package? How to access, import a package? Explain with
examples.

Creating and using packages in Java helps organize your code into modular, reusable
pieces. Let's break it down:

Defining a Package:
You define a package at the very top of your Java file using the package keyword:

Sntyax;
package com.example.myapp;
public class MyClass {
// class content
}

This places MyClass inside the com.example.myapp package.

Importing a Package:
To use a class from another package, you import it using the import keyword:

import com.example.myapp.MyClass;
public class Test {
public static void main(String[] args) {
MyClass obj = new MyClass();
}
}

This places MyClass inside the com.example.myapp package.

Importing a Package:
To use a class from another package, you import it using the import keyword:

import com.example.myapp.*;
Example:

1.Create a package named com.myapp.utils:

// File: Utils.java
package com.myapp.utils;
public class Utils {
public static void printMessage(String message) {
System.out.println(message);
}
}

2.Access the package from another file:

// File: Main.java
import com.myapp.utils.Utils;
public class Main {
public static void main(String[] args) {
Utils.printMessage("Hello from Utils!");
}
}

b.Demonstrate the class Throwable with the help of a Java program.

The Throwable class in Java is the superclass for all errors and exceptions in the
language. Let's create a simple program to illustrate its use:

public class ThrowableExample {


public static void main(String[] args) {
try {
throw new Exception("This is an example exception");
} catch (Exception e) {
System.out.println("Caught Exception: " + e.getMessage());
printThrowableDetails(e);
}
}

public static void printThrowableDetails(Throwable t) {


System.out.println("Throwable Details:");
System.out.println("Message: " + t.getMessage());
System.out.println("Class: " + t.getClass().getName());

System.out.println("Stack Trace:");
for (StackTraceElement element : t.getStackTrace()) {
System.out.println(element);
}

Throwable cause = t.getCause();


if (cause != null) {
System.out.println("Cause: " + cause.getMessage());
} else {
System.out.println("No cause available");
}
}
}

Explanation:

 The program throws an Exception with a custom message.

 The catch block catches the exception and prints its message.

 The printThrowableDetails method demonstrates how to access various details


from the Throwable object, including the stack trace and the cause.

2.

a) Give the syntax to create a package in Java. How to set the path and class path
variables? Explain.

Creating a Package: Here's how you define a package in Java:

Syntax
package com.example.myapp;
public class MyClass {
// class content
}

Setting the Path and Classpath:

PATH: This environment variable tells the operating system where to look for
executable files. Typically, you include the JDK/bin directory in the PATH to run
Java commands from any directory.

On Windows:

set CLASSPATH=C:\myfolder\myclasses;%CLASSPATH%

b. Discuss about wrapper classes in Java.

Wrapper classes in Java are objects that encapsulate primitive data types in order to
provide object-oriented features. Each primitive type (like int, char, boolean, etc.) has a
corresponding wrapper class (Integer, Character, Boolean, etc.).
Key Features:

 Object Representation: They allow primitives to be treated as objects, enabling


them to be used in collections like ArrayList that require objects.

 Utility Methods: They provide methods to manipulate and convert primitive


values. For example, Integer.parseInt("123") converts a string to an int.

 Nullability: Unlike primitives, wrapper classes can hold null values, which is
useful for representing the absence of a value.

Examples:

// Boxing: converting primitive to wrapper object


int primitiveInt = 5;
Integer wrapperInt = Integer.valueOf(primitiveInt);

// Unboxing: converting wrapper object to primitive


int unboxedInt = wrapperInt.intValue();

// Auto-boxing and auto-unboxing


Integer autoBoxedInt = primitiveInt; // auto-boxing
int autoUnboxedInt = wrapperInt; // auto-unboxing

// Using utility methods


String str = "123";
int parsedInt = Integer.parseInt(str);

3.
a Write the differences between the following classes Date, Calendar and Gregorian
Calendar and usage of time package.

Date Class
Purpose: Represents a specific instant in time, with millisecond precision.

Usage: Used mainly for working with date and time in a simple way.

Example:
Date date = new Date();
System.out.println(date);

Limitations: Lacks many methods for date manipulation. Mostly deprecated and replaced
by the Calendar class.

Calendar Class
Purpose: Abstract class for manipulating dates and times.

Usage: Provides methods for setting and getting specific parts of a date (like year,
month, day).
Example:
Calendar calendar = Calendar.getInstance();
calendar.set(2024, Calendar.OCTOBER, 28);
Date date = calendar.getTime();
System.out.println(date);

Flexibility: Allows for more complex date manipulations and is locale-sensitive.

GregorianCalendar Class
Purpose: Concrete subclass of Calendar that implements the Gregorian calendar system.

Usage: Default calendar implementation in Java.

Example:
GregorianCalendar gCal = new GregorianCalendar(2024, Calendar.OCTOBER, 28);
Date date = gCal.getTime();
System.out.println(date);

Features: Provides additional methods specific to the Gregorian calendar, such as


checking leap years.

java.time Package
Purpose: Introduced in Java 8, it provides a more comprehensive date and time API.

Classes: Includes LocalDate, LocalTime, LocalDateTime, ZonedDateTime, and more.

Usage: Offers a fluent API for handling date and time with immutability and thread-safety.

Example:
LocalDateTime now = LocalDateTime.now();
System.out.println(now);

LocalDate date = LocalDate.of(2024, Month.OCTOBER, 28);


System.out.println(date);

The java.time package is highly recommended for modern applications due to its
enhanced functionality and ease of use compared to the older Date and Calendar
classes.

4. Discuss about java.lang package and its key classes.

The java.lang package is the core package in Java, containing fundamental classes that
are essential for the language’s design and functionality. It's automatically imported into
every Java program, so you don't need to import it explicitly.

Key Classes:

 Object: The root class from which all other classes inherit. Provides basic
methods like toString(), equals(), hashCode(), and clone().
 Class: Represents classes and interfaces in a running Java application. You can
use Class objects to get information about fields, methods, and constructors.

 System: Provides access to system resources like standard input and output, and
methods for copying arrays and interacting with the garbage collector.

 String: Represents immutable sequences of characters. It's arguably the most


commonly used class, providing methods for string manipulation and
comparison.

 StringBuilder and StringBuffer: Mutable sequences of characters. StringBuilder is


faster but not thread-safe; StringBuffer is thread-safe but slightly slower.

 Math: Contains methods for performing basic numeric operations like


exponentiation, logarithms, square roots, and trigonometric functions.

 Throwable, Exception, Error: These are the classes for exception handling in Java.
Throwable is the superclass for all exceptions and errors, Exception is for
conditions that a reasonable application might want to catch, and Error represents
serious problems that an application should not attempt to catch.

 Thread: Represents a thread of execution in a program. It’s fundamental for


concurrent programming in Java.

 Runtime: Enables the application to interface with the environment in which the
application is running. It provides methods to execute processes, read system
properties, and interact with the garbage collector.

 Boolean, Byte, Character, Double, Float, Integer, Long, Short: These are wrapper
classes for the respective primitive types, allowing primitive values to be treated
as objects.

 Enum: Base class for all enumeration types in Java, providing methods to retrieve
enumeration constants and their names.

Examples:

String Manipulation:

String str = "Hello, World!";


System.out.println(str.toUpperCase()); // Outputs: HELLO, WORLD!

Math Operations:

double result = Math.sqrt(16);


System.out.println(result); // Outputs: 4.0
Using Thread:

Thread thread = new Thread(() -> System.out.println("Hello from a thread!"));


thread.start();
The java.lang package is the backbone of Java programming, providing the classes and
interfaces you rely on every day.

5
a. a) What is an exception? In what an exception differs from error?Distinguish between
user defined and built-in exceptions.

Exception vs. Error

Exception: Represents conditions that a program should catch and handle. Examples
include IOException, SQLException, and ArithmeticException.

Error: Represents serious issues that are typically outside the scope of the program's
control and usually signal fundamental problems with the JVM, like OutOfMemoryError
and StackOverflowError. Generally, these should not be caught as they denote serious
issues.

Built-in vs. User-defined Exceptions

 Built-in Exceptions: These are predefined in Java’s standard library and include:

 IOException: Issues with input-output operations.

 NullPointerException: Attempting to use null where an object is required.

 ArithmeticException: Arithmetic operations like division by zero.

 ArrayIndexOutOfBoundsException: Accessing an array with an illegal index.

User-defined Exceptions: These are custom exceptions created by programmers to


handle specific application needs. Here’s how you define and use one:

Creating a User-defined Exception:

class CustomException extends Exception {


public CustomException(String message) {
super(message);
}
}

public class Main {


public static void main(String[] args) {
try {
validateAge(15);
} catch (CustomException e) {
System.out.println("Caught Custom Exception: " + e.getMessage());
}
}

static void validateAge(int age) throws CustomException {


if (age < 18) {
throw new CustomException("Age must be 18 or above to vote.");
}
}
}

Difference in Usage:

Built-in: Provides standard error handling for common runtime anomalies.

User-defined: Offers specific error handling tailored to the application’s needs.

b. Discuss about file handling in java in detail.

Java's file handling mechanisms offer a comprehensive way to read, write, and
manipulate files. Let’s break it down:

Basics of File Handling


 Java's java.io package provides various classes to interact with file systems:

 File: Represents file and directory pathnames in an abstract manner.

 FileReader/FileWriter: For reading and writing character files.

 BufferedReader/BufferedWriter: For efficient reading and writing of text using


buffering.

 FileInputStream/FileOutputStream: For reading and writing binary data.

 DataInputStream/DataOutputStream: For reading and writing primitive data types

Reading Files
Using FileReader and BufferedReader

FileReader: Reads characters from a file.

 BufferedReader: Reads text from a character-input stream, buffering characters to


provide efficient reading.

 Using FileInputStream and DataInputStream

 FileInputStream: Reads raw bytes from a file.


 DataInputStream: Reads primitive data types from an input stream.

Writing Files

 FileWriter: Writes characters to a file.

 BufferedWriter: Writes text to a character-output stream, buffering characters to


provide efficient writing.

 Using FileOutputStream and DataOutputStream

Example:
import java.io.*;
public class FileIO {

public static void main(String args[]) throws IOException {


FileReader in = null;
FileWriter out = null;

try {
in = new FileReader("C:\\Raja\\Input-File.txt");
out = new FileWriter("C:\\Raja\\Output-File.txt");

int c;
while ((c = in.read()) != -1) {
out.write(c);
}
System.out.println("Reading and Writing in a file is done!!!");
}
catch(Exception e) {
System.out.println(e);
}
finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
6.
a.Write short notes on i) wrapper classes ii) Temporal adjusters class iii)throws clause

i) Wrapper Classes

Wrapper classes in Java are used to convert primitive data types (like int, char, boolean,
etc.) into objects. Each primitive has a corresponding wrapper class (e.g., Integer for int,
Character for char). They are useful because many utility methods and collections in
Java work with objects, not primitives.

For example:

Integer.parseInt("123") converts a string to an integer.

Wrappers allow primitives to be used in collections like ArrayList<Integer>.

ii) Temporal Adjusters Class


The TemporalAdjusters class in the java.time package provides static methods for date-
time adjustments, such as finding the next or previous day of the week, the last day of
the month, or the first day of the next year. These adjustments are used with the
LocalDate, LocalTime, LocalDateTime, and ZonedDateTime classes to perform complex
date-time manipulations easily.
Example:

LocalDate next
Sunday=LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY));

iii) throws Clause


The throws clause in Java is used in method signatures to declare that a method may
throw one or more exceptions. It informs the caller of the method about the potential
exceptions that need to be handled.

For example:

public void readFile(String fileName) throws IOException {


BufferedReader br = new BufferedReader(new FileReader(fileName));
// Method implementation
}
Using throws promotes robust error handling and makes the contract of the method
clear to its callers.

7.
a)Describe the Hierarchy of Java exception classes with a neat sketch.

Hierarchy Overview:
At the top of the hierarchy is the Throwable class, which is the superclass for all
exceptions and errors. Under Throwable, there are two main branches: Exception and
Error.
Throwable:

The root class for all error and exception types.

Exception:

 Represents conditions a program might want to catch.

 Subclasses: IOException, SQLException, ClassNotFoundException, etc.

 RuntimeException (a subclass of Exception):

 Represents exceptions that can occur during the normal operation of the Java
Virtual Machine.

Subclasses:
NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, etc.

Error:

 Represents serious problems that a program should not try to catch.

 Subclasses: OutOfMemoryError, StackOverflowError, VirtualMachineError, etc.

 Imagine it as a tree diagram, with Throwable at the top, branching out into
Exception and Error, and further branching into more specific exception types.
b. Explain nested try statements and multiple catch blocks with a suitable program

Nested try statements and multiple catch blocks are useful for handling different types of
exceptions within different blocks of code. Here's an example to demonstrate both:

Example Program

public class NestedTryCatchExample {


public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[10]); // This will throw
ArrayIndexOutOfBoundsException

try {
int result = 10 / 0; // This will throw ArithmeticException
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("Caught an ArithmeticException: " + e.getMessage());
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Caught an ArrayIndexOutOfBoundsException: " +
e.getMessage());
} catch (Exception e) {
System.out.println("Caught a general exception: " + e.getMessage());
}

System.out.println("Program continues...");
}
}

Explanation

Outer try Block:

Attempts to access an invalid index in the numbers array, throwing


ArrayIndexOutOfBoundsException.

Inner try Block:

 Located within the outer try block.

 Attempts to perform division by zero, throwing ArithmeticException.

 Multiple catch Blocks:

 Each catch block handles a specific type of exception.


 The outer catch blocks handle ArrayIndexOutOfBoundsException and a general
Exception.

 The inner catch block handles ArithmeticException.

 Key Points:
 Nested try-catch: Inner try block can handle exceptions specific to its scope.

 Multiple catch: Different exception types are caught by different catch blocks,
making error handling more precise and informative.

8.
a)Discuss about Byte stream and Character streams in detail.

Byte Streams
Byte streams in Java are used for handling raw binary data. They are useful when
working with data such as images, audio, or any kind of file where character encoding
isn't an issue. The core classes for byte stream are InputStream and OutputStream.

Key Classes:

InputStream: Abstract superclass for all byte input streams. Subclasses include
FileInputStream, BufferedInputStream, DataInputStream.

OutputStream: Abstract superclass for all byte output streams. Subclasses include
FileOutputStream, BufferedOutputStream, DataOutputStream.

Example:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamExample {


public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input.dat");
FileOutputStream fos = new FileOutputStream("output.dat")) {
int byteData;
while ((byteData = fis.read()) != -1) {
fos.write(byteData);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Character Streams
Character streams are designed for handling character data, making them ideal for text
files where encoding is important. The core classes are Reader and Writer.

Key Classes:

 Reader: Abstract superclass for all character input streams. Subclasses include
FileReader, BufferedReader, InputStreamReader.

 Writer: Abstract superclass for all character output streams. Subclasses include
FileWriter, BufferedWriter, OutputStreamWriter.

Example:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharacterStreamExample {


public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("input.txt"));
FileWriter fw = new FileWriter("output.txt")) {
String line;
while ((line = br.readLine()) != null) {
fw.write(line);
fw.write(System.lineSeparator());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

b.Write the functionality of the Scanner class in Java with example


program.

The Scanner class in Java, part of the java.util package, is a versatile tool for parsing
input and simplifying data extraction from various input sources like strings, files, and
input streams (such as System.in).

Key Functionalities:
 Reading from Standard Input:

 next(): Reads the next token from the input as a String.

 nextInt(), nextDouble(), etc.: Reads the next token as an int, double, etc.

 nextLine(): Reads the entire line as a String.


Reading from a File:

Uses methods similar to those for standard input but with a File object as the source.

Delimiters:

useDelimiter(String pattern): Allows customization of the delimiters (separators) used to


parse tokens.

Example Program:
Here's a program demonstrating how to use Scanner to read input from the console and
a file:

Reading from Standard Input:

import java.util.Scanner;

public class ScannerExample {


public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

System.out.print("Enter your name: ");


String name = scanner.nextLine();

System.out.print("Enter your age: ");


int age = scanner.nextInt();

System.out.println("Hello, " + name + ". You are " + age + " years old.");

scanner.close();
}
}
Unit-5
PART-A(SHORT QUESTIONS AND ANSWERS)

1. What is the CharSequence interface in Java, and how is it related to strings?

The CharSequence is a readable sequence of char values, providing a standardized way to work
with different types of character sequences. It defines methods to access and manipulate a
sequence of characters.

Key Methods of the CharSequence Interface:

The CharSequence interface includes the following primary methods:

1. charAt(int index): Returns the character at the specified index.


2. length(): Returns the length of the sequence.
3. subSequence(int start, int end): Returns a new CharSequence that is a
subsequence from the specified start index to the end index.
4. toString(): Converts the CharSequence to a String.

Implementations of CharSequence

Several classes in Java implement the CharSequence interface, including:

 String: The most commonly used implementation. A String is an immutable sequence


of characters.
 StringBuilder: A mutable sequence of characters, allowing modification without
creating new instances.
 StringBuffer: Similar to StringBuilder but thread-safe, making it suitable for use in
multi-threaded environments.
 CharBuffer: Part of the java.nio package, used for working with buffers of characters.

2. Explain how you can search for a substring within a string in Java.

In Java, you can search for a substring within a string using several built-in methods provided by the
String class. Here are some commonly used approaches:

 contains(): Checks if the substring is present.


 indexOf(): Finds the index of the first occurrence of the substring.
 lastIndexOf(): Finds the index of the last occurrence.
 matches(): Uses regular expressions to check for matches.
 regionMatches(): Compares a specific region of the string.

class string
{

public static void main(String[] args)

StringBuffer sb=new StringBuffer(" java Programming");

System.out.println(sb.charAt(2));

System.out.println(sb.indexOf("J"));

System.out.println(sb.lastIndexOf("a"));

3. What is the String class in Java, and how is it different from other objects?

String is a sequence of characters. But in Java, string is an object that represents a sequence of
characters. The java.lang.String class is used to create a string object. String is an immutable and
provides various methods for string manipulation.

How to create a string object?

There are two ways to create String object:

1. By string literal
2. By new keyword

1) String Literal

Java String literal is created by using double quotes

1. String s="welcome";
2. String s1="Welcome"; String s2="Welcome";//It doesn't create a new instance
By new keyword

1. String s=new String("Welcome");

In such case, JVM will create a new string object in normal (non-pool) heap memory, and the
literal "Welcome" will be placed in the string constant pool. The variable s will refer to the
object in a heap (non-pool).

public class StringExample


{
public static void main(String args[])
{
String s1="java";//creating string by Java string literal
char ch[]={'s','t','r','i','n','g','s'};
String s2=new String(ch);
String s3=new String("example");
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
}
}

4. What is multithreaded programming, and why is it important in Java?

Multithreading in Java is a process of executing multiple threads simultaneously. A thread is a


lightweight sub-process, the smallest unit of processing. Multiprocessing and multithreading,
both are used to achieve multitasking. However, we use multithreading than multiprocessing
because threads use a shared memory area. They don't allocate separate memory area so saves
memory, and context-switching between the threads takes less time than process. Java
Multithreading is mostly used in games, animation, etc.

Advantages of Java Multithreading


1) It doesn't block the user because threads are independent and you can
perform multiple operations at the same time.
2) You can perform many operations together, so it saves time.
3) Threads are independent, so it doesn't affect other threads if an exception
occurs in a single thread.
5. How does Java handle inter-thread communication?

Inter-thread communication is allow the synchronized threads to communicate with each


other. it is a mechanism in which a thread is paused running in its critical section and another
thread is allowed to enter (or lock) in the same critical section to be executed.It is implemented
by following methods of Object class:

 wait()
 notify()
 notifyAll()

wait() method

The wait() method causes current thread to release the lock and wait until either another thread
invokes the notify() method or the notifyAll() method for this object, or a specified amount of
time has elapsed.

notify() method

The notify() method wakes up a single thread that is waiting on this object's monitor. If any
threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary
and occurs at the discretion of the implementation.

Syntax:

public final void notify() ;

notifyAll() method

Wakes up all threads that are waiting on this object's monitor.

Syntax:

public final void notifyAll()

6. What are the methods for suspending, resuming, and stopping threads in Java?

You can develop a multithreaded program which can be suspended, resumed, or stopped completely
based on your requirements. There are various static methods which you can use on thread objects to
control their behavior.

This method puts a thread in the suspended state and can be resumed
public void suspend() using resume() method.
public void stop() This method stops a thread completely.
This method resumes a thread, which was suspended using
public void resume()
suspend() method.

PART-B(LONG QUESTIONS AND ANSWERS)

1a) Write a program to implement producer and consumer problem by using Multithreading.

class Q
{
int n;
boolean valueSet = false;
synchronized int get()
{
while(!valueSet)
try {
wait();
}
catch(InterruptedException e)
{
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
} //end of the get() method
synchronized void put(int n)
{
while(valueSet)
try {
wait();
}
catch(InterruptedException e)
{
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
} //end of the put method
} //end of the class Q
class Producer implements Runnable
Q q;
Producer(Q q)
{
this.q = q;
new Thread(this, "Producer").start();
}
public void run()
{
int i = 0;
while(true)
{
q.put(i++);
}
}
} //end of Producer
class Consumer implements Runnable
{
Q q;
Consumer(Q q)
{
this.q = q;
new Thread(this, "Consumer").start();
}
public void run()
{
while(true)
{
q.get();
}
}
}//end of Consumer
class PCFixed
{
public static void main(String args[])
{
Q q = new Q();
new Producer(q);
new Consumer(q);
System.out.println("Press Control-C to stop.");
}
}
Output:
Put : 1
Got:1
Put:2
Got:2
Put:3
Got:3
------
------
------
Put:1000
Got :1000
Press ctr1+c to stop
1b) What are the states in the lifecycle of a thread? Explain with a neat diagram.

Thread States (Life-Cycle of a Thread): The life cycle of a thread contains several states. At any time
the thread falls into any one of these states.

Threads exist in several states. A thread can be running. It can be ready to run as soon as it gets CPU
time. A running thread can be suspended, which temporarily suspends its activity. A suspended
thread can then be resumed, allowing it to pick up where it left off. A thread can be blocked when
waiting for a resource. At any time, a thread can be terminated, which halts its execution
immediately. Once terminated, a thread cannot be resumed.
 The thread that was just created is in the new state.
 The thread remains in this state until the threads start method is called. This causes the
thread to enter the ready state.
 The highest priority ready thread enters the running state when system assigns a processor
to the thread i.e., the thread begins executing.
 When a running thread calls wait state, then thread enters into a waiting state for the
particular object on which wait was called. Every thread in the waiting state for a given
object becomes ready on a call to notify all by another thread associated with that object.
 When a sleep method is called in a running thread that thread enters into the suspended
(sleep) state. A sleeping thread becomes ready after the designated sleep time expires. A
sleeping thread cannot use a processor even if one is available.
 A thread enters the terminate state when its run() method completes for any reason. A
terminated thread is eventually be disposed of by the system.
 One common way for a running thread to enter the blocked state is when the thread issues
an input or output request. In this case a blocked thread becomes ready when the input or
output waits for completes. A blocked thread can’t use a processor even if one is available.

Creation of threads
We are following different ways to create a new thread by using methods and constructors of the
Thread class.
 By inheriting the Thread class
 By implementing the Runnable interface.

By inheriting the Thread class


Threads can be created by inheriting the java.lang.Thread class. All the thread methods belonging the
Thread class can be used in the program because of the extension.
Steps to be followed for thread creation:
 Declare our own class as extending the Thread class.
 Override the run() method, which constitutes the body of the thread
 Create the thread object and use the start() method to initiate the thread execution.

Declaring a class:Any new class can be declared to extend the Thread class, thus inheriting all the
functionalities of the Thread class.
Class NewThread extends Thread
{
---------
---------
---------
}
Here, we have a new type of thread, named as ‘New Thread’.
Overriding the run() method: The run method has to be overridden by writing codes required for
the thread. The thread behaves as per this code segment . A typical run() method like as below:
public void run()
{
------
// code segment providing the functionality of thread
-------
}
Starting New Thread: The start() method, which is required to create and initiate an instance of our
Thread Class.’
NewThread thread1= new NewThread();
thread1.start();
The first line creates an instance of the class NewThread, where the object is just created. The thread
here is in newborn state.
Second line which calls start() method, moves the thread to runnable state, where the Java Runtime
will schedule the thread to run by invoking the run() method. Now the thread is said to be in running
state.
Example1:- Creating a thread using the Thread Class.
class One extends Thread{
public void run(){
System.out.println("thread is running...");
}
public static void main(String args[]){
One t1=new One();
t1.start();
}
}
Output:thread is running...
Example2:- Creating a thread using the Thread Class.
class Mythread extends Thread
{
public void run()
{
for(int i=0;i<=10;i++)
{
System.out.println("child Thread");
}
}
}
class ThreadDemoO
{
public static void main(String args[])
{
Mythread t=new Mythread();
t.start();
for(int i=0;i<=10;i++)
{
System.out.println("Main Thread");
}
}
2a) Explain the String class and its key methods for manipulating strings.

The String class in Java is one of the most commonly used classes and is used to represent sequences
of characters. It is part of the java.lang package and provides various methods for manipulating
strings. Strings in Java are immutable, meaning once a String object is created, its value cannot be
changed. Any operation that seems to modify a string actually creates a new String object.
some of the key methods provided by the String class:

length()
 Returns the number of characters in the string.
 Example:
String str = "Hello, World!";
int length = str.length();

charAt(int index)

 Returns the character at the specified index.

String str = "Hello";


char ch = str.charAt(1);

substring(int beginIndex) and substring(int beginIndex, int endIndex)

 Returns a new string that is a substring of the original string.


 The first method extracts from the specified index to the end of the string.
 The second method extracts from the start index up to, but not including, the end index.

String str = "Hello, World!";


String sub1 = str.substring(7);
String sub2 = str.substring(0, 5);

toUpperCase() and toLowerCase()

 Converts all characters in the string to upper or lower case.

String str = "Hello";


String upper = str.toUpperCase();
String lower = str.toLowerCase();

trim()
 Removes leading and trailing whitespace from the string.

String str = " Hello, World! ";


String trimmed = str.trim();

equals(Object another) and equalsIgnoreCase(String another)

 equals() checks if two strings have the same content, considering case.
 equalsIgnoreCase() checks if two strings are equal, ignoring case differences.

String str1 = "Hello";


String str2 = "hello";
boolean isEqual = str1.equals(str2);
boolean isEqualIgnoreCase = str1.equalsIgnoreCase(str2);

indexOf(String str) and lastIndexOf(String str)

 indexOf() returns the index of the first occurrence of the specified substring.
 lastIndexOf() returns the index of the last occurrence.
 If the substring is not found, these methods return -1.

String str = "Hello, World!";


int index1 = str.indexOf("o");
int index2 = str.lastIndexOf("o");

2b) Discuss thread priority in Java and its impact on thread scheduling

THREAD PRIORITY: Each thread has a set priority, which helps the scheduler to decide the order
of sequence of thread execution,i.e) which thread should run when?. By default the threads created,
carry the same priority due to which the java scheduler schedules them for processor on first come
first serve basis. It is to be noted that java follows preemptive scheduling policy, like as an operating
system. When a high priority thread becomes ready for execution, the currently low-priority thread
will be stopped. Low priority thread has to wait until the high priority thread is dead or blocked
because of some reason or other. The reason for this can be any one of the following:


 Thread stops as soon as it exits run()
 It sleeps (by using sleep())
 It waits (by using wait() or join())


Once it resumes from the blocked state, it will again preempt the low priority thread to which it had
relinquished its control earlier, thus forcing the low priority to move to the Runnable state from the
running state.
As shown in the below table, the Thread class has a method setPriority(), responsible for setting the
priority of thread by programmer. The signature of the method is:
final void setPriority(int x)
Where x specifies the value used to signify the thread’s priority. Thread class define several
predefined priority constants(as static final variables) as under, Table: Priority constants and their
corresponding value for threads

CONTENT VALUE MEANING


Min priority a thread can have
MIN_PRIPORITY 1
Default priority a thread can have
NORM_PRIORITY 5
Max priority a thread can have
MAX_PRIORITY 10

Thus priorities can be set from 1 to 10. If any is not created (assigned externally, by default it is set to
NORM_PRIORITY i.e) 5 for threads.

A thread’s current priority can be obtained by the getpriority() method of thread class which returns
an integer value.

Syntax: final int getPriority()


Example Program:
class ThreadOne extends Thread
{
public void run()
{
try
{
for(int i=1;i<=5;i++)
{
System.out.println("\t from child thread1:i="+i);
Thread.sleep(700);
}
}
catch(InterruptedException e)
{
System.out.println("child Thread1 interrupted");
}
System.out.println("Exit from child Thread1");
}
}
class ThreadTwo extends Thread
{
public void run()
{
try
{
for(int j=1;j<=5;j++)
{
System.out.println("\t from child thread2:j="+j);
Thread.sleep(700);
}
}
catch(InterruptedException e)
{
System.out.println("child Thread2 interrupted");
}
System.out.println("Exit from child Thread2");
}
}
class ThreadThree extends Thread
{
public void run()
{
try
{
for(int k=1;k<=5;k++)
{
System.out.println("\t from child thread3:k="+k);
Thread.sleep(700);
}
}
catch(InterruptedException e)
{
System.out.println("child Thread3 interrupted");
}
System.out.println("Exit from child Thread3");
}
}
class ThreadPriority
{
public static void main(String args[])
{
ThreadOne a=new ThreadOne();
ThreadTwo b=new ThreadTwo();
ThreadThree c=new ThreadThree();
System.out.println("default priority for thread1:"+a.getPriority());
System.out.println("default priority for thread2:"+b.getPriority());
System.out.println("default priority for thread3:"+c.getPriority());
System.out.println(" ");
a.setPriority(Thread.MIN_PRIORITY);
b.setPriority(Thread.NORM_PRIORITY);
c.setPriority(Thread.MAX_PRIORITY);
//a.setPriority(2);
//b.setPriority(6);
//c.setPriority(9);
System.out.println("default priority for thread1:"+a.getPriority());
System.out.println("default priority for thread2:"+b.getPriority());
System.out.println("default priority for thread3:"+c.getPriority());
System.out.println(" ");
System.out.println("All the threads start from here");
a.start();
b.start();
c.start();
}
}
OUTPUT:
C:\R19>java ThreadPriority
default priority for thread1:5
default priority for thread2:5
default priority for thread3:5
default priority for thread1:1
default priority for thread2:5
default priority for thread3:10
All the threads start from here
from child thread1:i=1
from child thread2:j=1
from child thread3:k=1
from child thread3:k=2
from child thread1:i=2
from child thread2:j=2
from child thread3:k=3
from child thread2:j=3
from child thread1:i=3
from child thread3:k=4
from child thread2:j=4
from child thread1:i=4
from child thread2:j=5
from child thread3:k=5
from child thread1:i=5
Exit from child Thread3
Exit from child Thread1
Exit from child Thread2
3a) Write a java program to sort the given set of strings as per the alphabetical order.

import java.util.Arrays;
import java.util.Scanner;

public class SortStrings {


public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);

// Get the number of strings from the user


System.out.print("Enter the number of strings: ");
int n = scanner.nextInt();
scanner.nextLine(); // Consume the newline character

// Array to hold the strings


String[] strings = new String[n];

// Get the strings from the user


System.out.println("Enter the strings:");
for (int i = 0; i < n; i++) {
strings[i] = scanner.nextLine();
}

// Sort the strings in alphabetical order


Arrays.sort(strings);

// Display the sorted strings


System.out.println("Strings in alphabetical order:");
for (String str : strings) {
System.out.println(str);
}

scanner.close();
}
}

3b) Distinguish between process based and thread based multitasking

Aspect Process-based Multitasking Thread-based Multitasking

Multiple independent programs Multiple threads within a single


Definition (processes) process
Memory Separate memory space for each Shared memory space for all
Management process threads
Easier and faster (shared
Communication Complex, slower (requires IPC) memory)
Execution Higher (creating and switching Lower (creating and switching
Overhead processes) threads)
Less isolation, potential data
Isolation Better isolation, more secure issues
Running independent programs Concurrent tasks within the same
Use Cases or services program

4a) Write a java program that prints numbers from 1 to10 line by line after every 5 seconds.

public class PrintNumbersWithDelay {


public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
System.out.println(i);
try {
// Pause for 5 seconds (5000 milliseconds)
Thread.sleep(5000);
} catch (InterruptedException e) {
System.out.println("Interrupted: " + e.getMessage());
}
}
}
}

Output:
1
(wait for 5 seconds)
2
(wait for 5 seconds)
3
(wait for 5 seconds)
4
(wait for 5 seconds)
5
(wait for 5 seconds)
6
(wait for 5 seconds)
7
(wait for 5 seconds)
8
(wait for 5 seconds)
9
(wait for 5 seconds)
10

4b) Explain isAlive(), join(), sleep() and main() methods.

1. isAlive():

 Checks if a thread is currently running or has finished execution.


 Returns true if the thread is still active, otherwise false.
 Useful for confirming the state of a thread, especially in multi-threaded programs.

Program:

public class IsAliveExample {

public static void main(String[] args) {

Thread thread = new Thread(() -> {

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

});

thread.start();

System.out.println("Is the thread alive? " + thread.isAlive()); // Checks if the thread is alive

2. join():

 Makes the current thread wait until the specified thread has completed its execution.
 Helps ensure that one thread completes before others continue, especially if the result
of one thread is needed by another.
 Variants include join(milliseconds) to specify a wait time.
Program:

public class JoinExample {

public static void main(String[] args) {

Thread thread = new Thread(() -> {

System.out.println("Thread is doing some work...");

});

thread.start();

try {

thread.join(); // Main thread waits until `thread` finishes

} catch (InterruptedException e) {

e.printStackTrace();

System.out.println("Main thread continues after `thread` finishes.");

3. sleep():

 Pauses the execution of the current thread for a set time (in milliseconds).
 Throws InterruptedException if the thread is interrupted while sleeping.
 Often used to control timing or delay operations in a thread.

Program:

public class SleepExample {

public static void main(String[] args) {

System.out.println("Message 1");

try {
Thread.sleep(3000); // Pause for 3 seconds

} catch (InterruptedException e) {

e.printStackTrace();

System.out.println("Message 2 (printed after 3 seconds)");

4. main():

 The entry point of every Java program, where execution begins.


 Has the signature public static void main(String[] args), allowing the JVM to start the program.
 It can accept command-line arguments via args and is the starting method of the
application.

Program:

public class MainMethodExample {

public static void main(String[] args) {

System.out.println("This is the entry point of the program.");

System.out.println("Arguments passed to the program:");

for (String arg : args) {

System.out.println(arg);

}
5. Explain the difference between String, String Buffer and String Builder classes.

1. String

 Description: String is an immutable class, meaning once a String object is created, it cannot be
modified. If any changes are made, a new String object is created in memory.
 Mutability: Immutable – does not allow modification of the existing object.
 Thread-Safety: Safe for multi-threading because it’s immutable.
 Performance: Slower when performing many string manipulations (e.g., concatenations), as
new objects are created for each modification.
 Usage: Suitable for scenarios where the string value does not change frequently, such as
constants and simple messages.
 Example:

String str = "Hello";

str = str + " World"; // A new "Hello World" object is created in memory

2. StringBuffer

 Description: StringBuffer is a mutable class, meaning that it allows modifications without


creating new objects. It can be used when frequent changes to strings are needed.
 Mutability: Mutable – can modify the same object, improving performance for repeated
changes.
 Thread-Safety: Thread-safe, as it’s synchronized, making it suitable for multi-threaded
environments.
 Performance: Slower than StringBuilder due to synchronization but faster than String for large
modifications.
 Usage: Ideal for use cases where strings are modified often in multi-threaded applications.
 Example:

StringBuffer sb = new StringBuffer("Hello");

sb.append(" World"); // Modifies the same object

System.out.println(sb); // Output: Hello World

3. StringBuilder
 Description: Similar to StringBuffer but without thread-safety. It is also mutable and designed
for use in single-threaded scenarios where frequent modifications to strings are needed.
 Mutability: Mutable – allows modification without creating new objects.
 Thread-Safety: Not thread-safe, as it lacks synchronization, making it faster in single-threaded
environments.
 Performance: Faster than both String and StringBuffer for single-threaded cases with frequent
modifications.
 Usage: Best suited for single-threaded applications where strings are modified often, such as
in loops or intensive string processing tasks.
 Example

StringBuilder sb = new StringBuilder("Hello");

sb.append(" World"); // Modifies the same object

System.out.println(sb); // Output: Hello World

6) In how many ways a thread can be implemented? Demonstrate any one technique with
suitable example.

In Java, a thread can be implemented in two primary ways:

1. By Extending the Thread Class


2. By Implementing the Runnable Interface

1. Extending the Thread Class

You can create a new thread by creating a class that extends the Thread class and overriding its
run() method. This method contains the code that will execute when the thread starts.

2. Implementing the Runnable Interface

Alternatively, you can create a thread by implementing the Runnable interface. This involves
creating a class that implements the Runnable interface and overriding the run() method. The
Runnable instance is then passed to a Thread object.

Demonstration Using the Thread Class


Let’s demonstrate the first method (extending the Thread class) with a simple example.

Example: Implementing a Thread by Extending the Thread Class

// Step 1: Create a class that extends the Thread class

class MyThread extends Thread {

@Override

public void run() {

// Code to be executed by the thread

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

System.out.println("Thread " + Thread.currentThread().getName() + " - Count: " + i);

try {

Thread.sleep(1000); // Pause for 1 second between iterations

} catch (InterruptedException e) {

e.printStackTrace();

// Step 2: Create the main class to run the thread

public class ThreadExample {

public static void main(String[] args) {

MyThread thread1 = new MyThread(); // Create an instance of the thread

MyThread thread2 = new MyThread(); // Create another instance

// Step 3: Start the threads

thread1.start(); // Start the first thread


thread2.start(); // Start the second thread

Explanation of the example:

1. Extend Thread Class: The MyThread class extends Thread and overrides the run() method. The
run() method contains the code that will be executed by the thread.
2. Create Instances: In the main method, two instances of MyThread are created.
3. Start Threads: The start() method is called on each thread instance, which invokes the run()
method in a new thread of execution.
4. Output: Each thread prints its name and a count from 1 to 5, pausing for 1 second between
each count.

Output of above example:

Thread Thread-0 - Count: 1

Thread Thread-1 - Count: 1

Thread Thread-0 - Count: 2

Thread Thread-1 - Count: 2

Thread Thread-0 - Count: 3

Thread Thread-1 - Count: 3

Thread Thread-0 - Count: 4

Thread Thread-1 - Count: 4

Thread Thread-0 - Count: 5

Thread Thread-1 - Count: 5


7) Demonstrate the thread synchronization in multithreading? Why it is important? Explain with
example.

Thread Synchronization in Multithreading:

Thread synchronization is a mechanism that ensures that multiple threads do not simultaneously
execute critical sections of code that can lead to data inconsistency. This is particularly important
in a multithreading environment where shared resources are accessed by multiple threads.

Importance of Thread Synchronization:

1. Data Integrity: Synchronization helps in maintaining data integrity by preventing simultaneous


access to shared resources, which could result in inconsistent or corrupt data.
2. Avoiding Race Conditions: Without synchronization, race conditions can occur when two or
more threads modify shared data at the same time, leading to unpredictable results.
3. Coherent Program Behavior: Synchronization ensures that threads operate in a controlled
manner, leading to more predictable and understandable program behavior.

Example of Thread Synchronization:

In this example, we will demonstrate thread synchronization using a shared bank account where
multiple threads attempt to withdraw money simultaneously.

class BankAccount {

private int balance = 1000; // Shared resource

// Synchronized method to withdraw money

public synchronized void withdraw(int amount) {

if (balance >= amount) {

System.out.println(Thread.currentThread().getName() + " is going to withdraw: " +


amount);
// Simulating delay

try {

Thread.sleep(500); // Simulate time taken to process the withdrawal

} catch (InterruptedException e) {

e.printStackTrace();

balance -= amount;

System.out.println(Thread.currentThread().getName() + " completed withdrawal.


Remaining balance: " + balance);

} else {

System.out.println(Thread.currentThread().getName() + " insufficient balance to withdraw:


" + amount);

class WithdrawThread extends Thread {

private BankAccount account;

public WithdrawThread(BankAccount account) {

this.account = account;

@Override

public void run() {

// Each thread attempts to withdraw a certain amount

account.withdraw(700);

}
}

public class SynchronizationExample {

public static void main(String[] args) {

BankAccount account = new BankAccount(); // Shared bank account

// Create two threads that will attempt to withdraw money

WithdrawThread thread1 = new WithdrawThread(account);

WithdrawThread thread2 = new WithdrawThread(account);

// Start both threads

thread1.start();

thread2.start();

Explanation of above example:

1. BankAccount Class: This class contains a synchronized method withdraw(), which ensures that
only one thread can execute this method at a time. This prevents simultaneous modifications
to the balance variable.
2. WithdrawThread Class: This class extends Thread and represents a thread that attempts to
withdraw money from the shared bank account. The run() method calls the withdraw()
method of the BankAccount instance.
3. Synchronization Mechanism: The synchronized keyword in the withdraw() method ensures
that when one thread is executing this method, any other thread that tries to execute it will
be blocked until the first thread finishes its execution.
4. Creating and Starting Threads: In the main() method, we create an instance of BankAccount
and two WithdrawThread instances, each attempting to withdraw money from the same
account. Both threads are started, which means they will execute concurrently.
Sample Output

The output will vary, but it will show how synchronization prevents the two threads from
modifying the shared balance at the same time:

Thread-0 is going to withdraw: 700

Thread-1 insufficient balance to withdraw: 700

Thread-0 completed withdrawal. Remaining balance: 300

8) Describe the concept of deadlock and race conditions in multithreaded programming.

In multithreaded programming, deadlock and race conditions are two common problems that can
lead to unexpected behavior and application failures. Here's a detailed explanation of both concepts:
1. Deadlock
Definition: A deadlock occurs when two or more threads are blocked forever, each waiting for a
resource that the other thread holds. This situation creates a cycle of dependencies that cannot be
resolved, effectively halting the execution of the threads involved.
Causes of Deadlock:
Deadlocks typically arise from the following conditions, often referred to as the Coffman conditions:
1. Mutual Exclusion: At least one resource must be held in a non-shareable mode. Only one
thread can use the resource at any given time.
2. Hold and Wait: A thread holding at least one resource is waiting to acquire additional
resources that are currently being held by other threads.
3. No Preemption: Resources cannot be forcibly taken from threads holding them; they must
voluntarily release them.
4. Circular Wait: A circular chain of threads exists, where each thread is waiting for a resource
that the next thread in the chain holds.
Example Program:
class Resource {
private final String name;
public Resource(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
class DeadlockExample implements Runnable {
private final Resource resource1;
private final Resource resource2;
public DeadlockExample(Resource resource1, Resource resource2) {
this.resource1 = resource1;
this.resource2 = resource2;
}
@Override
public void run() {
synchronized (resource1) {
System.out.println(Thread.currentThread().getName() + " locked " + resource1.getName());
try {
// Simulate some work with resource1
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (resource2) {
System.out.println(Thread.currentThread().getName() + " locked " + resource2.getName());
}
}
}
public static void main(String[] args) {
Resource resourceA = new Resource("Resource A");
Resource resourceB = new Resource("Resource B");
Thread thread1 = new Thread(new DeadlockExample(resourceA, resourceB), "Thread 1");
Thread thread2 = new Thread(new DeadlockExample(resourceB, resourceA), "Thread 2");
thread1.start();
thread2.start();
}
}
Output
The output will show that both threads are locked, waiting indefinitely for each other, causing a
deadlock.

2. Race Conditions
Definition: A race condition occurs when two or more threads access shared data and try to change it
at the same time. If the threads are not synchronized properly, the final value of the shared data may
depend on the sequence or timing of how the threads are scheduled, leading to unpredictable results.
Causes of Race Conditions
Race conditions occur primarily due to:
 Lack of synchronization when accessing shared resources.
 The non-atomic operations on shared variables.
Example Program:
class Counter {
private int count = 0;
public void increment() {
count++; // Non-atomic operation
}
public int getCount() {
return count;
}
}
class RaceConditionExample implements Runnable {
private final Counter counter;
public RaceConditionExample(Counter counter) {
this.counter = counter;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
}
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread thread1 = new Thread(new RaceConditionExample(counter));
Thread thread2 = new Thread(new RaceConditionExample(counter));
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println("Final Count: " + counter.getCount()); // Expected: 2000
}
}
Output
The output may not always show Final Count: 2000 due to the race condition, demonstrating that the
final count may vary depending on the timing of thread execution.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy