ST2 OOP Solution
ST2 OOP Solution
Q1.
(a) Discuss the purpose of the @FunctionalInterface annotation?
Ans. The @FunctionalInterface annotation in Java is used to indicate that an interface is intended to
be a functional interface. A functional interface is an interface that has exactly one abstract
method, and thus can be represented by a lambda expression or method reference. A functional
interface can have any number of default methods and static methods in addition to the single
abstract method.
(b) Define sealed classes in java using suitable example.
Ans. Sealed classes in Java are a feature introduced in JDK 17 that allow you to restrict which classes
can extend or implement them.
A sealed class is declared using the sealed keyword, and the subclasses that are permitted to
extend it are listed using the permits clause. Subclasses of a sealed class must be declared as one
of the following:
• final: No further subclassing is allowed.
• sealed: Allows further subclassing, with restrictions.
• non-sealed: No restrictions on further subclassing.
Example:
// Shape.java
public sealed class Shape permits Circle, Rectangle, Square {
public abstract double area();
}
// Circle.java
public final class Circle extends Shape {
private final double radius;
@Override
public double area() {
return Math.PI * radius * radius;
}
}
// Rectangle.java
public non-sealed class Rectangle extends Shape {
private final double length;
private final double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double area() {
return length * width;
}
}
// Square.java
public final class Square extends Rectangle {
public Square(double side) {
super(side, side);
}
}
(c) What are repeating annotations in Java and where can type annotations be used in Java?
Ans. Repeating annotations allow the same annotation to be applied multiple times to a single program
element. This feature was introduced in Java 8. It is particularly useful when you want to apply
the same annotation with different values to a single target.
(d) What is the purpose of the Iterator interface in Java? Name the default method of the Iterator
interface.
Ans. The Iterator interface in Java is a fundamental part of the Java Collections Framework. It
provides a standard way to traverse elements in a collection sequentially without exposing the
underlying structure of the collection. This is useful for processing each element in the collection
one by one, allowing for operations like iteration, removal, and conditional processing.
The Iterator interface in Java has a default method called forEachRemaining. This method is
used to perform the given action for each remaining element in the iteration until all elements
have been processed or the action throws an exception.
(e) What is an ArrayList in Java? How is an ArrayList different from an array?
Ans. ArrayList is a resizable array implementation of the List interface in Java's Collections
Framework. It provides dynamic array capabilities, allowing for flexible and efficient storage
and manipulation of elements.
ArrayList Array
1.Resizable. Automatically grows and shrinks 1.Fixed size. Cannot change size once
as elements are added or removed. initialized.
2.Supports generics, ensuring type safety.
2.Can hold primitives and objects, but does not
3.Offers constant-time complexity for indexed support generics.
access (get and set operations). However, 3.Constant-time access and modification.
insertion and deletion operations can be slower Adding or removing elements is not natively
due to potential resizing and shifting of supported and requires manual handling.
elements.
4.Uses more memory due to its dynamic nature 4.Uses less memory as it does not require
and internal array resizing mechanism. It has an additional space for resizing. The size is fixed
initial capacity that grows as needed. at initialization.
5.Provides many utility methods (add, remove, 5.Limited in functionality. Any additional
contains, etc.), making it easier to work with. operations (like resizing) need to be
implemented manually.
Q2.
(a) Explain the significance of functional interfaces in Java 8. How do they relate to lambda
expressions?
Ans. Functional interfaces are a key feature introduced in Java 8 that enable the use of lambda
expressions and method references. A functional interface is an interface that contains exactly
one abstract method. This single abstract method defines the target type for a lambda expression
or method reference.
Lambda expressions provide a clear and concise way to represent instances of functional
interfaces. They enable treating functionality as a method argument or treating a block of code
as data. This is a major shift from the traditional approach where an anonymous class would be
used to achieve the same goal.
Before Java 8, you might use an anonymous class to pass behavior:
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Running in a thread");
}
};
new Thread(runnable).start();
With Java 8, you can achieve the same using a lambda expression.
Runnable runnable = () -> System.out.println("Running in a thread");
new Thread(runnable).start();
(b) Write a code example using the try-with-resources statement to read from a file.
Ans. The try-with-resources statement in Java is a feature introduced in Java 7 that ensures that
resources are closed automatically after the program is finished with them. This is particularly
useful for managing resources such as file streams, database connections, and network sockets,
which must be closed to avoid resource leaks.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
The Java Collection Framework is a unified architecture for representing and manipulating
collections in Java. It provides a set of interfaces and classes to store and manipulate groups of
objects. The framework is a part of the java.util package and offers a comprehensive set of
interfaces, implementations, and algorithms to handle various types of collections, such as lists,
sets, queues, and maps.
Collection Interface is the root interface of the collection hierarchy. It basic operations like
add(), remove(), size(), clear(), and iterator().
Set Interface is a collection that does not allow duplicate elements. There is no specific order of
elements. The common implementations are HashSet,LinkedHashSet,TreeSet.
Queue Interface is a collection used to hold multiple elements prior to processing. Typically
orders elements in FIFO (First In, First Out). Common implementations are LinkedList,
PriorityQueue.
Deque Interface is a double-ended queue that supports element insertion and removal at both
ends. Common implementations are ArrayDeque,LinkedList
Map Interface ia an object that maps keys to values. No duplicate keys allowed, but values
can be duplicated. Common implementations are HashMap, LinkedHashMap, TreeMap.
ArrayList Implements the List interface using a dynamic array. Provides fast random access
and is resizable.
LinkedList Implements both the List and Deque interfaces using a doubly linked list. Provides
efficient insertions and deletions.
HashSet Implements the Set interface using a hash table. Offers constant time performance for
basic operations.
TreeSet Implements the Set interface using a red-black tree. Maintains elements in sorted
order.
PriorityQueue Implements the Queue interface using a priority heap. Elements are ordered
according to their natural ordering or a comparator.
ArrayDeque Implements the Deque interface using a resizable array. Provides a growable
array-based implementation of the deque interface.
HashMap Implements the Map interface using a hash table. Provides constant time
performance for basic operations.
TreeMap Implements the Map interface using a red-black tree. Maintains keys in sorted order.
(d) Describe about set interface and any five methods of set interface.
Ans. The Set interface in the Java Collection Framework represents a collection that does not allow
duplicate elements. It models the mathematical set abstraction and is part of the java.util
package. The primary characteristic of a Set is that it contains no duplicate elements, ensuring
that each element is unique.
Five Methods of Set Interface
Here are five key methods defined in the Set interface, along with descriptions:
add(E e) : Description: Adds the specified element to the set if it is not already present.
Returns: true if the set did not already contain the specified element.
Example :
Set<String> set = new HashSet<>();
set.add("apple"); // returns true
set.add("apple"); // returns false
remove(Object o) :
Description: Removes the specified element from the set if it is present.
Returns: true if the set contained the specified element.
Example :
Set<String> set = new HashSet<>();
set.add("apple");
set.remove("apple"); // returns true
set.remove("banana"); // returns false
contains(Object o) :
Description: Returns true if the set contains the specified element.
Returns: true if the set contains the specified element.
Example :
Set<String> set = new HashSet<>();
set.add("apple");
set.contains("apple"); // returns true
set.contains("banana"); // returns false
size() :
Description: Returns the number of elements in the set (its cardinality).
Returns: The number of elements in the set.
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
int size = set.size(); // returns 2
iterator():
Description: Returns an iterator over the elements in the set.
Returns: An Iterator over the elements in the set
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
Q3.
(a) Develop a Java application that reads a file, encodes its content to Base64, saves the encoded
content to a new file, and then decodes it back to its original form. Explain the steps and logic
used.
try {
// Step 1: Read the File
Path inputPath = Paths.get(inputFilePath);
byte[] fileContent = Files.readAllBytes(inputPath);
1. Read the File: Read the content of the file into a byte array.
2. Encode to Base64: Encode the byte array to a Base64 string.
3. Save Encoded Content: Write the Base64 string to a new file.
4. Decode from Base64: Read the Base64 string from the encoded file and decode it back
to a byte array.
5. Save Decoded Content: Write the decoded byte array back to a new file, restoring the
original content.
(b) Write a program that demonstrates the use of the Iterator interface to traverse a collection.
Explain the code and its output.
Code Explanation
1. Create a Collection: We will create an ArrayList and add some elements to it.
2. Obtain an Iterator: We will obtain an Iterator for the ArrayList.
3. Traverse the Collection: We will use the Iterator to traverse and print the elements of
the ArrayList.
Q4.
(a) Explain the difference of switch statements and switch expressions in Java. Provide a detailed
example using the yield keyword to return values from a switch expression.
Ans. Switch statements are the traditional way to implement a multi-way branch in Java.
It Uses case labels followed by a colon. Each case ends with a break statement to prevent fall-
through. Break Statement is Essential to prevent execution from falling through to the next
case. Default Case is an optional case that executes if none of the other cases match. The
Scope of variables defined in one case are not accessible in other cases unless they are defined
outside the switch block.
Switch Expressions
Introduced in Java 12 as a preview feature and made standard in Java 14, switch expressions
enhance the switch statement with additional functionality, allowing it to return a value and
support a concise syntax. Switch expressions can return a value, making them more expressive
and reducing boilerplate code. It Uses -> instead of : to separate cases from their actions, which
makes the code cleaner. Each case must produce a value, and there is no need for explicit break
statements since fall-through is not allowed.
When multiple statements are needed for a case, the yield statement can be used to return a value.
Better type checking and control flow analysis, which can make the code more robust.
Example using the yield keyword to return values from a switch expression.
import java.time.Year;
(b) Describe Queue Interface and write a Java program to demonstrate the implementation of a
Queue Interface.
Ans. The Queue interface in Java is a part of the Java Collections Framework, and it represents a
collection designed for holding elements prior to processing. Queue supports operations for
adding, removing, and inspecting elements. It typically follows a First-In-First-Out (FIFO)
order, although other types of queues (such as priority queues) might have different ordering
rules.
1. FIFO Order: Elements are processed in the order they were added.
2. Common Operations:
o add(E e): Inserts the specified element into the queue.
o offer(E e): Inserts the specified element into the queue (similar to add but does
not throw an exception if it fails).
o remove(): Retrieves and removes the head of the queue. Throws an exception if
the queue is empty.
o poll(): Retrieves and removes the head of the queue, or returns null if the queue
is empty.
o element(): Retrieves, but does not remove, the head of the queue. Throws an
exception if the queue is empty.
o peek(): Retrieves, but does not remove, the head of the queue, or returns null if
the queue is empty.
import java.util.LinkedList;
import java.util.Queue;