Group B — Descriptive Questions (5 marks)

Q1Explain the four fundamental pillars of Object-Oriented Programming with suitable code snippets.

Q1. Discuss the four fundamental pillars of Object-Oriented Programming (OOP) with real-world examples.

Object-Oriented Programming is a paradigm based on the concept of 'objects', which can contain data (attributes/fields) and code (methods). The four fundamental pillars that define OOP are:

  • Encapsulation: This is the mechanism of wrapping data (variables) and code acting on the data (methods) together as a single unit (a class). In encapsulation, the variables of a class are hidden from other classes and can only be accessed through the methods of their current class. Therefore, it is also known as data hiding.
    Real-World Example: A medicinal capsule. The medicine (data/variables) is safely hidden inside the capsule cover (methods). Or a Bank Account where the balance is private and only updated via deposit() or withdraw() methods.
  • Inheritance: It is a mechanism wherein a new class is derived from an existing class. The new class (subclass) inherits the attributes and methods of the existing class (superclass). This promotes code reusability and establishes an IS-A relationship.
    Real-World Example: A Vehicle class might have properties like wheels and methods like startEngine(). A Car class inherits from Vehicle, automatically gaining those features, but can add its own specific features like airConditioning().
  • Polymorphism: Poly means "many" and morphism means "forms". Polymorphism allows us to perform a single action in different ways. In Java, this occurs via method overloading (compile-time) and method overriding (run-time).
    Real-World Example: A person can have different roles at the same time. A man can be a father, a husband, and an employee. Thus, the same person behaves differently depending on the situation (context). In code, a draw() method will behave differently for a Circle object vs a Square object.
  • Abstraction: It is the property of hiding complex implementation details and showing only the essential features of the object. It helps to reduce programming complexity and effort.
    Real-World Example: Driving a car. You know that pressing the accelerator increases speed and pressing the brake stops it. You don't need to know the complex internal combustion engine mechanics to drive the car. In Java, this is achieved using abstract classes and interfaces.
Q2Compare Procedural Programming and Object-Oriented Programming.

Q2. Compare and contrast Procedural Programming with Object-Oriented Programming (OOP).

Programming paradigms dictate how we approach problem-solving in code. Procedural Oriented Programming (POP) and Object-Oriented Programming (OOP) are the two most prominent paradigms.

FeatureProcedural Programming (POP)Object-Oriented Programming (OOP)
Core ConceptFocuses on functions and procedures. The program is divided into smaller parts called functions.Focuses on data and objects. The program is divided into objects that interact with each other.
ApproachFollows a Top-Down approach in program design.Follows a Bottom-Up approach in program design.
Data SecurityPoor security. Data moves freely around the system from function to function. Most data is global.High security. Data is hidden (encapsulated) and cannot be accessed by external functions without permission.
Real-world modelingDifficult to map to real-world scenarios.Extremely easy to map real-world entities into software objects.
ReusabilityNo direct mechanism for reusing code, though functions help to some extent.Inheritance provides a powerful mechanism to reuse existing code.
ModifiabilityAdding new data or functions is difficult as it might affect the entire program.Highly extensible. Adding new classes or modifying existing ones is easier without breaking the system.
ExamplesC, Pascal, FORTRAN, BASIC.Java, C++, Python, C#.

Conclusion: While POP is suitable for small, simple scripts where execution speed is critical, OOP is indispensable for building large, complex, maintainable, and scalable enterprise applications.

Q3Explain Constructor Chaining in Java using 'this()' and 'super()'.

Q3. What is Constructor Chaining in Java? Explain with a relevant code snippet.

Constructor chaining is the process of calling one constructor from another constructor within the same class (or from a child class to a parent class) during the object creation process. This technique is primarily used to prevent code duplication and to ensure that multiple constructors share common initialization logic.

Types of Constructor Chaining:
  • Within the same class: Achieved using the this() keyword. It must always be the first statement inside the constructor.
  • From a child class to a parent class: Achieved using the super() keyword. It also must be the first statement. If not explicitly written, the Java compiler implicitly inserts a default super() call.
Code Example:
JAVA
class Employee {
    String name;
    int id;
    String department;

    // Constructor 1 (Takes only name)
    public Employee(String name) {
        // Calls Constructor 2
        this(name, 0);
        System.out.println("Inside Constructor 1");
    }

    // Constructor 2 (Takes name and id)
    public Employee(String name, int id) {
        // Calls Constructor 3 (The main initialization constructor)
        this(name, id, "Unassigned");
        System.out.println("Inside Constructor 2");
    }

    // Constructor 3 (Takes all parameters)
    public Employee(String name, int id, String department) {
        // This constructor actually sets the values
        this.name = name;
        this.id = id;
        this.department = department;
        System.out.println("Inside Constructor 3");
    }
}

public class Main {
    public static void main(String[] args) {
        // When we call the single-parameter constructor, it triggers the chain.
        Employee emp = new Employee("Alice");
    }
}

Output of the above code:
Inside Constructor 3
Inside Constructor 2
Inside Constructor 1

As seen in the output, the this() call immediately pauses the execution of the current constructor and jumps to the target constructor, meaning the most parameterized constructor finishes executing first.

Q4Discuss dynamic method dispatch (Run-time Polymorphism) with a code example.

Q4. Explain Dynamic Method Dispatch (Runtime Polymorphism) in Java with an example.

Dynamic Method Dispatch is a mechanism by which a call to an overridden method is resolved at runtime, rather than at compile-time. This is how Java implements runtime polymorphism. When an overridden method is called through a superclass reference, Java determines which version of that method to execute based on the actual type of the object being referred to at the time the call occurs, not the type of the reference variable.

Key Rules:
  • Upcasting is required: A superclass reference variable must point to a subclass object.
  • The method must be overridden in the subclass.
Code Example:
JAVA
class Animal {
    public void sound() {
        System.out.println("Animal makes a generic sound");
    }
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Dog barks: Woof Woof!");
    }
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Cat meows: Meow!");
    }
}

public class RuntimePolymorphismDemo {
    public static void main(String[] args) {
        // Superclass reference points to Animal object
        Animal myAnimal = new Animal();
        myAnimal.sound(); // Output: Animal makes a generic sound

        // Superclass reference points to Dog object (Upcasting)
        Animal myDog = new Dog(); 
        // At runtime, JVM checks the actual object type (Dog) 
        myDog.sound(); // Output: Dog barks: Woof Woof!

        // Superclass reference points to Cat object (Upcasting)
        Animal myCat = new Cat();
        myCat.sound(); // Output: Cat meows: Meow!
    }
}

Advantages: It allows Java to support overriding, which is central to OOP. It enables you to write robust, extensible code because you can write methods that accept a superclass parameter and they will automatically behave correctly for any subclass passed to them.

Q5Differentiate Abstract Class and Interface in Java with appropriate use-cases.

Q5. Differentiate between Abstract Class and Interface in Java.

Both abstract classes and interfaces are used to achieve abstraction in Java, but they have distinct differences in their design and usage.

FeatureAbstract ClassInterface
Keyword & DefinitionDeclared using the abstract keyword. Can have both abstract (no body) and concrete (with body) methods.Declared using the interface keyword. (Before Java 8) Could only have abstract methods. Now can have default and static methods.
VariablesCan have final, non-final, static, and non-static variables.Variables are implicitly public static final (constants).
InheritanceA class can extend only ONE abstract class (Single Inheritance).A class can implement MULTIPLE interfaces (Multiple Inheritance).
ConstructorsCan have a constructor (used during subclass object creation).Cannot have a constructor.
Access ModifiersMethods and variables can have any access modifier (private, protected, etc.).Methods are implicitly public abstract.
Code Example:
JAVA
// Interface
interface Drawable {
    void draw(); // implicitly public and abstract
}

// Abstract Class
abstract class Shape {
    String color;
    // Constructor in abstract class
    public Shape(String color) { this.color = color; }
    // Concrete method
    public void displayColor() { System.out.println("Color: " + color); }
    // Abstract method
    abstract double calculateArea();
}

// Concrete Class implementing Interface AND extending Abstract Class
class Circle extends Shape implements Drawable {
    double radius;
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    @Override
    public void draw() { System.out.println("Drawing a Circle."); }
    @Override
    double calculateArea() { return Math.PI * radius * radius; }
}
Q6Explain access specifiers in Java and their visibility scopes across packages.

Q6. Explain Access Specifiers (Modifiers) in Java with examples.

Access specifiers determine the scope or visibility of classes, variables, methods, and constructors in Java. They are crucial for implementing Encapsulation (data hiding). Java provides four access specifiers:

  • 1. private: The access level is restricted strictly within the class. It cannot be accessed from outside the class, not even by subclasses. It provides the highest level of security.
  • 2. default (no keyword): If you don't explicitly specify an access modifier, it is considered 'default'. The access level is restricted within the same package. It cannot be accessed from outside the package.
  • 3. protected: The access level is within the same package, and outside the package only through child classes (inheritance). If a class outside the package does not extend it, it cannot access protected members.
  • 4. public: The access level is everywhere. It can be accessed from within the class, within the package, outside the package by subclasses, and outside the package by non-subclasses.
Code Summary:
JAVA
package com.example.pack1;

public class Parent {
    private int privateVar = 1;      // Visible ONLY inside Parent
    int defaultVar = 2;              // Visible ONLY inside pack1
    protected int protectedVar = 3;  // Visible inside pack1 AND subclasses everywhere
    public int publicVar = 4;        // Visible everywhere

    public void show() {
        System.out.println(privateVar); // OK
    }
}

// Different package scenario:
package com.example.pack2;
import com.example.pack1.Parent;

class Child extends Parent {
    public void testAccess() {
        // System.out.println(privateVar);  // Error: private
        // System.out.println(defaultVar);  // Error: different package
        System.out.println(protectedVar);   // OK: accessed via inheritance
        System.out.println(publicVar);      // OK: public
    }
}
Q7Discuss static blocks, static variables, and static methods in Java with an example.

Q7. Describe the role of the 'static' keyword in Java.

The static keyword in Java is used primarily for memory management. It indicates that a particular member belongs to the class itself, rather than to instances (objects) of the class. It can be applied to variables, methods, blocks, and nested classes.

  • 1. Static Variables: A static variable is shared among all objects of that class. Memory is allocated only once in the class area at the time of class loading. It is useful for representing common properties (e.g., company name for all employees).
  • 2. Static Methods: A static method belongs to the class and can be invoked without creating an object of the class (using ClassName.methodName()). A crucial rule is that static methods can only directly access other static data and static methods; they cannot access non-static (instance) data directly or use this or super keywords.
  • 3. Static Blocks: Used to initialize static variables. It is executed automatically exactly once when the class is loaded into memory, even before the main() method executes.
Code Example:
JAVA
class Student {
    int rollNo; // Instance variable
    String name; // Instance variable
    static String college = "MIT"; // Static variable shared by all

    // Static Block
    static {
        System.out.println("Static Block Executed");
        // college = "Stanford"; // Can modify static variables here
    }

    public Student(int r, String n) {
        rollNo = r;
        name = n;
    }

    // Static Method
    public static void changeCollege(String newCollege) {
        college = newCollege;
        // name = "John"; // ERROR: Cannot make a static reference to non-static field
    }

    public void display() {
        System.out.println(rollNo + " " + name + " " + college);
    }
}

public class Main {
    public static void main(String[] args) {
        Student.changeCollege("Harvard"); // Calling static method without object
        Student s1 = new Student(101, "Alice");
        Student s2 = new Student(102, "Bob");
        
        s1.display(); // 101 Alice Harvard
        s2.display(); // 102 Bob Harvard
    }
}
Q8Explain the usage and implications of the 'final' keyword when applied to classes, methods, and variables.

Q8. What is the significance of the 'final' keyword in Java?

The final keyword in Java is a non-access modifier used to restrict the user. It can be applied in three different contexts: variables, methods, and classes. Once applied, it signifies that the entity is complete and cannot be altered.

  • 1. Final Variable (Constant): When a variable is declared as final, its value cannot be changed once initialized. It effectively becomes a constant. A blank final variable (uninitialized at declaration) can only be initialized inside a constructor.
  • 2. Final Method (Prevents Overriding): When a method is declared as final, it cannot be overridden by any subclasses. This is useful for locking down the implementation of a critical method to prevent unexpected behavior in child classes.
  • 3. Final Class (Prevents Inheritance): When a class is declared as final, it cannot be extended (inherited) by any other class. For security and immutability reasons, many core Java classes like String, Integer, and Math are declared as final.
Code Example:
JAVA
// 1. Final Class
final class Vehicle {
    public void drive() { System.out.println("Driving a vehicle"); }
}
// class Car extends Vehicle { } // ERROR: Cannot inherit from final Vehicle

class Parent {
    // 2. Final Method
    public final void show() {
        System.out.println("This is a final method");
    }
}

class Child extends Parent {
    // public void show() { } // ERROR: Cannot override final method
    
    public void testVariable() {
        // 3. Final Variable
        final int MAX_AGE = 100;
        // MAX_AGE = 101; // ERROR: Cannot assign a value to final variable
        System.out.println("Max age is: " + MAX_AGE);
    }
}
Q9Explain Exception Handling mechanism in Java with try-catch-finally blocks.

Q9. Describe Exception Handling in Java using try, catch, and finally blocks.

An exception is an unwanted or unexpected event occurring during the execution of a program (at runtime) that disrupts the normal flow of instructions. Java provides a robust mechanism to handle these exceptions so that the program can terminate gracefully or recover.

The Core Keywords:
  • try: The try block encloses the code that might throw an exception. It must be followed by either a catch or a finally block.
  • catch: The catch block is used to handle the exception thrown by the preceding try block. You can have multiple catch blocks to handle different types of exceptions specifically.
  • finally: The finally block contains crucial code that must execute whether an exception occurs or not, and whether it is caught or not. It is primarily used for cleaning up resources (closing files, database connections, network sockets).
Code Example:
JAVA
import java.util.Scanner;

public class ExceptionDemo {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        try {
            System.out.print("Enter a number to divide 100 by: ");
            int divisor = scanner.nextInt();
            
            // Risky code that might throw an ArithmeticException
            int result = 100 / divisor; 
            System.out.println("Result: " + result);
            
        } catch (ArithmeticException e) {
            // Handled if divisor is 0
            System.out.println("Error: Cannot divide by zero!");
            
        } catch (Exception e) {
            // Generic catch-all for any other exception (e.g., InputMismatchException)
            System.out.println("An unexpected error occurred: " + e.getMessage());
            
        } finally {
            // This block ALWAYS executes
            System.out.println("Executing finally block: Closing resources.");
            scanner.close();
        }
        
        System.out.println("Program continues normally after try-catch-finally.");
    }
}
Q10Differentiate Checked Exceptions and Unchecked Exceptions with examples.

Q10. Differentiate between Checked and Unchecked Exceptions in Java.

In Java, the java.lang.Throwable class is the root class of all exceptions and errors. The exception hierarchy is divided into two primary categories: Checked and Unchecked exceptions.

FeatureChecked ExceptionsUnchecked Exceptions
Verification TimeChecked at Compile-time by the compiler.Occur at Runtime. The compiler does not check them.
Handling RequirementMust be explicitly handled using a try-catch block or declared in the method signature using the throws keyword. Otherwise, the code will not compile.No mandatory requirement to handle or declare them, though it is good programming practice to do so if they are predictable.
HierarchyClasses that extend Throwable or Exception (except RuntimeException and its subclasses).Classes that extend RuntimeException (and Error, though errors are typically unrecoverable system failures).
Typical Use CaseRepresents conditions outside the immediate control of the program (e.g., a missing file, a broken network connection). The programmer is forced to plan for these.Represents programming logic errors (e.g., dividing by zero, accessing a null reference, going out of array bounds). These should be fixed by writing better code.
ExamplesIOException, SQLException, ClassNotFoundException, InterruptedException.NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException, IllegalArgumentException.
Q11Write a Java program to create and throw a custom user-defined exception.

Custom Exception:

class MyEx extends Exception { MyEx(String s) { super(s); } } throw new MyEx("Error");
Q12Explain Thread Life Cycle in Java with a state transition diagram.

Thread Life Cycle: New -> Runnable -> Running -> Blocked/Waiting -> Terminated.

Q13Compare extending Thread class vs implementing Runnable interface for multithreading.

Thread vs Runnable: Implementing Runnable is better as Java doesn't support multiple inheritance, so you can extend another class if needed.

Q14Explain Thread Synchronization using synchronized methods and synchronized blocks.

Thread Synchronization: Prevents thread interference using synchronized keyword on methods or blocks.

Q15Explain Inter-Thread communication using wait(), notify(), and notifyAll().

Inter-Thread Communication: Threads communicate via wait(), notify(), and notifyAll() inside synchronized context.

Q16Discuss the concept of Deadlock in Multithreading and how to avoid it.

Deadlock: Two or more threads are blocked forever, waiting for each other. Avoid by acquiring locks in a consistent order.

Q17Explain why String objects are immutable in Java. Compare String, StringBuilder, and StringBuffer.

String Immutability: Strings cannot be changed once created for security, thread-safety, and performance (String Pool).

Q18Explain Autoboxing and Unboxing in Java with code examples.

Autoboxing and Unboxing: Automatic conversion between primitive types and their corresponding wrapper classes.

Q19Compare ArrayList and Vector classes in Java Collections Framework.

ArrayList vs Vector: ArrayList is unsynchronized and fast. Vector is synchronized and slow.

Q20Explain the internal working mechanism of HashMap in Java (hashing, buckets, collision handling).

HashMap Working: Uses hashing. Stores key-value pairs in buckets. Handles collisions using Linked Lists or Trees.

Q21Discuss Java Generics and wildcards (, , ).

Java Generics and Wildcards: Generics provide compile-time type safety. Wildcards (?) allow flexibility in generic types.

Q22Explain Byte Streams vs Character Streams in Java File I/O.

Byte vs Character Streams: Byte streams (InputStream/OutputStream) read/write 1 byte at a time. Character streams (Reader/Writer) read/write 2 bytes (Unicode).

Q23Explain Object Serialization and Deserialization in Java with an example program.

Serialization: Process of converting an object into a byte stream. Deserialization is the reverse.

Q24Discuss Lambda Expressions in Java 8 and how they simplify code syntax.

Lambda Expressions: Anonymous functions in Java 8 that simplify code by treating functionality as a method argument.

Q25Explain Functional Interfaces and the @FunctionalInterface annotation.

Functional Interfaces: Interfaces with exactly one abstract method. Annotated with @FunctionalInterface.

Q26Write a Java program to demonstrate Stream API operations (filter, map, reduce).

Stream API:

list.stream().filter(x -> x>5).map(x -> x*2).collect(Collectors.toList());
Q27Explain the Singleton Design Pattern implementation (Lazy initialization vs Eager initialization).

Singleton Pattern: Ensures only one instance exists. Lazy initializes on first use; Eager initializes at class loading.

Q28Explain the Factory Method Design Pattern with a clean class diagram and code snippet.

Factory Pattern: Creates objects without exposing the instantiation logic to the client.

Q29Explain the SOLID principles of OOD with brief definitions.

SOLID Principles: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion.

Q30Explain UML Relationships: Association, Aggregation, and Composition with real-world examples.

UML Relationships: Association (uses-a), Aggregation (has-a, weak), Composition (part-of, strong).

Q31Draw and explain a UML Use Case Diagram for an Online Shopping System.

Use Case Diagram: Visual representation of system interactions by actors and use cases.

Q32Explain Friend Functions and Friend Classes in C++ with code snippets.

Friend Functions: Functions in C++ that can access private/protected members of a class.

Q33Explain Operator Overloading in C++ with an example.

Operator Overloading: Giving special meaning to an existing operator in C++ for user-defined types.

Q34Explain Deep Copy vs Shallow Copy in C++/Java constructors.

Deep vs Shallow Copy: Shallow copy copies references. Deep copy creates new copies of the referenced objects.

Q35Discuss Virtual Base Classes and Multiple Inheritance ambiguity (Diamond Problem) in C++.

Diamond Problem: Ambiguity in multiple inheritance. Solved in C++ using virtual inheritance.

Q36Write a program to implement a Generic Stack class using Java Generics.

Generic Stack:

class Stack<T> { List<T> items = new ArrayList<>(); }
Q37Explain the concept of Reflection API in Java.

Reflection API: Allows inspection and modification of classes, interfaces, fields, and methods at runtime.

Q38Discuss the Try-with-Resources statement introduced in Java 7.

Try-with-Resources: Automatically closes resources like files or sockets at the end of the statement.

Q39Write a Java program to count word frequencies in a text file using Collections/Maps.

Word Frequency:

Map<String, Integer> map = new HashMap<>(); // Logic to split words and map.put(word, map.getOrDefault(word, 0) + 1);
Q40Explain the concept of Model-View-Controller (MVC) Architecture.

MVC Architecture: Separates application into Model (data), View (UI), and Controller (logic).