0% found this document useful (0 votes)
29 views59 pages

Java Record

Uploaded by

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

Java Record

Uploaded by

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

exercise1

Write a JAVA program to display default value of all primitive data type of JAVA.
give this in a format of 1 aim 2 prerequisites (atleast 10 lines) 3 program 4 out
put

1. Aim
To write a Java program that demonstrates and displays the default values assigned
to each of the eight primitive data types when they are declared as instance
variables without explicit initialization.

2. Prerequisites
Before diving into the program, it's essential to have a foundational understanding
of several core Java concepts. A solid grasp of these prerequisites will make the
program's logic and its output much clearer.

Java Class and Main Method: You should know that every Java application starts with
a class, and the execution begins from the public static void main(String[] args)
method.

Variables: Understand that variables are named memory locations used to store data.

Data Types: In a statically-typed language like Java, every variable must have a
declared type, which determines the kind of data it can hold (e.g., a number, a
character).

Primitive Data Types: Be familiar with Java's eight primitive data types: byte,
short, int, long for integer numbers, float and double for floating-point numbers,
char for single characters, and boolean for true/false values.

Instance Variables vs. Local Variables: This is a crucial concept for this program.

Instance variables are declared inside a class but outside any method. They belong
to an object (an instance) of the class. Java automatically assigns default values
to these variables if they are not explicitly initialized.

Local variables are declared inside a method. They must be explicitly initialized
before they are used, as the compiler does not assign them default values.

Object Creation: You should understand how to create an object from a class using
the new keyword (e.g., ClassName obj = new ClassName();). This is necessary to
access instance variables.

System.out.println(): Be familiar with this statement, which is the standard way to


print text or variable values to the console.

Compilation and Execution: You should have a basic idea of how to compile a .java
file into .class bytecode using javac and how to run the compiled code using the
java command.

3. Program
public class DefaultValues {

// These are instance variables.


// They are declared inside the class but outside any method.
// Java assigns default values to them automatically.
static byte defaultByte;
static short defaultShort;
static int defaultInt;
static long defaultLong;
static float defaultFloat;
static double defaultDouble;
static char defaultChar;
static boolean defaultBoolean;

public static void main(String[] args) {


System.out.println("--- Default Values of Java Primitive Data Types ---");

// Displaying the default values.


System.out.println("Default value of byte is: " + defaultByte);
System.out.println("Default value of short is: " + defaultShort);
System.out.println("Default value of int is: " + defaultInt);
System.out.println("Default value of long is: " + defaultLong);
System.out.println("Default value of float is: " + defaultFloat);
System.out.println("Default value of double is: " + defaultDouble);

// The default char is the null character ('\u0000'), which may not be
visible.
System.out.println("Default value of char is: " + defaultChar);
System.out.println("Default value of char (as integer) is: " +
(int)defaultChar);

System.out.println("Default value of boolean is: " + defaultBoolean);


}
}

4. Output
When you compile and run the above Java program, you will see the following output
on the console:

--- Default Values of Java Primitive Data Types ---


Default value of byte is: 0
Default value of short is: 0
Default value of int is: 0
Default value of long is: 0
Default value of float is: 0.0
Default value of double is: 0.0
Default value of char is:
Default value of char (as integer) is: 0
Default value of boolean is: false

Note: The default value for char is the null character (\u0000). It has a numeric
value of 0 but doesn't have a visual representation, which is why it prints as a
blank space.

b)Write a java program that display the roots of a quadratic equation ax2+bx=0.
Calculate the

discriminate D and basing on value of D, describe the nature of root.

1. Aim
To write a Java program that calculates the roots of a standard quadratic equation
of the form ax² + bx + c = 0. The program will first compute the discriminant (D =
b² - 4ac) and then, based on its value, determine and display the nature of the
roots (whether they are real and distinct, real and equal, or complex).
2. Prerequisites
To fully understand and write this program, you should be familiar with the
following concepts:

Quadratic Equations: A fundamental understanding of what a quadratic equation is


and its standard form (ax² + bx + c = 0).

The Quadratic Formula: Knowledge of the formula used to find the roots: x = [-b ±
sqrt(b² - 4ac)] / 2a.

The Discriminant: Understanding that the discriminant (D = b² - 4ac) determines the


nature of the roots.

Java Variables and Data Types: You should know how to declare variables,
particularly using the double data type to handle decimal values for coefficients
and roots.

User Input in Java: Familiarity with the java.util.Scanner class to read input (the
coefficients a, b, and c) from the user via the console.

Conditional Statements: Proficiency in using if-else if-else statements in Java to


execute different blocks of code based on the value of the discriminant (positive,
zero, or negative).

Java Math Class: Knowledge of how to use methods from the Math class, specifically
Math.sqrt() to calculate the square root.

Arithmetic Operations: Comfort with performing basic arithmetic operations like


multiplication, subtraction, and division in Java.

Console Output: Knowing how to use System.out.println() to display information and


results to the user.

Compiling and Running Java Code: A basic ability to compile the .java source file
and run the resulting .class file from the command line.

3. Program
import java.util.Scanner;

public class QuadraticRoots {

public static void main(String[] args) {

// Create a Scanner object to read input from the user


Scanner input = new Scanner(System.in);

System.out.println("--- Quadratic Equation Root Calculator ---");


System.out.println("Enter the coefficients for the equation ax^2 + bx + c =
0");

// Prompt for and read the coefficients


System.out.print("Enter coefficient a: ");
double a = input.nextDouble();

System.out.print("Enter coefficient b: ");


double b = input.nextDouble();

System.out.print("Enter coefficient c: ");


double c = input.nextDouble();

// Calculate the discriminant


double discriminant = b * b - 4 * a * c;

System.out.println("\n----------------------------------------");
System.out.println("The discriminant (D) is: " + discriminant);

// Check the value of the discriminant to determine the nature of the roots
if (discriminant > 0) {
// Two real and distinct roots
double root1 = (-b + Math.sqrt(discriminant)) / (2 * a);
double root2 = (-b - Math.sqrt(discriminant)) / (2 * a);
System.out.println("Nature of roots: Real and Distinct");
System.out.format("Root 1 = %.2f%n", root1);
System.out.format("Root 2 = %.2f%n", root2);
} else if (discriminant == 0) {
// Two real and equal roots
double root1 = -b / (2 * a);
// root2 is the same as root1
System.out.println("Nature of roots: Real and Equal");
System.out.format("Root 1 = Root 2 = %.2f%n", root1);
} else {
// No real roots, two complex roots
double realPart = -b / (2 * a);
double imaginaryPart = Math.sqrt(-discriminant) / (2 * a);
System.out.println("Nature of roots: Complex and Distinct");
System.out.format("Root 1 = %.2f + %.2fi%n", realPart, imaginaryPart);
System.out.format("Root 2 = %.2f - %.2fi%n", realPart, imaginaryPart);
}
System.out.println("----------------------------------------");

// Close the scanner


input.close();
}
}

4. Output
Here are three sample runs of the program, demonstrating the output for each
possible nature of the roots.

Sample Output 1: Real and Distinct Roots (D > 0)

--- Quadratic Equation Root Calculator ---


Enter the coefficients for the equation ax^2 + bx + c = 0
Enter coefficient a: 1
Enter coefficient b: -5
Enter coefficient c: 6

----------------------------------------
The discriminant (D) is: 1.0
Nature of roots: Real and Distinct
Root 1 = 3.00
Root 2 = 2.00
----------------------------------------

Sample Output 2: Real and Equal Roots (D = 0)

--- Quadratic Equation Root Calculator ---


Enter the coefficients for the equation ax^2 + bx + c = 0
Enter coefficient a: 1
Enter coefficient b: 4
Enter coefficient c: 4

----------------------------------------
The discriminant (D) is: 0.0
Nature of roots: Real and Equal
Root 1 = Root 2 = -2.00
----------------------------------------

Sample Output 3: Complex Roots (D < 0)

--- Quadratic Equation Root Calculator ---


Enter the coefficients for the equation ax^2 + bx + c = 0
Enter coefficient a: 1
Enter coefficient b: 4
Enter coefficient c: 5

----------------------------------------
The discriminant (D) is: -4.0
Nature of roots: Complex and Distinct
Root 1 = -2.00 + 1.00i
Root 2 = -2.00 - 1.00i
----------------------------------------

Exercise - 2

a) Write a JAVA program to search for an element in a given list of elements using
binary search mechanism.
1. Aim
To write a Java program that implements the binary search algorithm. The program
will search for a user-specified element within a pre-sorted list of elements and
report whether the element is found and, if so, at what index.

2. Prerequisites
A solid understanding of the following concepts is essential to grasp the workings
of the binary search program.

Arrays: You must be comfortable with what arrays are, how to declare and initialize
them in Java, and how to access their elements using indices.

The Binary Search Concept: This is the most critical prerequisite. You must
understand that binary search is a highly efficient searching algorithm that only
works on sorted arrays. It operates on a "divide and conquer" principle.

Licensed by Google
Algorithm Logic: The algorithm repeatedly divides the search interval in half. If
the value of the search key is less than the item in the middle of the interval, it
narrows the interval to the lower half. Otherwise, it narrows it to the upper half.

Loops in Java: The program uses a while loop to continue the search process as long
as the potential search interval is valid (i.e., the low index is less than or
equal to the high index).
Conditional Statements: Mastery of if-else if-else statements is required to
compare the middle element with the target element and decide which half of the
array to search next.

Variables and Pointers: You should understand the use of variables to act as
"pointers" or indices, specifically for the low, high, and mid points of the search
interval.

User Input (Scanner Class): The program needs to be interactive, so knowledge of


the java.util.Scanner class is necessary to get the array elements and the search
key from the user.

Methods (Functions): The core search logic is encapsulated in its own method for
modularity and reusability. Understanding how to define, call, and return values
from methods is key.

Return Values: The search method needs to communicate its result back to the
caller. It returns the index of the element if found or a conventional value like -
1 to signify that the element was not present.

Time Complexity: It is helpful to know that binary search has a time complexity of
O(log n), making it significantly faster than linear search (O(n)) for large
datasets.

3. Program
import java.util.Scanner;

public class BinarySearch {

/**
* This method performs a binary search on a sorted integer array.
*
* @param arr The sorted array to be searched.
* @param key The element to search for.
* @return The index of the element if found; otherwise, -1.
*/
public static int performBinarySearch(int[] arr, int key) {
int low = 0;
int high = arr.length - 1;

// Continue searching as long as the low index is less than or equal to the
high index
while (low <= high) {
// Calculate mid point to avoid potential overflow
int mid = low + (high - low) / 2;

// Check if the key is present at the mid point


if (arr[mid] == key) {
return mid; // Element found, return its index
}

// If key is greater, ignore the left half


if (arr[mid] < key) {
low = mid + 1;
}
// If key is smaller, ignore the right half
else {
high = mid - 1;
}
}

// If we reach here, the element was not present in the array


return -1;
}

public static void main(String[] args) {


Scanner scanner = new Scanner(System.in);

System.out.println("--- Binary Search Program ---");

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


int n = scanner.nextInt();

int[] array = new int[n];

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


for (int i = 0; i < n; i++) {
System.out.print("Enter element " + (i + 1) + ": ");
array[i] = scanner.nextInt();
}

System.out.print("\nEnter the element you want to search for: ");


int searchKey = scanner.nextInt();

// Call the binary search method


int result = performBinarySearch(array, searchKey);

System.out.println("\n----------------------------------------");
if (result == -1) {
System.out.println("Element " + searchKey + " not found in the
array.");
} else {
System.out.println("Element " + searchKey + " found at index: " +
result);
}
System.out.println("----------------------------------------");

scanner.close();
}
}

4. Output
Here are two sample outputs to show how the program works when an element is found
and when it is not.

Sample Output 1: Element Found

--- Binary Search Program ---


Enter the number of elements in the array: 7
Enter the elements in SORTED ORDER:
Enter element 1: 10
Enter element 2: 22
Enter element 3: 35
Enter element 4: 48
Enter element 5: 59
Enter element 6: 62
Enter element 7: 71
Enter the element you want to search for: 59

----------------------------------------
Element 59 found at index: 4
----------------------------------------

Sample Output 2: Element Not Found

--- Binary Search Program ---


Enter the number of elements in the array: 6
Enter the elements in SORTED ORDER:
Enter element 1: 5
Enter element 2: 15
Enter element 3: 25
Enter element 4: 35
Enter element 5: 45
Enter element 6: 55

Enter the element you want to search for: 30

----------------------------------------
Element 30 not found in the array.
----------------------------------------

b) Write a JAVA program to sort for an element in a given list of elements using
bubble sort

1. Aim
To write a Java program that implements the Bubble Sort algorithm to sort a given
list of integer elements in ascending order. The program will display the list both
before and after the sorting process.

2. Prerequisites
To effectively understand and implement the Bubble Sort algorithm in Java, one
should have a strong grasp of the following fundamental concepts:

Arrays: You must be proficient in declaring, initializing, and manipulating arrays


in Java, including accessing and modifying elements using their indices.

Sorting Algorithms: Have a basic conceptual understanding of what sorting is and


why it's a fundamental operation in computer science.

Bubble Sort Logic: Understand the core mechanism of Bubble Sort. It repeatedly
steps through the list, compares each pair of adjacent items, and swaps them if
they are in the wrong order.

Nested Loops: The algorithm's implementation relies heavily on nested for loops.
The outer loop controls the number of passes through the array, while the inner
loop handles the comparison of adjacent elements.

Conditional Statements: Knowledge of if statements is crucial for comparing two


elements to decide whether a swap is necessary.

Variable Swapping: You need to know the standard technique for swapping the values
of two variables, which typically involves using a third, temporary variable.
Java Methods (Functions): It's good practice to encapsulate the sorting logic
within a separate method for better code organization and reusability.

User Input (Scanner Class): To make the program interactive, you should know how to
use the java.util.Scanner class to read the list of elements from the user.

Console I/O: Familiarity with System.out.println() and System.out.print() is


required to display prompts and the final results to the user.

Time Complexity: While not strictly required to write the code, it is beneficial to
know that Bubble Sort has a worst-case and average time complexity of O(n²), making
it inefficient for large datasets.

3. Program
import java.util.Scanner;
import java.util.Arrays;

public class BubbleSort {

/**
* This method sorts an integer array using the Bubble Sort algorithm.
*
* @param arr The array to be sorted.
*/
public static void bubbleSort(int[] arr) {
int n = arr.length;
boolean swapped;

// Outer loop for passes


for (int i = 0; i < n - 1; i++) {
swapped = false;
// Inner loop for comparisons and swaps
for (int j = 0; j < n - 1 - i; j++) {
// Compare adjacent elements
if (arr[j] > arr[j + 1]) {
// Swap elements if they are in the wrong order
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}

// OPTIMIZATION: If no two elements were swapped by inner loop, then


break
// because the array is already sorted.
if (!swapped) {
break;
}
}
}

public static void main(String[] args) {


Scanner scanner = new Scanner(System.in);

System.out.println("--- Bubble Sort Program ---");

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


int n = scanner.nextInt();
int[] array = new int[n];

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


for (int i = 0; i < n; i++) {
System.out.print("Enter element " + (i + 1) + ": ");
array[i] = scanner.nextInt();
}

System.out.println("\n----------------------------------------");
System.out.println("Original array: " + Arrays.toString(array));

// Call the bubbleSort method to sort the array


bubbleSort(array);

System.out.println("Array after Bubble Sort: " + Arrays.toString(array));


System.out.println("----------------------------------------");

scanner.close();
}
}

4. Output
Here is a sample run of the program showing how it takes an unsorted list and sorts
it.

--- Bubble Sort Program ---


Enter the number of elements in the array: 6
Enter the elements of the array:
Enter element 1: 64
Enter element 2: 34
Enter element 3: 25
Enter element 4: 12
Enter element 5: 22
Enter element 6: 11

----------------------------------------
Original array: [64, 34, 25, 12, 22, 11]
Array after Bubble Sort: [11, 12, 22, 25, 34, 64]
----------------------------------------

c) Write a JAVA program using StringBuffer to delete, remove character.


1. Aim
To write a Java program that demonstrates the character deletion capabilities of
the StringBuffer class. The program will showcase how to remove a single character
at a specific position using deleteCharAt() and how to remove a substring (a
sequence of characters) from a given range using delete().

2. Prerequisites
To fully comprehend this program, a foundational knowledge of the following Java
concepts is recommended:

Java Strings: You must understand that String objects in Java are immutable,
meaning they cannot be changed after they are created.

Mutable vs. Immutable Objects: Grasping the difference between immutable objects
(String) and mutable objects (StringBuffer, StringBuilder) is key to understanding
why StringBuffer is used for modifications.

StringBuffer Class: You should know what the StringBuffer class is and its purpose:
to provide a mutable sequence of characters.

Object Instantiation: Knowledge of how to create an object from a class using the
new keyword (e.g., StringBuffer sb = new StringBuffer("text");).

Method Calling: Familiarity with calling methods on an object using the dot
operator (e.g., sb.delete()).

Zero-Based Indexing: Understanding that characters in a string or StringBuffer are


accessed by an index that starts at 0.

deleteCharAt(int index) Method: Knowing that this method removes the single
character at the specified index.

delete(int start, int end) Method: Understanding that this method removes the
characters in a substring beginning at the specified start index and extending to
the character at index end - 1.

Console Output: You should know how to use System.out.println() to print text and
variable contents to the console.

Basic Java Program Structure: Familiarity with the public static void main(String[]
args) method and the overall structure of a simple Java class.

3. Program
public class StringBufferDeleteDemo {

public static void main(String[] args) {

// 1. Create a StringBuffer object with an initial string.


StringBuffer sb = new StringBuffer("Hello Java Programming!");

System.out.println("--- StringBuffer Deletion Demonstration ---");


System.out.println("Original StringBuffer content: " + sb);
System.out.println("Original length: " + sb.length());
System.out.println("-------------------------------------------");

// 2. Using deleteCharAt() to remove a single character.


// Let's remove the character at index 4, which is 'o'.
// The index is 0-based: H(0) e(1) l(2) l(3) o(4)
sb.deleteCharAt(4);

System.out.println("After using deleteCharAt(4): " + sb);


System.out.println("New length: " + sb.length());
System.out.println("-------------------------------------------");

// 3. Using delete() to remove a range of characters (a substring).


// The new string is "Hell Java Programming!".
// Let's remove the substring " Java" which is from index 5 up to (but not
including) 10.
// H(0) e(1) l(2) l(3) (4) J(5) a(6) v(7) a(8) (9)
sb.delete(5, 10);

System.out.println("After using delete(5, 10): " + sb);


System.out.println("Final length: " + sb.length());
System.out.println("-------------------------------------------");
}
}

4. Output
The following is the exact output produced when the above Java program is compiled
and executed.

--- StringBuffer Deletion Demonstration ---


Original StringBuffer content: Hello Java Programming!
Original length: 23
-------------------------------------------
After using deleteCharAt(4): Hell Java Programming!
New length: 22
-------------------------------------------
After using delete(5, 10): Hell Programming!
Final length: 17
-------------------------------------------

Exercise - 3

a) Write a JAVA program to implement class mechanism. Create a class, methods and
invoke them inside main method.
1. Aim
To write a Java program that illustrates the fundamental class and object
mechanism. The goal is to define a custom class with attributes (fields) and
behaviors (methods), then create instances (objects) of that class and invoke their
methods from within the main method.

2. Prerequisites
A solid understanding of the following concepts is essential for grasping the
program's structure and logic.

Object-Oriented Programming (OOP): A basic understanding of the OOP paradigm, where


programs are organized around data, or "objects," rather than functions and logic.

Class vs. Object: This is the most critical concept. A class is a blueprint or
template for creating objects. An object is a real-world instance of a class.

Fields (Attributes/Instance Variables): These are variables within a class that


define the properties or state of an object (e.g., a Dog class might have fields
for name and age).

Methods (Behaviors): These are functions defined inside a class that describe the
actions an object can perform (e.g., a Dog object can bark()).

main Method: Understanding that public static void main(String[] args) is the
special entry point for any Java application. Execution starts here.

Object Instantiation (The new Keyword): You must know how to use the new keyword to
create an object from a class definition (e.g., Dog myDog = new Dog();).

The Dot Operator (.): Knowledge of the dot operator is crucial for accessing an
object's fields and invoking its methods (e.g., myDog.name or myDog.bark()).

Constructors: A constructor is a special method that is automatically called when


an object is created. It's used to initialize the object's state.
The this Keyword: Understanding that this is a reference to the current object,
used to differentiate between instance variables and local parameters.

Basic Java Syntax: Familiarity with Java's syntax for declaring variables, defining
classes and methods, and using System.out.println() for console output.

3. Program
This program defines a Dog class and then, in the ClassDemo class's main method, it
creates and interacts with two different Dog objects.

/**
* This is the Dog class, which acts as a blueprint for creating Dog objects.
* It has properties (name, breed) and methods (bark, displayInfo).
*/
class Dog {
// Fields (Instance Variables) to store the state of a Dog object
String name;
String breed;

// Constructor to initialize a new Dog object


public Dog(String name, String breed) {
System.out.println("A new dog is being created...");
this.name = name; // 'this.name' refers to the instance variable
this.breed = breed; // 'name' refers to the parameter
}

/**
* A method that represents the dog's barking behavior.
*/
public void bark() {
System.out.println(this.name + " says: Woof! Woof!");
}

/**
* A method to display all the information about the dog.
*/
public void displayInfo() {
System.out.println("Dog's Name: " + this.name);
System.out.println("Dog's Breed: " + this.breed);
}
}

/**
* This is the main class that will run the program.
*/
public class ClassDemo {

public static void main(String[] args) {


System.out.println("--- Class and Object Demonstration ---");
System.out.println("Program starting in the main method.");
System.out.println("--------------------------------------\n");

// 1. Create an instance (object) of the Dog class


// This calls the Dog constructor
Dog dog1 = new Dog("Buddy", "Golden Retriever");

// 2. Invoke the methods on the 'dog1' object


System.out.println("\nInvoking methods for the first dog...");
dog1.displayInfo();
dog1.bark();

System.out.println("\n--------------------------------------\n");

// 3. Create a second instance of the Dog class


Dog dog2 = new Dog("Lucy", "Poodle");

// 4. Invoke methods on the 'dog2' object to show it's independent


System.out.println("\nInvoking methods for the second dog...");
dog2.displayInfo();
dog2.bark();

System.out.println("\n--------------------------------------");
System.out.println("Program finished.");
}
}

4. Output
The following is the exact output that will be displayed on the console when the
ClassDemo.java program is compiled and executed.

--- Class and Object Demonstration ---


Program starting in the main method.
--------------------------------------

A new dog is being created...

Invoking methods for the first dog...


Dog's Name: Buddy
Dog's Breed: Golden Retriever
Buddy says: Woof! Woof!

--------------------------------------

A new dog is being created...

Invoking methods for the second dog...


Dog's Name: Lucy
Dog's Breed: Poodle
Lucy says: Woof! Woof!

--------------------------------------
Program finished.

b) Write a JAVA program implement method overloading.

1. Aim
To write a Java program that demonstrates the concept of method overloading. The
program will define a class containing multiple methods with the same name but
different parameters (in terms of number or data type). The goal is to show how the
Java compiler determines which method to execute based on the arguments passed
during the method call.

2. Prerequisites
To understand and implement method overloading in Java, a firm grasp of the
following concepts is required:
Methods: Understanding that methods are blocks of code that perform a specific task
and are associated with a class.

Method Signature: This is the most crucial concept for overloading. In Java, a
method signature is composed of the method's name and its parameter list (the
number, type, and order of parameters).

Polymorphism: Method overloading is a form of compile-time polymorphism (or static


polymorphism), where the decision of which method to call is made at compile time.

Parameters and Arguments: Knowing the difference between parameters (variables in


the method declaration) and arguments (the actual values passed to the method when
it is invoked).

Return Type: It's essential to understand that the return type is not part of the
method signature. You cannot overload a method just by changing its return type.

Data Types: A clear understanding of Java's primitive data types (int, double,
etc.) is necessary, as overloading often involves creating methods that accept
different types of data.

Class and Object: The program will be structured within a class, and methods will
be called on an instance (object) of that class.

The main Method: Recognizing that public static void main(String[] args) is the
entry point for the application, from where the overloaded methods will be called.

Method Invocation: Knowing the syntax for calling a method on an object and passing
the required arguments.

Compiler Role: Understanding that the Java compiler is responsible for matching the
method call with the correct method definition based on the arguments provided.
This process is called overload resolution.

3. Program
This program defines a Printer class with multiple display methods. Each display
method has the same name but accepts different types or numbers of parameters.

/**
* This class demonstrates method overloading with a method named 'display'.
*/
class Printer {

/**
* Method to display an integer.
* @param a The integer value to display.
*/
public void display(int a) {
System.out.println("-> Called display(int a)");
System.out.println(" Displaying integer: " + a);
}

/**
* Method to display a String. This is an overload of the display method.
* @param s The String value to display.
*/
public void display(String s) {
System.out.println("-> Called display(String s)");
System.out.println(" Displaying String: \"" + s + "\"");
}

/**
* Method to display an integer and a String. This is another overload.
* @param a The integer value.
* @param s The String value.
*/
public void display(int a, String s) {
System.out.println("-> Called display(int a, String s)");
System.out.println(" Displaying Number: " + a + " and String: \"" + s +
"\"");
}

/**
* Method to display a String and an integer. This is another overload,
* demonstrating that the order of parameters matters.
* @param s The String value.
* @param a The integer value.
*/
public void display(String s, int a) {
System.out.println("-> Called display(String s, int a)");
System.out.println(" Displaying String: \"" + s + "\" and Number: " + a);
}
}

/**
* This is the main class to test the method overloading in the Printer class.
*/
public class MethodOverloadingDemo {

public static void main(String[] args) {


System.out.println("--- Method Overloading Demonstration ---");

// Create an object of the Printer class


Printer myPrinter = new Printer();

System.out.println("\nCalling the overloaded 'display' methods:");


System.out.println("-----------------------------------------");

// Call the first version of display with an integer argument


myPrinter.display(100);
System.out.println("-----------------------------------------");

// Call the second version with a String argument


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

// Call the third version with an int and then a String


myPrinter.display(25, "Apples");
System.out.println("-----------------------------------------");

// Call the fourth version with a String and then an int


myPrinter.display("Oranges", 50);
System.out.println("-----------------------------------------");
}
}

4. Output
The following is the exact output produced when the MethodOverloadingDemo.java
program is compiled and executed.

--- Method Overloading Demonstration ---

Calling the overloaded 'display' methods:


-----------------------------------------
-> Called display(int a)
Displaying integer: 100
-----------------------------------------
-> Called display(String s)
Displaying String: "Hello, Java!"
-----------------------------------------
-> Called display(int a, String s)
Displaying Number: 25 and String: "Apples"
-----------------------------------------
-> Called display(String s, int a)
Displaying String: "Oranges" and Number: 50
-----------------------------------------

c) Write a JAVA program to implement constructor.

1. Aim
To write a Java program to implement a constructor for initializing an object's
state.

2. Prerequisites
Understanding constructors requires familiarity with several core Java concepts. A
constructor is a special method that is automatically called when an object of a
class is created. Its primary purpose is to initialize the instance variables of
the new object.

Key points to understand are:

Class and Object: A class is a blueprint for creating objects. An object is an


instance of a class, with its own state (instance variables) and behavior
(methods).

new Keyword: The new keyword is used to allocate memory for a new object and create
an instance of a class.

Constructor Naming Rule: A constructor must have the exact same name as the class
it belongs to.

No Return Type: Unlike other methods, a constructor does not have an explicit
return type, not even void.

Purpose of Initialization: Constructors are essential for setting the initial


values of an object's properties. Without them, fields would be initialized to
default values (0 for numbers, null for objects), which may not be desirable.

Types of Constructors:

Default Constructor: If you don't define any constructor in a class, the Java
compiler provides a default, no-argument constructor.

Parameterized Constructor: A constructor that accepts one or more parameters. This


is the most common type, used to initialize an object with specific values at the
time of its creation.
Method Invocation: Basic knowledge of how to call methods on an object using the
dot (.) operator is necessary.

main method: Understanding that the main method is the entry point for the
execution of any Java application.

3. Program
// We define a class named 'Car'
class Car {
// Instance variables for the Car class
String model;
int year;

// This is the parameterized constructor for the Car class.


// It takes a model name and a year as arguments.
public Car(String modelName, int carYear) {
System.out.println("Constructor called!");
// 'this.model' refers to the instance variable of the current object.
// 'modelName' is the local parameter passed to the constructor.
this.model = modelName;
this.year = carYear;
}

// A simple method to display the car's details


public void displayDetails() {
System.out.println("Car Model: " + model);
System.out.println("Car Year: " + year);
}
}

// This is the main class where the program execution begins


public class Main {
public static void main(String[] args) {
// Create an object of the Car class.
// This statement calls the constructor Car(String, int).
// We pass "Tesla Model S" and 2023 as arguments.
Car myCar = new Car("Tesla Model S", 2023);

// Call the displayDetails method on the myCar object to show its state.
myCar.displayDetails();
}
}

4. Output
Constructor called!
Car Model: Tesla Model S
Car Year: 2023

d) Write a JAVA program to implement constructor overloading

1. Aim
To write a Java program to implement constructor overloading, which allows a class
to have multiple constructors with different parameter lists.

2. Prerequisites
Constructor overloading is an application of polymorphism in Java. To fully grasp
this concept, one must be familiar with the fundamentals of constructors and method
overloading.

Key points to understand are:

Constructor Basics: A constructor is a special method used to initialize objects.


It shares the same name as the class and has no return type.

Method Overloading: This is the ability to define multiple methods with the same
name within the same class, as long as their parameter lists differ. The difference
can be in the number of parameters, the data type of parameters, or the order of
parameters.

Constructor Overloading: Applying the principle of overloading to constructors. A


class can have more than one constructor, each with a unique signature (parameter
list). This provides flexibility for creating objects in different ways.

Compiler's Role: The Java compiler decides which constructor to execute based on
the arguments provided when you create an object using the new keyword. For
example, new Student() would call the no-argument constructor, while new
Student("Alice", 101) would call the constructor that accepts a String and an
integer.

Flexibility in Object Creation: This feature is incredibly useful. It allows you to


create objects with default values (using a no-argument constructor), with partial
information, or with a complete set of initial values, all while using the same
class blueprint.

this() keyword (Optional but related): You can use this() to call one constructor
from another within the same class. This is known as constructor chaining and helps
reduce code duplication.

3. Program
// We define a class named 'Student'
class Student {
// Instance variables for the Student class
int studentId;
String studentName;
String grade;

// Constructor 1: No arguments (Default-like constructor)


// Initializes the object with default values.
public Student() {
System.out.println("No-argument constructor called.");
this.studentId = 0;
this.studentName = "Unknown";
this.grade = "N/A";
}

// Constructor 2: Takes studentId and studentName as parameters


public Student(int id, String name) {
System.out.println("Two-argument constructor (int, String) called.");
this.studentId = id;
this.studentName = name;
this.grade = "10th"; // A default grade
}

// Constructor 3: Takes all three parameters


public Student(int id, String name, String studentGrade) {
System.out.println("Three-argument constructor (int, String, String)
called.");
this.studentId = id;
this.studentName = name;
this.grade = studentGrade;
}

// A method to display the student's details


public void displayDetails() {
System.out.println("Student ID: " + studentId);
System.out.println("Student Name: " + studentName);
System.out.println("Grade: " + grade);
System.out.println("--------------------");
}
}

// Main class to demonstrate constructor overloading


public class Main {
public static void main(String[] args) {
// Creating student1 using the no-argument constructor
Student student1 = new Student();
student1.displayDetails();

// Creating student2 using the two-argument constructor


Student student2 = new Student(101, "Alice");
student2.displayDetails();

// Creating student3 using the three-argument constructor


Student student3 = new Student(102, "Bob", "12th");
student3.displayDetails();
}
}

4. Output
No-argument constructor called.
Student ID: 0
Student Name: Unknown
Grade: N/A
--------------------
Two-argument constructor (int, String) called.
Student ID: 101
Student Name: Alice
Grade: 10th
--------------------
Three-argument constructor (int, String, String) called.
Student ID: 102
Student Name: Bob
Grade: 12th
--------------------

Exercise - 4

a) Write a JAVA program to implement Single Inheritance

1. Aim
To write a Java program to implement single inheritance, where a new class
(subclass) is derived from an existing class (superclass), inheriting its fields
and methods.
2. Prerequisites
Understanding single inheritance in Java requires knowledge of fundamental object-
oriented programming (OOP) principles. Inheritance is a core OOP concept that
promotes code reusability and establishes a logical relationship between classes.

Key concepts to be familiar with are:

Class and Object: A class is a blueprint for creating objects. An object is an


instance of a class.

Inheritance: It is the mechanism by which one object acquires all the properties
and behaviors of a parent object. This represents an "is-a" relationship. For
example, a Dog is an Animal.

Superclass (Parent/Base Class): The class whose features are inherited. It is the
class being extended.

Subclass (Child/Derived Class): The class that inherits the other class. It can add
its own unique fields and methods.

extends Keyword: This keyword is used to establish the inheritance relationship


between two classes. The syntax is: class Subclass extends Superclass { ... }.

Code Reusability: Inheritance is a powerful tool for reusing code. The subclass can
directly use the methods and fields of the superclass without rewriting them.

Method Overriding (Related Concept): A subclass can provide a specific


implementation for a method that is already defined in its superclass.

Access Modifiers: The visibility of superclass members (public, protected, private)


determines whether they can be accessed by the subclass. public and protected
members are accessible, while private members are not.

Object Creation: Understanding how to create an instance of the subclass using the
new keyword. An object of the subclass has access to members of both its own class
and its superclass.

3. Program
// Superclass or Parent class
class Animal {
// A method in the superclass
public void eat() {
System.out.println("This animal eats food.");
}
}

// Subclass or Child class that inherits from Animal


// The 'extends' keyword establishes the inheritance relationship
class Dog extends Animal {
// A method specific to the Dog subclass
public void bark() {
System.out.println("The dog barks.");
}
}

// Main class to demonstrate Single Inheritance


public class Main {
public static void main(String[] args) {
// Create an object of the subclass 'Dog'
Dog myDog = new Dog();

// Call the 'eat()' method from the superclass 'Animal'


// This is possible because Dog inherits from Animal
myDog.eat();

// Call the 'bark()' method from the subclass 'Dog'


myDog.bark();
}
}

4. Output
This animal eats food.
The dog barks.

b) Write a JAVA program to implement multi level Inheritance

1. Aim
To write a Java program to implement multilevel inheritance, where a derived class
serves as the base class for another class, forming a chain of inheritance.

2. Prerequisites
Multilevel inheritance builds upon the concept of single inheritance. It involves a
chain of classes, where one class extends another, which in turn extends a third
class. A solid understanding of the following concepts is essential.

Key concepts to be familiar with are:

Single Inheritance: The fundamental idea of a subclass inheriting from a single


superclass using the extends keyword.

Inheritance Chain: In multilevel inheritance, a class acts as both a subclass to


one class and a superclass to another. For example, if class C extends B, and class
B extends A, this forms a multilevel inheritance chain (A → B → C).

Transitive Nature: Inheritance in this model is transitive. The most derived class
(C) inherits all the accessible members not only from its immediate superclass (B)
but also from its grandparent class (A).

"Is-a" Relationship: The "is-a" relationship holds true throughout the chain. Using
the A → B → C example, C is a B, and B is an A.

extends Keyword: This keyword is used at each level of the chain to establish the
parent-child relationship.

Code Reusability: This structure enhances code reusability by allowing a class to


inherit features from multiple levels of ancestors.

Access Modifiers: The accessibility (public, protected) of members in the


superclasses dictates whether they can be accessed by the classes lower down in the
inheritance hierarchy. private members are never inherited.

Object Instantiation: When an object of the most derived class is created, it


contains all the non-private fields and methods from every class in its inheritance
chain.

3. Program
// The base or 'Grandparent' class
class Vehicle {
public void startEngine() {
System.out.println("Engine has started.");
}
}

// The intermediate or 'Parent' class, which inherits from Vehicle


class Car extends Vehicle {
public void drive() {
System.out.println("The car is moving.");
}
}

// The most derived or 'Child' class, which inherits from Car


class SportsCar extends Car {
public void accelerate() {
System.out.println("The sports car is accelerating at high speed!");
}
}

// Main class to demonstrate Multilevel Inheritance


public class Main {
public static void main(String[] args) {
// Create an object of the most derived class, 'SportsCar'
SportsCar mySportsCar = new SportsCar();

// Call the method from the 'Vehicle' class (Grandparent)


mySportsCar.startEngine();

// Call the method from the 'Car' class (Parent)


mySportsCar.drive();

// Call the method from the 'SportsCar' class (Child)


mySportsCar.accelerate();
}
}

4. Output
Engine has started.
The car is moving.
The sports car is accelerating at high speed!

c) Write a JAVA program for abstract class to find areas of different shapes

1. Aim
To write a Java program that demonstrates the use of an abstract class to calculate
the areas of different geometric shapes, enforcing a common structure for all
derived shape classes.

2. Prerequisites
Understanding how to use abstract classes is crucial for leveraging one of the core
principles of Object-Oriented Programming (OOP): Abstraction. This program requires
familiarity with several related concepts.

Key concepts to be familiar with are:

Abstraction: The concept of hiding complex implementation details and showing only
the essential features of the object. An abstract class is a primary way to achieve
abstraction in Java.

Abstract Class: A class that is declared with the abstract keyword. It cannot be
instantiated, meaning you cannot create an object of an abstract class. It serves
as a blueprint for other classes.

Abstract Method: A method declared with the abstract keyword and without any
implementation (no method body). It exists only as a signature.

Inheritance (extends): Subclasses must extend the abstract class to use its
functionality.

Implementation Mandate: Any subclass that extends an abstract class must provide a
concrete implementation for all of its abstract methods, or the subclass must also
be declared as abstract.

Concrete Class: A regular class (non-abstract) that provides the full


implementation for all the methods it declares or inherits. In this example,
Rectangle and Circle are concrete classes.

Polymorphism: This allows us to perform a single action in different ways. Here,


the calculateArea() method is defined in the abstract Shape class, but its actual
calculation (the "how") is implemented differently in each subclass (Rectangle,
Circle).

Purpose: Abstract classes are used to define a standard interface or template for a
group of related subclasses, ensuring they all have a common set of methods.

3. Program
// Abstract class 'Shape'
// This class cannot be instantiated directly.
abstract class Shape {
// An abstract method 'calculateArea()'
// It has no body and must be implemented by any subclass.
public abstract double calculateArea();

// An abstract class can also have concrete methods.


public void display() {
System.out.println("Calculating the area of a shape.");
}
}

// Concrete class 'Rectangle' that extends Shape


class Rectangle extends Shape {
private double length;
private double width;

// Constructor for Rectangle


public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}

// Provide implementation for the abstract method from Shape


@Override
public double calculateArea() {
return length * width;
}
}
// Concrete class 'Circle' that extends Shape
class Circle extends Shape {
private double radius;

// Constructor for Circle


public Circle(double radius) {
this.radius = radius;
}

// Provide implementation for the abstract method from Shape


@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}

// Main class to demonstrate the abstract class implementation


public class Main {
public static void main(String[] args) {
// We cannot create an object of Shape like this:
// Shape myShape = new Shape(); // This will cause a compilation error.

// Create an object of the concrete class Rectangle


Shape rectangle = new Rectangle(10.0, 5.0);
rectangle.display();
System.out.println("Area of Rectangle: " + rectangle.calculateArea());

System.out.println("--------------------");

// Create an object of the concrete class Circle


Shape circle = new Circle(7.0);
circle.display();
System.out.println("Area of Circle: " + circle.calculateArea());
}
}

4. Output
Calculating the area of a shape.
Area of Rectangle: 50.0
--------------------
Calculating the area of a shape.
Area of Circle: 153.93804002589985

Exercise - 5

a) Write a JAVA program give example for "super" keyword.


1. Aim
To write a Java program that demonstrates the three primary uses of the super
keyword:

To call the constructor of the immediate superclass.

To access an instance variable of the immediate superclass when it is hidden by the


subclass.

To invoke a method of the immediate superclass when it has been overridden by the
subclass.
2. Prerequisites
The super keyword in Java is a reference variable that is used to refer to the
immediate parent class object. Its usage is fundamentally tied to the concept of
inheritance. A clear understanding of the following Object-Oriented Programming
(OOP) principles is required.

Key concepts to be familiar with are:

Inheritance: The mechanism where a new class (subclass) derives properties and
behaviors (fields and methods) from an existing class (superclass). The extends
keyword is used to establish this relationship.

Superclass and Subclass: The class being inherited from is the superclass (or
parent class), and the class that inherits is the subclass (or child class).

Constructor Chaining: When a subclass constructor is called, it implicitly or


explicitly calls a constructor from its superclass. super() is the explicit way to
do this. If not used, the compiler automatically adds a call to the superclass's
no-argument constructor.

Method Overriding: This occurs when a subclass provides a specific implementation


for a method that is already defined in its superclass. super allows the subclass
to still access the original, overridden method from the parent.

Variable Shadowing (or Hiding): If a subclass declares a variable with the same
name as an instance variable in its superclass, the subclass's variable "hides" the
superclass's variable. The super keyword provides a way to access the hidden
variable from the superclass.

this vs. super: While this is a reference to the current object, super is a
reference to the parent part of the current object.

3. Program
// The superclass or 'Parent' class
class Animal {
String type = "Generic Animal";

// Superclass constructor
public Animal() {
System.out.println("Animal class constructor called.");
}

// Superclass method
public void displayInfo() {
System.out.println("This is an animal.");
}
}

// The subclass or 'Child' class


class Dog extends Animal {
// This variable hides the 'type' variable from the Animal class
String type = "Canine";

// Subclass constructor
public Dog() {
// 1. Use of super() to call the superclass constructor.
// This call is often implicit but shown here for clarity.
super();
System.out.println("Dog class constructor called.");
}

// Overridden method
@Override
public void displayInfo() {
System.out.println("This is a dog.");
}

public void printDetails() {


// Call the displayInfo() method of the current (Dog) class
displayInfo();

// 3. Use of super to invoke the superclass method


super.displayInfo();

// Print the 'type' variable of the current (Dog) class


System.out.println("Type from Dog class: " + type);

// 2. Use of super to access the superclass instance variable


System.out.println("Type from Animal class: " + super.type);
}
}

// Main class to demonstrate the 'super' keyword


public class Main {
public static void main(String[] args) {
// Create an object of the subclass
Dog myDog = new Dog();

System.out.println("\n--- Calling printDetails() method ---");


myDog.printDetails();
}
}

4. Output
Animal class constructor called.
Dog class constructor called.

--- Calling printDetails() method ---


This is a dog.
This is an animal.
Type from Dog class: Canine
Type from Animal class: Generic Animal

b) Write a JAVA program to implement Interface. What kind of Inheritance can be


achieved?

1. Aim
To write a Java program that demonstrates how to define and use an interface. The
program will also illustrate how interfaces are Java's mechanism for achieving
multiple inheritance, allowing a single class to inherit behaviors from multiple,
unrelated sources.

2. Prerequisites
Interfaces are a fundamental concept in Java that enable abstraction and a form of
multiple inheritance. To fully grasp their implementation, one must be familiar
with the following principles.

An interface is a completely abstract type that is used to group related methods


with empty bodies. It acts as a contract that a class can promise to fulfill.

Key concepts to be familiar with are:

interface Keyword: Used to declare an interface.

Abstract Methods: By default, all methods declared in an interface are public and
abstract. They have no implementation body.

implements Keyword: A class uses the implements keyword to inherit from an


interface. A class must provide a concrete implementation for all the abstract
methods of the interface it implements.

Constants: All variables declared in an interface are implicitly public, static,


and final. They are constants, not instance variables.

Multiple Inheritance: This is the primary type of inheritance achieved using


interfaces. While a Java class can only extend one superclass (single inheritance),
it can implement multiple interfaces. This allows a class to inherit the abstract
methods of several interfaces, effectively combining different behaviors. This
design avoids the "Diamond Problem" of ambiguity that can arise with multiple class
inheritance, where a class inherits conflicting methods from two parent classes.

Abstraction: Interfaces are a core mechanism for achieving 100% abstraction,


defining a contract of what a class can do without specifying how it does it.

3. Program
// First interface defining a 'drawable' behavior
interface Drawable {
// Abstract method (public abstract by default)
void draw();
}

// Second interface defining a 'loggable' behavior


interface Loggable {
// Abstract method
void logInfo(String message);
}

// A concrete class 'Circle' that implements BOTH interfaces


// This demonstrates multiple inheritance
class Circle implements Drawable, Loggable {
private double radius;

public Circle(double radius) {


this.radius = radius;
}

// Providing the implementation for the draw() method from Drawable


@Override
public void draw() {
System.out.println("Drawing a circle with radius: " + radius);
}

// Providing the implementation for the logInfo() method from Loggable


@Override
public void logInfo(String message) {
System.out.println("LOG: " + message);
}
}

// Main class to demonstrate the interface implementation


public class Main {
public static void main(String[] args) {
// Create an object of the Circle class
Circle myCircle = new Circle(10.5);

// Call the method from the Drawable interface


myCircle.draw();

// Call the method from the Loggable interface


myCircle.logInfo("Circle object has been created and drawn successfully.");

// We can also create a reference of the interface type


Drawable shape = new Circle(5.0);
shape.draw(); // Can only call Drawable methods through this reference
}
}

4. Output
Drawing a circle with radius: 10.5
LOG: Circle object has been created and drawn successfully.
Drawing a circle with radius: 5.0

c) Write a JAVA program that implements Runtime polymorphism

1. Aim
To write a Java program that demonstrates runtime polymorphism, also known as
dynamic method dispatch. The program will show how a superclass reference variable
can invoke the overridden methods of different subclass objects at runtime, leading
to different behaviors from the same method call.

2. Prerequisites
Runtime polymorphism is a cornerstone of Object-Oriented Programming (OOP) where
the method to be executed is determined at runtime instead of compile time. A
thorough understanding of the following concepts is essential for grasping its
implementation.

Key concepts to be familiar with are:

Inheritance: The mechanism where a subclass acquires the properties and methods of
a superclass using the extends keyword. This parent-child relationship is the
foundation for polymorphism.

Method Overriding: This occurs when a subclass provides a specific implementation


for a method that is already defined in its superclass. For overriding to occur,
the method in the subclass must have the same name, return type, and parameters as
the one in the parent class.

Upcasting: This is the process of treating a subclass object as an object of its


superclass type. A reference variable of a superclass type is allowed to hold an
object of any of its subclass types (e.g., Superclass ref = new Subclass();).
Dynamic Method Dispatch: This is the core mechanism that enables runtime
polymorphism. When an overridden method is called through a superclass reference,
the Java Virtual Machine (JVM) dynamically determines which version of the method
to execute based on the actual object the reference is pointing to at that moment,
not the type of the reference variable itself. This resolution happens during the
program's execution, hence the term "runtime."

3. Program
// The superclass or 'Parent' class
class Shape {
// The method to be overridden by subclasses
public void draw() {
System.out.println("Drawing a generic shape.");
}
}

// A subclass that extends Shape


class Circle extends Shape {
// Overriding the draw() method for the Circle class
@Override
public void draw() {
System.out.println("Drawing a circle.");
}
}

// Another subclass that extends Shape


class Rectangle extends Shape {
// Overriding the draw() method for the Rectangle class
@Override
public void draw() {
System.out.println("Drawing a rectangle.");
}
}

// A third subclass that extends Shape


class Triangle extends Shape {
// Overriding the draw() method for the Triangle class
@Override
public void draw() {
System.out.println("Drawing a triangle.");
}
}

// Main class to demonstrate runtime polymorphism


public class Main {
public static void main(String[] args) {
// A reference variable of the superclass 'Shape'
Shape myShape;

// --- DYNAMIC METHOD DISPATCH IN ACTION ---

// 1. myShape points to a Circle object


myShape = new Circle();
// At runtime, the JVM sees myShape refers to a Circle,
// so it calls the draw() method of the Circle class.
myShape.draw();
// 2. myShape now points to a Rectangle object
myShape = new Rectangle();
// At runtime, the JVM sees myShape refers to a Rectangle,
// so it calls the draw() method of the Rectangle class.
myShape.draw();

// 3. myShape now points to a Triangle object


myShape = new Triangle();
// At runtime, the JVM sees myShape refers to a Triangle,
// so it calls the draw() method of the Triangle class.
myShape.draw();
}
}

4. Output
Drawing a circle.
Drawing a rectangle.
Drawing a triangle.

Exercise - 6

a) Write a JAVA program that describes exception handling mechanism


1. Aim
To write a Java program that demonstrates the core mechanisms of exception handling
using the try, catch, finally, throw, and throws keywords. The program will handle
a potential ArithmeticException to prevent an abnormal program termination and
ensure graceful execution.

2. Prerequisites
Exception handling is a critical feature in Java for managing runtime errors and
maintaining the normal flow of an application. To understand its implementation,
familiarity with the following concepts is essential.

An exception is an event that disrupts the normal flow of a program's instructions.


When an error occurs within a method, the method creates an exception object and
hands it off to the runtime system.

Key mechanisms and keywords are:

try block: This is the block where you place the code that might generate an
exception. It is the section of code to be monitored for errors.

catch block: This block catches and handles the exception. It is executed only if
an exception of the type it specifies occurs within the associated try block. A try
block can be followed by multiple catch blocks to handle different types of
exceptions.

finally block: This block is always executed, regardless of whether an exception is


thrown or caught. It is placed after the try and catch blocks and is typically used
for cleanup code, such as closing files or releasing system resources.

throw keyword: This is used to manually throw an exception, either a new one or one
that has just been caught. It is typically used for custom or explicit error
conditions.

throws keyword: This is used in a method's signature to declare the types of


exceptions that the method might throw but does not handle internally. It delegates
the responsibility of handling the exception to the caller method.

Exception Hierarchy: In Java, all exception types are subclasses of the


java.lang.Throwable class. This hierarchy is divided into Error (irrecoverable
system errors) and Exception (errors that can often be handled by the application).

3. Program
public class Main {

/**
* This method attempts to divide two numbers.
* It uses the 'throws' keyword to indicate it might throw an
ArithmeticException
* if the divisor is zero, delegating handling to the caller.
* It also uses the 'throw' keyword to create and throw the exception
explicitly.
*/
public static int divideNumbers(int numerator, int denominator) throws
ArithmeticException {
if (denominator == 0) {
// Manually throwing an exception using the 'throw' keyword.
throw new ArithmeticException("Division by zero is not allowed.");
}
return numerator / denominator;
}

public static void main(String[] args) {

System.out.println("--- Attempting a valid division ---");


// Example 1: No exception occurs.
try {
System.out.println("Entering the try block...");
int result = divideNumbers(100, 5);
System.out.println("The result of 100 / 5 is: " + result);
System.out.println("Leaving the try block normally.");
} catch (ArithmeticException e) {
// This 'catch' block will not be executed in this case.
System.out.println("Caught an exception: " + e.getMessage());
} finally {
// The 'finally' block is always executed.
System.out.println("This is the finally block. It always runs.");
}

System.out.println("\n----------------------------------------\n");

System.out.println("--- Attempting division by zero ---");


// Example 2: An ArithmeticException is thrown and caught.
try {
System.out.println("Entering the try block...");
int result = divideNumbers(10, 0); // This line will throw an
exception.
// This next line will not be reached.
System.out.println("This message will not be printed.");
} catch (ArithmeticException e) {
// The 'catch' block is executed because an exception was thrown.
System.out.println("Exception handled! The 'catch' block was
executed.");
System.out.println("Error message: " + e.getMessage());
} finally {
// The 'finally' block is still executed, even after the exception.
System.out.println("This is the finally block. It always runs.");
}

System.out.println("\nProgram has finished execution gracefully.");


}
}

4. Output
--- Attempting a valid division ---
Entering the try block...
The result of 100 / 5 is: 20
Leaving the try block normally.
This is the finally block. It always runs.

----------------------------------------

--- Attempting division by zero ---


Entering the try block...
Exception handled! The 'catch' block was executed.
Error message: Division by zero is not allowed.
This is the finally block. It always runs.

Program has finished execution gracefully.

b) Write a JAVA program Illustrating Multiple catch clauses

1. Aim
To write a Java program that demonstrates the use of multiple catch clauses to
handle different types of exceptions that may arise from a single try block. The
program will show how to provide specific handling logic for each distinct
exception type.

2. Prerequisites
To effectively use multiple catch clauses, a solid understanding of Java's
exception handling hierarchy and mechanism is necessary. The program builds upon
the basic try-catch structure.

Key concepts to be familiar with are:

Exception Hierarchy: In Java, exceptions are objects that inherit from the
Throwable class. Different runtime errors are represented by different exception
classes (e.g., ArithmeticException, NullPointerException,
ArrayIndexOutOfBoundsException).

try Block: This block encloses the code that is monitored for potential exceptions.

Multiple catch Clauses: A single try block can be followed by several catch blocks.
Each catch block is an exception handler that specifies the type of exception it
can handle.

Execution Flow: When an exception occurs in the try block, the Java runtime system
looks for a matching catch block. It checks the catch blocks in the order they
appear. The first catch block whose parameter type matches the type of the
exception object (or is a superclass of it) is executed. After that one catch block
executes, the others are skipped.
Order of catch Blocks: It is crucial to order the catch blocks from the most
specific exception type to the most general. For instance, a catch for
ArrayIndexOutOfBoundsException must come before a catch for its superclass,
Exception. If the superclass catch comes first, it will handle all related
exceptions, making the more specific subclass catch block unreachable, which
results in a compile-time error.

3. Program
public class Main {
public static void main(String[] args) {

// This program demonstrates two scenarios by changing the code inside the
try block.

// Scenario 1: Triggering an ArithmeticException


System.out.println("--- Scenario 1: Attempting division by zero ---");
try {
int a[] = new int[5]; // Array declaration
System.out.println("Accessing an element: " + a[2]); // This is valid
int result = 100 / 0; // This line will throw an ArithmeticException
System.out.println("Result: " + result); // This line will not be
executed
}
catch (ArithmeticException e) {
// This block specifically catches division-by-zero errors.
System.out.println("Caught an ArithmeticException!");
System.out.println("Error: " + e.getMessage());
}
catch (ArrayIndexOutOfBoundsException e) {
// This block catches errors related to invalid array indices.
System.out.println("Caught an ArrayIndexOutOfBoundsException!");
System.out.println("Error: " + e.getMessage());
}
catch (Exception e) {
// This is a generic catch block for any other exceptions.
System.out.println("Caught a general Exception!");
System.out.println("Error: " + e.getMessage());
}

System.out.println("\n------------------------------------------------\n");

// Scenario 2: Triggering an ArrayIndexOutOfBoundsException


System.out.println("--- Scenario 2: Accessing an invalid array index ---");
try {
int a[] = new int[5];
System.out.println("Accessing an element out of bounds: " + a[10]); //
This throws an exception
}
catch (ArithmeticException e) {
// This block will be skipped in this scenario.
System.out.println("Caught an ArithmeticException!");
System.out.println("Error: " + e.getMessage());
}
catch (ArrayIndexOutOfBoundsException e) {
// This block will execute because the exception type matches.
System.out.println("Caught an ArrayIndexOutOfBoundsException!");
System.out.println("Error: " + e.getMessage());
}
catch (Exception e) {
// This block will be skipped.
System.out.println("Caught a general Exception!");
System.out.println("Error: " + e.getMessage());
}

System.out.println("\nProgram execution continues after handling the


exceptions.");
}
}

4. Output
--- Scenario 1: Attempting division by zero ---
Accessing an element: 0
Caught an ArithmeticException!
Error: / by zero

------------------------------------------------

--- Scenario 2: Accessing an invalid array index ---


Caught an ArrayIndexOutOfBoundsException!
Error: Index 10 out of bounds for length 5

Program execution continues after handling the exceptions.

c) Write a JAVA program for creation of Java Built-in Exceptions

1. Aim
To write a Java program that intentionally triggers and demonstrates the creation
of several common built-in (unchecked) exceptions. The program will show how the
Java Virtual Machine (JVM) automatically throws these exceptions at runtime when
the code violates fundamental language rules, and how they can be handled using
try-catch blocks.

2. Prerequisites
Java provides a robust exception handling framework with a rich set of pre-defined
exception classes, known as built-in exceptions. A clear understanding of these is
essential for writing stable code.

Key concepts to be familiar with are:

Built-in Exceptions: These are exception classes that are part of the standard Java
API, primarily within the java.lang package. They cover the most common programming
errors.

Checked vs. Unchecked Exceptions: Java exceptions are categorized into two main
types.

Checked Exceptions: These are exceptions that a compiler forces the programmer to
handle (e.g., IOException).

Unchecked Exceptions (Runtime Exceptions): These are exceptions that are not
checked at compile time. They usually stem from logical errors in the code, such as
dividing by zero or accessing a null object. The examples in this program are all
unchecked exceptions.

Exception Hierarchy: All exceptions descend from the java.lang.Throwable class. The
Exception class is a subclass of Throwable, and RuntimeException is a subclass of
Exception. Most built-in, unchecked exceptions are subclasses of RuntimeException.
Automatic Creation: Unlike user-defined exceptions, built-in exceptions are
typically created and thrown automatically by the JVM when it detects an illegal
operation. For example, the JVM itself creates an ArithmeticException object when
it encounters an integer division by zero.

3. Program
public class Main {
public static void main(String[] args) {

// 1. Demonstrating ArithmeticException
try {
System.out.println("1. Trying to divide by zero...");
int result = 30 / 0; // This line creates and throws an
ArithmeticException
} catch (ArithmeticException e) {
System.out.println(" CAUGHT: An ArithmeticException occurred!");
System.out.println(" Exception details: " + e);
}

System.out.println("\n----------------------------------------\n");

// 2. Demonstrating NullPointerException
try {
System.out.println("2. Trying to access a method on a null object...");
String str = null;
System.out.println(str.length()); // This creates and throws a
NullPointerException
} catch (NullPointerException e) {
System.out.println(" CAUGHT: A NullPointerException occurred!");
System.out.println(" Exception details: " + e);
}

System.out.println("\n----------------------------------------\n");

// 3. Demonstrating ArrayIndexOutOfBoundsException
try {
System.out.println("3. Trying to access an invalid array index...");
int[] numbers = new int[5];
System.out.println(numbers[10]); // This creates and throws an
ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println(" CAUGHT: An ArrayIndexOutOfBoundsException
occurred!");
System.out.println(" Exception details: " + e);
}

System.out.println("\n----------------------------------------\n");

// 4. Demonstrating NumberFormatException
try {
System.out.println("4. Trying to parse an invalid string to an
integer...");
String invalidNumber = "Java";
int num = Integer.parseInt(invalidNumber); // This creates and throws a
NumberFormatException
} catch (NumberFormatException e) {
System.out.println(" CAUGHT: A NumberFormatException occurred!");
System.out.println(" Exception details: " + e);
}

System.out.println("\nProgram finished handling all exceptions.");


}
}

4. Output
1. Trying to divide by zero...
CAUGHT: An ArithmeticException occurred!
Exception details: java.lang.ArithmeticException: / by zero

----------------------------------------

2. Trying to access a method on a null object...


CAUGHT: A NullPointerException occurred!
Exception details: java.lang.NullPointerException

----------------------------------------

3. Trying to access an invalid array index...


CAUGHT: An ArrayIndexOutOfBoundsException occurred!
Exception details: java.lang.ArrayIndexOutOfBoundsException: Index 10 out of
bounds for length 5

----------------------------------------

4. Trying to parse an invalid string to an integer...


CAUGHT: A NumberFormatException occurred!
Exception details: java.lang.NumberFormatException: For input string: "Java"

Program finished handling all exceptions.

d) Write a JAVA program for creation of User Defined Exception

1. Aim
To write a Java program that defines and uses a custom (user-defined) exception.
The program will create a specific exception class to handle a particular business
logic error—in this case, an invalid age for voting—and then throw and catch this
custom exception.

2. Prerequisites
While Java provides a wide range of built-in exceptions, there are situations where
a custom exception is needed to represent application-specific errors more clearly.
Understanding the following concepts is crucial for creating and using them.

Inheritance: Custom exception classes must extend one of the existing Throwable
subclasses. Typically, you extend java.lang.Exception to create a checked exception
or java.lang.RuntimeException to create an unchecked exception.

The Exception Class: By extending the Exception class, you are creating a custom
checked exception, which the compiler forces you to handle using a try-catch block
or declare with the throws keyword.

Constructors: A custom exception class usually has at least one constructor. A


common practice is to provide a constructor that accepts a String message. This
message is then passed to the superclass constructor using super(message), allowing
it to be retrieved later using the getMessage() method.

The throw Keyword: This keyword is used to manually throw an instance of an


exception object (either built-in or user-defined) when an error condition is met
in your code.

The throws Keyword: This keyword is used in a method's signature to declare that
the method might throw one or more specified exceptions. The calling method is then
responsible for handling them.

3. Program
// 1. Create a custom exception class by extending java.lang.Exception
class InvalidAgeException extends Exception {

// Constructor that accepts a custom error message


public InvalidAgeException(String message) {
// Call the constructor of the parent Exception class
super(message);
}
}

// 2. Main class to demonstrate the use of the custom exception


public class Main {

/**
* This method validates the age. If the age is less than 18,
* it throws our custom InvalidAgeException.
* The 'throws' keyword indicates that this method can throw this exception.
*/
public static void validateAge(int age) throws InvalidAgeException {
if (age < 18) {
// Manually throw our custom exception using the 'throw' keyword
throw new InvalidAgeException("Not eligible to vote: Age must be 18 or
older.");
} else {
System.out.println("Age is valid. Welcome to vote!");
}
}

public static void main(String[] args) {

// Scenario 1: Valid age - No exception is thrown


System.out.println("--- Scenario 1: Checking a valid age (25) ---");
try {
validateAge(25);
} catch (InvalidAgeException e) {
// This block will not be executed in this scenario
System.out.println("Caught an exception: " + e.getMessage());
}

System.out.println("\n------------------------------------------------\n");

// Scenario 2: Invalid age - The custom exception is thrown and caught


System.out.println("--- Scenario 2: Checking an invalid age (16) ---");
try {
// This call will trigger the exception
validateAge(16);
} catch (InvalidAgeException e) {
// The exception is caught here
System.out.println("Custom exception handled successfully!");
System.out.println("Caught exception details: " + e.getMessage());
}

System.out.println("\nProgram execution has completed.");


}
}

4. Output
--- Scenario 1: Checking a valid age (25) ---
Age is valid. Welcome to vote!

------------------------------------------------

--- Scenario 2: Checking an invalid age (16) ---


Custom exception handled successfully!
Caught exception details: Not eligible to vote: Age must be 18 or older.

Program execution has completed.

Exercise - 7

a) Write a JAVA program that creates threads by extending Thread class. First
thread display

"Good Morning "every 1 sec, the second thread displays "Hello "every 2 seconds and
the third

display "Welcome" every 3 seconds, (Repeat the same by implementing Runnable)

1. Aim
To write a Java program that demonstrates the creation and execution of multiple
threads concurrently. The program will be implemented in two ways:

Extending the Thread Class: Creating three threads where the first displays "Good
Morning " every 1 second, the second displays "Hello " every 2 seconds, and the
third displays "Welcome" every 3 seconds.

Implementing the Runnable Interface: Achieving the exact same functionality to


showcase the alternative and more flexible approach to thread creation.

2. Prerequisites
Understanding multithreading is fundamental to developing responsive and efficient
Java applications. It allows for the parallel execution of different parts of a
program.

Key concepts to be familiar with are:

Thread: A thread is the smallest unit of execution within a process. A Java


application runs by default in a single thread (the main thread).

Multithreading: The process of executing multiple threads simultaneously. This


helps in maximizing the utilization of the CPU and is essential for tasks like
animations, background processing, and server-side applications.

Thread Lifecycle: A thread goes through various stages in its life, such as New,
Runnable, Running, Blocked (Waiting), and Terminated. The start() method moves a
thread to the Runnable state.
Creating Threads: Java provides two primary ways to create a thread:

Extending java.lang.Thread: A class can inherit from the Thread class. It must
override the run() method, which contains the logic that the thread will execute.
This approach is simple but less flexible because Java does not support multiple
inheritance.

Implementing java.lang.Runnable: A class can implement the Runnable interface,


which has a single abstract method, run(). An instance of this class is then passed
to the Thread constructor. This is the preferred method as it allows the class to
extend another class while also being runnable.

Key Methods:

run(): Contains the code that constitutes the new thread's task.

start(): Begins the execution of a thread by calling its run() method.

sleep(long millis): Pauses the current thread's execution for the specified number
of milliseconds. It throws a checked InterruptedException, which must be handled.

Part A: Creating Threads by Extending Thread Class


3. Program
// Thread 1: Displays "Good Morning" every 1 second
class GoodMorningThread extends Thread {
@Override
public void run() {
try {
while (true) {
System.out.print("Good Morning ");
Thread.sleep(1000); // Pauses for 1000 milliseconds (1 second)
}
} catch (InterruptedException e) {
System.err.println("GoodMorningThread interrupted.");
}
}
}

// Thread 2: Displays "Hello" every 2 seconds


class HelloThread extends Thread {
@Override
public void run() {
try {
while (true) {
System.out.print("Hello ");
Thread.sleep(2000); // Pauses for 2000 milliseconds (2 seconds)
}
} catch (InterruptedException e) {
System.err.println("HelloThread interrupted.");
}
}
}

// Thread 3: Displays "Welcome" every 3 seconds


class WelcomeThread extends Thread {
@Override
public void run() {
try {
while (true) {
System.out.print("Welcome ");
Thread.sleep(3000); // Pauses for 3000 milliseconds (3 seconds)
}
} catch (InterruptedException e) {
System.err.println("WelcomeThread interrupted.");
}
}
}

public class Main {


public static void main(String[] args) {
System.out.println("--- Starting Part A: Extending Thread Class ---");

// Create instances of the thread classes


GoodMorningThread t1 = new GoodMorningThread();
HelloThread t2 = new HelloThread();
WelcomeThread t3 = new WelcomeThread();

// Start the execution of the threads


t1.start();
t2.start();
t3.start();
}
}

4. Output
(Note: The exact order of output can vary slightly due to the non-deterministic
nature of thread scheduling by the OS. This is a representative example of the
output over approximately 6 seconds.)

--- Starting Part A: Extending Thread Class ---


Good Morning Hello Welcome Good Morning Good Morning Hello Good Morning Good
Morning Good Morning Welcome Hello

Part B: Creating Threads by Implementing Runnable Interface


3. Program
// Runnable 1: Logic for displaying "Good Morning" every 1 second
class GoodMorningRunnable implements Runnable {
@Override
public void run() {
try {
while (true) {
System.out.print("Good Morning ");
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.err.println("GoodMorningRunnable interrupted.");
}
}
}

// Runnable 2: Logic for displaying "Hello" every 2 seconds


class HelloRunnable implements Runnable {
@Override
public void run() {
try {
while (true) {
System.out.print("Hello ");
Thread.sleep(2000);
}
} catch (InterruptedException e) {
System.err.println("HelloRunnable interrupted.");
}
}
}

// Runnable 3: Logic for displaying "Welcome" every 3 seconds


class WelcomeRunnable implements Runnable {
@Override
public void run() {
try {
while (true) {
System.out.print("Welcome ");
Thread.sleep(3000);
}
} catch (InterruptedException e) {
System.err.println("WelcomeRunnable interrupted.");
}
}
}

public class MainRunnable {


public static void main(String[] args) {
System.out.println("--- Starting Part B: Implementing Runnable Interface
---");

// Create instances of the Runnable classes


GoodMorningRunnable r1 = new GoodMorningRunnable();
HelloRunnable r2 = new HelloRunnable();
WelcomeRunnable r3 = new WelcomeRunnable();

// Create Thread objects, passing the Runnable instances to the constructor


Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
Thread t3 = new Thread(r3);

// Start the execution of the threads


t1.start();
t2.start();
t3.start();
}
}

4. Output
(The output for the Runnable implementation will be functionally identical to the
Thread extension method, demonstrating interleaved execution. This is a
representative example.)

--- Starting Part B: Implementing Runnable Interface ---


Good Morning Hello Welcome Good Morning Good Morning Hello Good Morning Good
Morning Good Morning Welcome Hello

b) Write a program illustrating is Alive and join ()


1. Aim
To write a Java program that demonstrates the usage and purpose of the isAlive()
and join() methods from the Thread class. The program will:

Use isAlive() to check the execution status of a thread at various points in its
lifecycle.

Use join() to make the main thread wait for the completion of other threads,
ensuring a specific order of execution.

2. Prerequisites
Coordinating the execution of threads is a critical aspect of concurrent
programming. isAlive() and join() are two fundamental methods for managing thread
interactions.

Key concepts to be familiar with are:

Thread Lifecycle: A thread exists in several states, including New, Runnable,


Running, and Terminated. The isAlive() method's return value is directly tied to
this lifecycle. A thread is "alive" if it is in the Runnable or Running state.

isAlive() Method: This is a final method in the Thread class that tests if a thread
is currently active. It returns true if the thread has been started (its start()
method has been called) and has not yet completed its execution (its run() method
has not finished). It returns false if the thread is in the New state or the
Terminated state.

join() Method: This method causes the current thread (the one calling the method)
to pause its execution until the thread on which join() is invoked completes its
task and terminates. It is essential for scenarios where one thread's work depends
on the result or completion of another.

InterruptedException: The join() method can be interrupted by another thread.


Because of this, it is declared to throw a checked InterruptedException, which must
be handled with a try-catch block.

Thread Scheduling: The order in which threads are executed is determined by the
thread scheduler, which is part of the operating system. Using join() allows a
programmer to impose a specific order on this otherwise non-deterministic process.

3. Program
class WorkerThread extends Thread {
public WorkerThread(String name) {
super(name); // Set the thread's name
}

@Override
public void run() {
System.out.println("-> " + getName() + " has started.");
try {
// Simulate some work by sleeping for 2 seconds
Thread.sleep(2000);
} catch (InterruptedException e) {
System.err.println(getName() + " was interrupted.");
}
System.out.println("<- " + getName() + " has finished.");
}
}

public class Main {


public static void main(String[] args) {
System.out.println("Main thread started.");

// Create two worker threads


WorkerThread t1 = new WorkerThread("Worker-1");
WorkerThread t2 = new Worker-Thread("Worker-2");

// --- Demonstrating isAlive() ---


System.out.println("\n--- Checking isAlive() ---");
System.out.println("Before starting, is " + t1.getName() + " alive? " +
t1.isAlive()); // Should be false

// Start the threads


t1.start();
t2.start();

System.out.println("After starting, is " + t1.getName() + " alive? " +


t1.isAlive()); // Should be true

// --- Demonstrating join() ---


System.out.println("\n--- Using join() to wait for threads to finish ---");
System.out.println("Main thread is now waiting for Worker-1 and Worker-2 to
complete...");

try {
t1.join(); // Main thread pauses here until t1 finishes
System.out.println(t1.getName() + " has joined.");

t2.join(); // Main thread pauses here until t2 finishes


System.out.println(t2.getName() + " has joined.");

} catch (InterruptedException e) {
System.err.println("Main thread was interrupted.");
}

// --- Final check with isAlive() ---


System.out.println("\n--- Final check of isAlive() status ---");
System.out.println("After joining, is " + t1.getName() + " alive? " +
t1.isAlive()); // Should be false
System.out.println("After joining, is " + t2.getName() + " alive? " +
t2.isAlive()); // Should be false

System.out.println("\nMain thread has finished.");


}
}

4. Output
(Note: The start messages of Worker-1 and Worker-2 might appear in a different
order, but the rest of the output will be consistent due to the join() calls.)

Main thread started.

--- Checking isAlive() ---


Before starting, is Worker-1 alive? false
After starting, is Worker-1 alive? true

--- Using join() to wait for threads to finish ---


Main thread is now waiting for Worker-1 and Worker-2 to complete...
-> Worker-1 has started.
-> Worker-2 has started.
<- Worker-1 has finished.
Worker-1 has joined.
<- Worker-2 has finished.
Worker-2 has joined.

--- Final check of isAlive() status ---


After joining, is Worker-1 alive? false
After joining, is Worker-2 alive? false

Main thread has finished.

c) Write a Program illustrating Daemon Threads.

1. Aim
To write a Java program that demonstrates the concept and behavior of a daemon
thread. The program will create a background thread, configure it as a daemon, and
show how its lifecycle is tied to the lifecycle of user threads. The primary goal
is to illustrate that the Java Virtual Machine (JVM) will exit and terminate all
running daemon threads as soon as the last user thread has finished its execution.

2. Prerequisites
Daemon threads are a special kind of thread designed to run in the background,
providing services to user threads. Understanding their unique properties is
essential for correct usage.

Key concepts to be familiar with are:

User Thread vs. Daemon Thread: By default, every thread created in Java is a "user
thread." The JVM will wait for all user threads to complete their execution before
it shuts down. In contrast, a "daemon thread" is a low-priority thread that runs in
the background. The JVM does not wait for daemon threads to finish.

Purpose: Daemon threads are suitable for background tasks that should not prevent
the application from closing, such as garbage collection, monitoring services, or
auto-saving functionality.

setDaemon(boolean on) Method: This Thread class method is used to mark a thread as
a daemon thread. It is crucial to call this method before the thread is started
(i.e., before calling the start() method). Attempting to set it after the thread
has started will result in an IllegalThreadStateException.

isDaemon() Method: This method returns true if the thread is a daemon thread, and
false otherwise.

JVM Shutdown: The key takeaway is that an application terminates when its last user
thread completes. At this point, any remaining daemon threads are abruptly stopped
and abandoned, regardless of what they are doing. Their finally blocks are not
guaranteed to execute, so they should not be used for critical I/O operations.

3. Program
class BackgroundWorker extends Thread {

@Override
public void run() {
// This is an infinite loop to simulate a long-running background task.
// We will check if the thread is a daemon or a user thread.
if (isDaemon()) {
System.out.println("-> Daemon thread has started its background
work.");
} else {
System.out.println("-> User thread has started its work.");
}

try {
while (true) {
System.out.println(" Background task is running...");
Thread.sleep(1000); // Pauses for 1 second
}
} catch (InterruptedException e) {
// This part is unlikely to be reached in this example because the
// thread will be terminated abruptly.
System.err.println("Thread was interrupted.");
} finally {
// IMPORTANT: Finally blocks are NOT guaranteed to run for daemon
threads
// when the JVM exits.
System.out.println(" Daemon thread's finally block.");
}
}
}

public class Main {


public static void main(String[] args) {
System.out.println("Main thread (a user thread) has started.");

// Create an instance of our worker thread


BackgroundWorker daemonThread = new BackgroundWorker();

// --- This is the crucial step ---


// Configure this thread as a daemon thread.
// This MUST be done before calling start().
daemonThread.setDaemon(true);

// Start the thread. It will now run in the background.


daemonThread.start();

try {
// The main thread will do some work and then finish.
// Let's make it sleep for 3 seconds to allow the daemon thread to run
for a bit.
System.out.println("Main thread is sleeping for 3 seconds...");
Thread.sleep(3000);
} catch (InterruptedException e) {
System.err.println("Main thread was interrupted.");
}

// Once the main thread finishes, the JVM will see that only daemon threads
// are left running, so it will exit, terminating the daemon thread.
System.out.println("Main thread is finishing. JVM will now exit.");
}
}

4. Output
(The output demonstrates that the daemon thread is abruptly terminated when the
main thread finishes. Notice the absence of the "finally block" message.)

Main thread (a user thread) has started.


Main thread is sleeping for 3 seconds...
-> Daemon thread has started its background work.
Background task is running...
Background task is running...
Background task is running...
Main thread is finishing. JVM will now exit.

d) Write a JAVA program Producer Consumer Problem

1. Aim
To write a Java program that implements a solution to the classic Producer-Consumer
synchronization problem. The program will use a shared, fixed-size buffer and
utilize synchronized methods along with inter-thread communication mechanisms
(wait() and notify()) to ensure that:

The producer does not add data to the buffer when it is full.

The consumer does not try to remove data from the buffer when it is empty.

Both threads can operate concurrently without causing data corruption or race
conditions.

2. Prerequisites
The Producer-Consumer problem is a cornerstone of concurrent programming, and its
solution requires a solid understanding of thread synchronization and
communication.

Key concepts to be familiar with are:

The Problem Statement: It involves two types of processes, producers and consumers,
who share a common, fixed-size buffer. Producers generate data and put it into the
buffer. Consumers remove data from the buffer and process it. The challenge is to
manage this process so the buffer is accessed safely.

Synchronization: To prevent race conditions where both threads might try to modify
the buffer simultaneously, access to the shared buffer must be synchronized. This
is achieved by placing the logic for adding and removing items into synchronized
methods or blocks, ensuring only one thread can execute them at any given time.

Inter-thread Communication: Simple synchronization is not enough. We need a way for


threads to communicate their state.

wait(): This method, called on an object lock, tells the calling thread to release
the lock and go into a waiting state. A producer will wait() if the buffer is full,
and a consumer will wait() if the buffer is empty.

notify(): This method wakes up a single thread that is waiting on the same object
lock. When a producer adds an item, it calls notify() to wake up a waiting
consumer. When a consumer removes an item, it calls notify() to wake up a waiting
producer.

wait() and notify() Rules: These methods must be called from within a synchronized
context (a block or method synchronized on the same object).

Spurious Wakeups: A waiting thread can sometimes wake up without being explicitly
notified. To guard against this, the condition for waiting (e.g., buffer.isFull())
must always be checked within a while loop, not an if statement.
3. Program
import java.util.LinkedList;
import java.util.Queue;

/**
* This class represents the shared buffer between the Producer and Consumer.
* It has a fixed capacity and synchronized methods for producing and consuming
items.
*/
class SharedBuffer {
private final Queue<Integer> buffer;
private final int capacity;

public SharedBuffer(int capacity) {


this.buffer = new LinkedList<>();
this.capacity = capacity;
}

/**
* Producer calls this method to put an item into the buffer.
* The method is synchronized to ensure thread safety.
* @param item The integer item to be produced.
* @throws InterruptedException if the thread is interrupted while waiting.
*/
public synchronized void produce(int item) throws InterruptedException {
// Use a while loop to check the condition to handle spurious wakeups.
while (buffer.size() == capacity) {
System.out.println("Buffer is full. Producer is waiting...");
wait(); // Release the lock and wait until notified.
}

buffer.add(item);
System.out.println("Produced: " + item + " [Buffer size: " + buffer.size()
+ "]");

// Notify a single waiting consumer thread that an item is available.


notify();
}

/**
* Consumer calls this method to get an item from the buffer.
* The method is synchronized to ensure thread safety.
* @return The integer item consumed.
* @throws InterruptedException if the thread is interrupted while waiting.
*/
public synchronized int consume() throws InterruptedException {
// Use a while loop to check the condition.
while (buffer.isEmpty()) {
System.out.println("Buffer is empty. Consumer is waiting...");
wait(); // Release the lock and wait until notified.
}

int item = buffer.poll();


System.out.println("Consumed: " + item + " [Buffer size: " + buffer.size()
+ "]");

// Notify a single waiting producer thread that space is now available.


notify();
return item;
}
}

/**
* The Producer thread, which produces items and puts them in the shared buffer.
*/
class Producer implements Runnable {
private final SharedBuffer buffer;

public Producer(SharedBuffer buffer) {


this.buffer = buffer;
}

@Override
public void run() {
try {
for (int i = 1; i <= 10; i++) {
buffer.produce(i);
Thread.sleep(100); // Simulate time taken to produce an item
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

/**
* The Consumer thread, which consumes items from the shared buffer.
*/
class Consumer implements Runnable {
private final SharedBuffer buffer;

public Consumer(SharedBuffer buffer) {


this.buffer = buffer;
}

@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
buffer.consume();
Thread.sleep(250); // Simulate time taken to consume an item
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}

public class Main {


public static void main(String[] args) {
System.out.println("--- Producer-Consumer Problem Simulation ---");

SharedBuffer buffer = new SharedBuffer(3); // Buffer with a capacity of 3

Thread producerThread = new Thread(new Producer(buffer));


Thread consumerThread = new Thread(new Consumer(buffer));
producerThread.start();
consumerThread.start();
}
}

4. Output
(Note: The exact timing and interleaving of the output can vary slightly due to
thread scheduling, but the logic will be consistent. This is a representative
example.)

--- Producer-Consumer Problem Simulation ---


Produced: 1 [Buffer size: 1]
Consumed: 1 [Buffer size: 0]
Produced: 2 [Buffer size: 1]
Produced: 3 [Buffer size: 2]
Consumed: 2 [Buffer size: 1]
Produced: 4 [Buffer size: 2]
Produced: 5 [Buffer size: 3]
Buffer is full. Producer is waiting...
Consumed: 3 [Buffer size: 2]
Produced: 6 [Buffer size: 3]
Buffer is full. Producer is waiting...
Consumed: 4 [Buffer size: 2]
Produced: 7 [Buffer size: 3]
Buffer is full. Producer is waiting...
Consumed: 5 [Buffer size: 2]
Produced: 8 [Buffer size: 3]
Buffer is full. Producer is waiting...
Consumed: 6 [Buffer size: 2]
Produced: 9 [Buffer size: 3]
Buffer is full. Producer is waiting...
Consumed: 7 [Buffer size: 2]
Produced: 10 [Buffer size: 3]
Buffer is full. Producer is waiting...
Consumed: 8 [Buffer size: 2]
Consumed: 9 [Buffer size: 1]
Consumed: 10 [Buffer size: 0]

Exercise -8

a) Write a JAVA program that import and use the user defined packages

1. Aim
To write a Java program that demonstrates the creation, compilation, and usage of a
user-defined package. The program will consist of two parts:

A Calculator class placed within a custom package named mypack.tools.

A Main class in the default package that imports and utilizes the Calculator class
to perform operations.

2. Prerequisites
Packages are a fundamental feature in Java for organizing and encapsulating classes
and interfaces. They are essential for creating modular, reusable, and manageable
codebases.

Key concepts to be familiar with are:


What is a Package? A package is a namespace that organizes a set of related classes
and interfaces. It helps in preventing naming conflicts. For example, you can have
a Date class in two different packages.

package Keyword: To place a class inside a package, the package statement must be
the very first line of the source code file.

Directory Structure: This is the most crucial aspect. Java uses the file system to
manage packages. A package named mypack.tools must have its corresponding .java
files inside a directory structure mypack/tools/. The compiler and JVM rely on this
structure to locate the necessary files.

import Keyword: To use a class from another package, you must import it using the
import keyword. You can import a specific class (e.g., import
mypack.tools.Calculator;) or all classes in a package (e.g., import
mypack.tools.*;).

Access Modifiers: For a class or its members (methods, variables) to be accessible


from outside its package, they must be declared as public. Members with protected,
private, or default (package-private) access cannot be accessed from a different
package.

Compilation (javac -d): When compiling classes that belong to a package, the javac
compiler's -d option is used. It specifies the destination directory for the
generated .class files, automatically creating the required package folder
structure.

Classpath: The classpath is the path where the Java Virtual Machine (JVM) and the
Java compiler search for .class files. The current directory (.) is usually on the
classpath by default, which is why the -d . command works.

3. Program
This program requires two separate files and a specific folder structure.

Step 1: Create the Directory Structure

First, create a main project folder (e.g., PackageDemo). Inside it, create the
directory structure for our package mypack/tools. Your final structure will look
like this:

PackageDemo/
├── mypack/
│ └── tools/
│ └── Calculator.java
└── Main.java

Step 2: Create the Calculator.java file inside mypack/tools/

This file defines our Calculator class and places it in the mypack.tools package.

// File: PackageDemo/mypack/tools/Calculator.java

package mypack.tools;

// The class must be public to be accessible from outside the package.


public class Calculator {

// The method must also be public.


public int add(int a, int b) {
return a + b;
}

public int subtract(int a, int b) {


return a - b;
}
}

Step 3: Create the Main.java file inside PackageDemo/

This is our main program that will import and use the Calculator class.

// File: PackageDemo/Main.java

// Import the Calculator class from the user-defined package.


import mypack.tools.Calculator;

public class Main {


public static void main(String[] args) {
System.out.println("Using the Calculator from 'mypack.tools' package.");

// Create an instance of the imported Calculator class.


Calculator calc = new Calculator();

int sum = calc.add(15, 7);


int difference = calc.subtract(15, 7);

System.out.println("Result of addition (15 + 7): " + sum);


System.out.println("Result of subtraction (15 - 7): " + difference);
}
}

Step 4: Compile and Run the Program

Open a terminal or command prompt and navigate to the PackageDemo directory.

Compile the Calculator.java file. The -d . command tells the compiler to create the
.class files in the correct package directory structure within the current folder
(.).

javac -d . mypack/tools/Calculator.java

Compile the Main.java file. The compiler will automatically find the
Calculator.class file because it's in the correct directory structure.

javac Main.java

Run the Main class.

java Main

4. Output
After executing the java Main command, you will see the following output on your
console:

Using the Calculator from 'mypack.tools' package.


Result of addition (15 + 7): 22
Result of subtraction (15 - 7): 8
b) Without writing any code, build a GUI that display text in label and image in an
ImageView

(use JavaFX)
1. Aim
To design a Graphical User Interface (GUI) in JavaFX that displays a text label and
an image. The entire user interface will be defined declaratively using FXML,
demonstrating the separation of the UI's appearance (the "View") from the
application's logic (the "Controller"). This fulfills the requirement of building a
GUI without writing procedural Java code for the layout itself.

2. Prerequisites
To understand this approach, one must be familiar with the JavaFX platform and its
declarative UI definition language, FXML.

Key concepts include:

JavaFX: The modern, official framework for building rich client applications in
Java. It replaces the older Swing toolkit.

FXML: An XML-based markup language created by Oracle that allows developers to


define a user interface's structure and components. It is similar in concept to
HTML for web pages or XAML for .NET applications.

Separation of Concerns (MVC Pattern): FXML allows for a clean separation of the
user interface (View) from the application logic (Controller) and data (Model). The
FXML file exclusively handles the layout and appearance.

Scene Builder: A visual layout tool for JavaFX. Scene Builder allows you to drag
and drop UI components to design an FXML file without writing the XML markup by
hand. It is the ultimate "no code" tool for creating Java GUIs.

Layout Panes: These are containers that manage the arrangement of UI components.
For this example, we will use a VBox, which arranges its children in a single
vertical column.

UI Controls: The visual components the user interacts with. We will use:

Label: A component for displaying non-editable text.

ImageView: A component used to display an Image.

FXMLLoader: While the FXML itself contains no procedural code, a minimal Java
application is required to load the FXML file and display it on the screen. The
FXMLLoader class is responsible for parsing the FXML source file and creating the
live UI object graph from it.

3. Program (The FXML Code)


This is the content of the FXML file, which declaratively defines the GUI. You
would save this file as DisplayUI.fxml. No .java file is needed to define the
layout itself.

<?xml version="1.0" encoding="UTF-8"?>

<!--
Import the necessary JavaFX classes. This is similar to 'import' in Java.
We need VBox for the layout, Label for the text, and ImageView/Image for the
picture.
-->
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.image.Image?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.text.Font?>

<!--
The root element is a VBox. It arranges its children vertically.
'alignment="CENTER"' centers the content horizontally.
'spacing="20"' adds 20 pixels of vertical space between the label and the image.
-->
<VBox xmlns:fx="[http://javafx.com/fxml/1](http://javafx.com/fxml/1)"
alignment="CENTER" spacing="20">

<!-- Add padding of 25 pixels around the entire VBox container -->
<padding>
<Insets top="25" right="25" bottom="25" left="25"/>
</padding>

<!--
This is the Label component.
- 'text' property sets the displayed text.
- 'font' tag sets the font size to 24.
-->
<Label text="A Beautiful Landscape from the Web">
<font>
<Font name="Arial Bold" size="24"/>
</font>
</Label>

<!--
This is the ImageView component that will display the image.
- 'fitWidth' sets the desired width of the view.
- 'preserveRatio="true"' ensures the image is not distorted when resized.
-->
<ImageView fitWidth="500" preserveRatio="true">
<image>
<!--
The Image object is created here. The 'url' attribute points to an
image on the internet. Using a URL avoids needing a local file.
-->
<Image url="[https://placehold.co/600x400/42a5f5/ffffff?
text=Sample+Image](https://placehold.co/600x400/42a5f5/ffffff?
text=Sample+Image)" />
</image>
</ImageView>

</VBox>

4. Output
When the DisplayUI.fxml file is loaded by a JavaFX application, it will produce a
window with the following appearance:

The window will contain a single vertical column of elements, centered


horizontally.
At the top, the text "A Beautiful Landscape from the Web" will be displayed in a
large, bold font.

Below the text, with a 20-pixel gap, a 500-pixel-wide image will be displayed. The
image will be a placeholder graphic with the text "Sample Image" on a blue
background.

The entire content will have a 25-pixel padded border inside the window.

c) Build a Tip Calculator app using several JavaFX components and learn how to
respond to user interactions with the GUI
1aim:
Create a complete graphical user interface (GUI) using the JavaFX framework.

Use several common components like Label, TextField, Slider, and Button.

Demonstrate how to handle user interactions to make the app responsive.

Update the GUI in real-time by calculating the tip and total bill when the user
interacts with the app.
Of course. Here are the prerequisites for building the JavaFX Tip Calculator
application.

2Prerequisites
To understand and build this application, familiarity with several core JavaFX
concepts is required. These concepts form the foundation of creating interactive
and well-structured graphical user interfaces in Java.

Key concepts include:

JavaFX Application Structure: You need to understand that every JavaFX application
extends the Application class and implements the start(Stage primaryStage) method.
This method is the main entry point for the GUI, where the Stage represents the
main window.

Scene Graph: The GUI is structured as a tree of nodes. A Scene object is created to
contain the root node of this tree (in our case, a VBox), which is then set on the
Stage.

Layout Panes: These are containers that organize the UI components. For this app,
you need to know about:

VBox: Arranges its child components in a single vertical column.

GridPane: Arranges its children in a flexible grid of rows and columns, which is
perfect for neatly aligning labels with their corresponding input fields.

UI Controls: You should be familiar with the basic interactive elements of a GUI.
The ones used in this program are:

Label: Displays non-editable text.

TextField: Allows the user to enter a single line of text (for the bill amount).

Slider: Lets the user select a value from a continuous range by dragging a thumb
(for the tip percentage).
Button: A control that triggers an action when clicked.

Event Handling: This is the most critical part for making the application
interactive. You must understand how to respond to user actions:

setOnAction: This is used on the Button to define a piece of code (a lambda


expression in our case) that runs when the button is clicked.

Property Listeners (addListener): This is used on the Slider's valueProperty to


execute code instantly whenever the slider's value changes, allowing for real-time
updates.

Data Conversion & Formatting: A practical application requires handling data. You
should know how to:

Convert a String from a TextField into a numeric type like double (e.g., using
Double.parseDouble()).

Handle potential errors, like the NumberFormatException if the user enters non-
numeric text.

Format numeric output neatly, for instance, using the DecimalFormat class to
display values as currency (e.g., "$24.10").

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.text.DecimalFormat;

public class TipCalculator extends Application {

// --- 1. Aim ---


// The aim of this program is to build a fully functional Tip Calculator
application
// using the JavaFX framework. This application will demonstrate the use of
several
// essential GUI components, including Labels, TextFields, Sliders, and
Buttons.
// A key objective is to learn how to handle user interactions, such as text
input,
// slider adjustments, and button clicks, to dynamically update the UI with
// calculated results in real-time.

// --- 2. Prerequisites ---


// To understand and build this application, familiarity with several core
JavaFX
// concepts is required. These concepts form the foundation of creating
interactive
// and well-structured graphical user interfaces in Java.
//
// Key concepts include:
// * JavaFX Application Structure: Every JavaFX app extends the `Application`
class
// and implements the `start(Stage primaryStage)` method, which is the main
entry
// point for the GUI. The `Stage` is the top-level window.
// * Scene Graph: The GUI is structured as a tree of nodes. The `Scene` object
// contains the root node of this tree.
// * Layout Panes: These are containers that organize the UI components. We
will use:
// - `VBox`: Arranges its children in a single vertical column.
// - `GridPane`: Arranges its children in a flexible grid of rows and
columns,
// which is perfect for aligning labels with input fields.
// * UI Controls: These are the interactive elements of the GUI. We will use:
// - `Label`: Displays non-editable text.
// - `TextField`: Allows the user to enter a single line of text (the bill
amount).
// - `Slider`: Allows the user to select a value from a continuous range by
dragging
// a thumb, which is ideal for selecting a tip percentage.
// - `Button`: A control that triggers an action when clicked.
// * Event Handling: This is the mechanism for responding to user interactions.
// - `setOnAction`: We will use this on the `Button` to define what happens
when it's clicked.
// - `valueProperty().addListener()`: We will use this on the `Slider` to
respond
// instantly to changes in its value, providing real-time feedback.
// * Data Conversion & Formatting: Handling potential `NumberFormatException`
when
// parsing user input and using `DecimalFormat` to display currency values
properly.
//

@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("Tip Calculator");

// --- Component Creation ---


// Labels to describe the input fields and results
Label billAmountLabel = new Label("Bill Amount:");
Label tipPercentageLabel = new Label("Tip Percentage:");
Label tipResultTitleLabel = new Label("Tip Amount:");
Label totalResultTitleLabel = new Label("Total Amount:");
Label tipPercentageValueLabel = new Label("15%"); // Shows the current
slider value
Label tipResultLabel = new Label("$0.00");
Label totalResultLabel = new Label("$0.00");

// Input components
TextField billAmountField = new TextField();
billAmountField.setPromptText("Enter total bill");

Slider tipSlider = new Slider(0, 30, 15); // Min: 0%, Max: 30%, Default:
15%
tipSlider.setShowTickLabels(true);
tipSlider.setShowTickMarks(true);
tipSlider.setMajorTickUnit(5);
Button calculateButton = new Button("Calculate Tip");

// --- Layout Setup ---


// Use a GridPane for neat alignment of labels and inputs
GridPane inputGrid = new GridPane();
inputGrid.setAlignment(Pos.CENTER);
inputGrid.setHgap(10); // Horizontal spacing
inputGrid.setVgap(10); // Vertical spacing

inputGrid.add(billAmountLabel, 0, 0);
inputGrid.add(billAmountField, 1, 0);
inputGrid.add(tipPercentageLabel, 0, 1);
inputGrid.add(tipSlider, 1, 1);
inputGrid.add(tipPercentageValueLabel, 2, 1); // Add the percentage display
next to the slider

// Use a VBox as the main container for all elements


VBox root = new VBox(20); // 20px spacing between elements
root.setPadding(new Insets(25));
root.setAlignment(Pos.CENTER);

// Add all components to the root layout


root.getChildren().addAll(inputGrid, calculateButton, tipResultTitleLabel,
tipResultLabel, totalResultTitleLabel, totalResultLabel);

// --- Event Handling ---

// 1. Respond to Slider changes in real-time


tipSlider.valueProperty().addListener((obs, oldVal, newVal) -> {
// Update the percentage label as the slider moves
tipPercentageValueLabel.setText(String.format("%.0f%%", newVal));
});

// 2. Respond to Button click


calculateButton.setOnAction(event -> {
try {
// Get user input
double billAmount = Double.parseDouble(billAmountField.getText());
double tipPercentage = tipSlider.getValue();

// Perform calculations
double tipAmount = billAmount * (tipPercentage / 100.0);
double totalAmount = billAmount + tipAmount;

// Format the results as currency


DecimalFormat currencyFormat = new DecimalFormat("$#,##0.00");

// Update the result labels


tipResultLabel.setText(currencyFormat.format(tipAmount));
totalResultLabel.setText(currencyFormat.format(totalAmount));

} catch (NumberFormatException e) {
// Handle invalid input (e.g., non-numeric text)
tipResultLabel.setText("Error!");
totalResultLabel.setText("Please enter a valid bill amount.");
}
});
// --- Scene and Stage Setup ---
Scene scene = new Scene(root, 400, 450);
primaryStage.setScene(scene);
primaryStage.show();
}

public static void main(String[] args) {


// --- 3. Program ---
// The main method launches the JavaFX application by calling the start()
method.
// The entire program logic, component creation, layout, and event handling
// are contained within the TipCalculator class, primarily in the start()
method.
launch(args);
}
}

// --- 4. Output ---


// When the program is run, a window titled "Tip Calculator" will appear.
//
// Initial State:
// - It will display a text field prompting "Enter total bill".
// - Below it, a slider will be set to a default value of 15%, with a label "15%"
next to it.
// - A "Calculate Tip" button is centered below the inputs.
// - The "Tip Amount" and "Total Amount" will both show "$0.00".
//
// After User Interaction:
// - The user enters "120.50" into the "Bill Amount" field.
// - The user drags the slider to "20%". The label next to the slider updates in
real-time.
// - The user clicks the "Calculate Tip" button.
// - The "Tip Amount" label will update to display "$24.10".
// - The "Total Amount" label will update to display "$144.60".
//

You might also like