Q4) How does Java achieve runtime polymorphism? Explain with an example.
Discuss multiple inheritance in Java. How is it achieved using interfaces?
Ans - Runtime polymorphism is achieved through method overriding, where a subclass
provides its own implementation of a method that is already defined in its parent class. This
allows Java to determine the appropriate method at runtime, not at compile time.
Example of Runtime Polymorphism
// Parent class
class Animal {
void makeSound() {
System.out.println("Animal makes a sound.");
}
}
// Child class overriding the method
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // Upcasting
myAnimal.makeSound(); // Calls overridden method in Dog class
}
}
Multiple Inheritance in Java
Java does not support multiple inheritance with classes due to the diamond problem
(ambiguity when two parent classes define the same method). However, multiple
inheritance is achieved using interfaces, since interfaces do not store state and provide a
structured way to implement multiple behaviors.
Example: Achieving Multiple Inheritance Using Interfaces
// First interface
interface Animal {
void eat();
}
// Second interface
interface Movable {
void move();
}
// Class implementing multiple interfaces
class Dog implements Animal, Movable {
public void eat() {
System.out.println("Dog eats.");
}
public void move() {
System.out.println("Dog runs.");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.eat();
myDog.move();
}
}
Q5) Explain the immutability of the String class in Java. How does StringBuffer help in
modifying strings?
Design an object-oriented solution for a Library Management System. Identify classes,
objects, and relationships.
Ans - Immutability of the String Class in Java
In Java, String objects are immutable, meaning their values cannot be changed after they are
created. Any modification to a String results in the creation of a new object in memory rather
than altering the existing object.
Why is String immutable?
1. Memory Efficiency – Reused from the String pool, reducing redundancy.
2. Security – Prevents accidental modification, crucial in scenarios like passwords or
file paths.
3. Thread Safety – Ensures reliability in concurrent environments.
Example-
public class Main {
public static void main(String[] args) {
String str = "Hello";
str = str.concat(", World!"); // Creates a new object instead of modifying `str`
System.out.println(str); // Prints: Hello, World!
}
}
How StringBuffer Helps in Modifying Strings
Unlike String, StringBuffer is mutable, meaning its contents can be modified without
creating new objects.
Benefits of StringBuffer:
• Efficient for frequent modifications (avoids excessive object creation).
• Thread-safe, making it suitable for concurrent operations.
• Provides methods like append(), insert(), replace(), and delete().
Example-
public class Main {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello");
sb.append(", World!"); // Modifies the same object instead of creating a new one
System.out.println(sb); // Prints: Hello, World!
}
}
Object-Oriented Design for a Library Management System
Identified Classes & Their Roles:
1. Library – Manages books and members.
2. Book – Represents books with attributes like title, author, ISBN, and availability.
3. Member – Stores name, ID, borrowedBooks.
4. Librarian – Handles operations like adding/removing books.
5. Transaction – Manages book borrowing and returning.
Relationships Between Classes:
• Library has-a Book and Member.
• Member has-many Book (borrowed).
• Librarian performs actions on Book and Member.
Java Implementation:
import java.util.ArrayList;
class Book {
String title, author, ISBN;
boolean isAvailable;
public Book(String title, String author, String ISBN) {
this.title = title;
this.author = author;
this.ISBN = ISBN;
this.isAvailable = true;
}
void display() {
System.out.println("Title: " + title + ", Author: " + author + ", ISBN: " + ISBN + ",
Available: " + isAvailable);
}
}
class Member {
String name;
int memberID;
ArrayList<Book> borrowedBooks = new ArrayList<>();
public Member(String name, int memberID) {
this.name = name;
this.memberID = memberID;
}
void borrowBook(Book book) {
if (book.isAvailable) {
borrowedBooks.add(book);
book.isAvailable = false;
System.out.println(name + " borrowed " + book.title);
} else {
System.out.println(book.title + " is not available.");
}
}
void returnBook(Book book) {
borrowedBooks.remove(book);
book.isAvailable = true;
System.out.println(name + " returned " + book.title);
}
}
public class LibrarySystem {
public static void main(String[] args) {
// Creating objects
Book book1 = new Book("Java Programming", "John Doe", "123456");
Member member1 = new Member("Alice", 101);
// Borrowing a book
member1.borrowBook(book1);
book1.display();
// Returning a book
member1.returnBook(book1);
book1.display();
}
}
Q6) How does Java achieve runtime polymorphism? Explain with an example.
What is the significance of the super keyword in Java? Give an example.
Ans - Runtime polymorphism is achieved through method overriding, where a subclass
provides its own implementation of a method that is already defined in its parent class. This
allows Java to determine the appropriate method at runtime, not at compile time.
Example of Runtime Polymorphism
// Parent class
class Animal {
void makeSound() {
System.out.println("Animal makes a sound.");
}
}
// Child class overriding the method
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // Upcasting
myAnimal.makeSound(); // Calls overridden method in Dog class
}
}
Significance of the super Keyword in Java
The super keyword in Java is used to refer to the parent class. It allows a subclass to:
1. Access parent class constructors.
2. Call parent class methods (especially overridden methods).
3. Access parent class variables when they are hidden by subclass variables.
Example: Using super to Call a Parent Class Method
// Parent class
class Animal {
void makeSound() {
System.out.println("Animal makes a sound.");
}
}
// Child class
class Dog extends Animal {
void makeSound() {
System.out.println("Dog barks.");
}
void callParentMethod() {
super.makeSound(); // Calls the overridden method in Animal
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.makeSound(); // Calls Dog's method
myDog.callParentMethod(); // Calls Animal's method using super
}
}
Q1) Explain the difference between an object and a class with an example in Java.
Write a Java program where a class Animal is inherited by a class Dog
Ans - Difference Between an Object and a Class in Java
Class: A class is a blueprint or template that defines attributes (variables) and behaviors
(methods) of objects. It does not occupy memory until an object is created.
Object: An object is an instance of a class that stores actual values and allows access to the
behaviors defined by the class
Example of Class vs Object
// Defining a class
class Car {
String brand;
int speed;
// Constructor
Car(String brand, int speed) {
this.brand = brand;
this.speed = speed;
}
// Method to display car details
void display() {
System.out.println("Brand: " + brand + ", Speed: " + speed + " km/h");
}
}
public class Main {
public static void main(String[] args) {
// Creating an object of Car class
Car myCar = new Car("Toyota", 120);
// Calling a method using the object
myCar.display();
}
}
Key Differences
Feature Class Object
Definition Blueprint or template Instance of a class
Memory No memory allocated until an object Allocates memory when
Allocation is created instantiated
Used to call methods and access
Access Cannot be used directly
attributes
Car myCar = new Car("Toyota",
Example class Car { }
120);
Inheritance in Java
Inheritance allows a child class to acquire properties and behaviors from a parent class,
promoting code reuse.
Example –
// Parent class
class Animal {
void makeSound() {
System.out.println("Animal makes a sound.");
}
}
// Child class inheriting from Animal
class Dog extends Animal {
void bark() {
System.out.println("Dog barks!");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.makeSound(); // Inherited method from Animal
myDog.bark(); // Dog-specific method
}
}
Q2) what is method overriding? Write a program demonstrating it.
Explain dynamic method dispatch with an example.
Ans - Method Overriding in Java
Method overriding allows a subclass to provide a specific implementation of a method that
is already defined in its parent class. The overridden method must have the same signature
(name, parameters, and return type) as the method in the parent class.
Example: Method Overriding
// Parent class
class Animal {
void makeSound() {
System.out.println("Animal makes a sound.");
}
}
// Child class overriding the method
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // Upcasting
myAnimal.makeSound(); // Calls the overridden method in Dog class
}
}
Dynamic Method Dispatch in Java
Dynamic method dispatch, also known as runtime polymorphism, allows Java to
determine the method to invoke at runtime, not compile time. It is achieved using method
overriding and upcasting.
Example: Dynamic Method Dispatch
class Parent {
void show() {
System.out.println("Parent class method.");
}
}
class Child extends Parent {
@Override
void show() {
System.out.println("Child class method.");
}
}
public class Main {
public static void main(String[] args) {
Parent obj = new Child(); // Upcasting
obj.show(); // Calls overridden method in Child class
}
}