Chapter 4
Q1: What is code reusability in Java?
A: Code reusability refers to the practice of using existing code for
new functions or programs instead of writing new code from scratch.
This is achieved through mechanisms like classes, interfaces, and
inheritance in Java.
Q2: How does inheritance contribute to code reusability?
A: Inheritance allows a new class (subclass) to inherit properties and
methods from an existing class (superclass). This enables
developers to reuse existing code and extend functionality without
modifying the original code.
Example 1: Basic Inheritance
// Superclass
class Animal {
void eat() {
System.out.println("This animal eats food.");
}
}
// Subclass
class Dog extends Animal {
void bark() {
System.out.println("The dog barks.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.eat(); // Inherited method
dog.bark(); // Dog's own method
}
}
Example 2: Method Overriding
// Superclass
class Vehicle {
void start() {
System.out.println("Vehicle is starting.");
}
}
// Subclass
class Car extends Vehicle {
@Override
void start() {
System.out.println("Car is starting.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Vehicle myCar = new Car();
myCar.start(); // Calls the overridden method in Car
}
}
Example 3: Multiple Levels of Inheritance
// Superclass
class Shape {
void display() {
System.out.println("This is a shape.");
}
}
// Intermediate subclass
class Circle extends Shape {
void draw() {
System.out.println("Drawing a circle.");
}
}
// Leaf subclass
class ColoredCircle extends Circle {
void fillColor() {
System.out.println("Filling the circle with color.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
ColoredCircle coloredCircle = new ColoredCircle();
coloredCircle.display(); // Inherited from Shape
coloredCircle.draw(); // From Circle
coloredCircle.fillColor(); // From ColoredCircle
}
}
Example 4: Using Constructors in Inheritance
// Superclass
class Person {
String name;
Person(String name) {
this.name = name;
}
}
// Subclass
class Student extends Person {
int studentId;
Student(String name, int studentId) {
super(name); // Call superclass constructor
this.studentId = studentId;
}
void display() {
System.out.println("Name: " + name + ", Student ID: " +
studentId);
}
}
// Usage
public class Main {
public static void main(String[] args) {
Student student = new Student("Alice", 101);
student.display(); // Output: Name: Alice, Student ID: 101
}
}
Example 5: Abstract Classes and Inheritance
// Abstract superclass
abstract class Animal {
abstract void sound(); // Abstract method
}
// Subclass
class Cat extends Animal {
@Override
void sound() {
System.out.println("The cat meows.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Animal myCat = new Cat();
myCat.sound(); // Output: The cat meows.
}
}
Example 6: Interface Implementation with Inheritance
// Interface
interface Playable {
void play();
}
// Superclass
class Game {
void start() {
System.out.println("Game is starting.");
}
}
// Subclass implementing the interface
class Soccer extends Game implements Playable {
@Override
public void play() {
System.out.println("Playing soccer.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Soccer soccer = new Soccer();
soccer.start(); // From Game
soccer.play(); // From Playable
}
}
Q3: What are interfaces, and how do they promote code
reusability?
A: Interfaces define a contract that classes can implement. They
allow different classes to be treated in the same way, promoting
code reusability by enabling polymorphism. This means you can use
the same method names across different classes.
Example 1: Basic Interface Implementation
// Define an interface
interface Animal {
void sound();
}
// Implement the interface in different classes
class Dog implements Animal {
@Override
public void sound() {
System.out.println("Dog barks.");
}
}
class Cat implements Animal {
@Override
public void sound() {
System.out.println("Cat meows.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
Animal myCat = new Cat();
myDog.sound(); // Output: Dog barks.
myCat.sound(); // Output: Cat meows.
}
}
Example 2: Polymorphism with Interfaces
// Define the interface
interface Shape {
double area();
}
// Implement the interface in different classes
class Rectangle implements Shape {
private double width;
private double height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
}
class Circle implements Shape {
private double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
// Usage
public class Main {
public static void main(String[] args) {
Shape[] shapes = { new Rectangle(4, 5), new Circle(3) };
for (Shape shape : shapes) {
System.out.println("Area: " + shape.area());
}
// Output:
// Area: 20.0
// Area: 28.274333882308138
}
}
Example 3: Multiple Interfaces
// Define the first interface
interface Playable {
void play();
}
// Define the second interface
interface Eatable {
void eat();
}
// Implement both interfaces in a single class
class Dog implements Playable, Eatable {
@Override
public void play() {
System.out.println("Dog is playing.");
}
@Override
public void eat() {
System.out.println("Dog is eating.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.play(); // Output: Dog is playing.
dog.eat(); // Output: Dog is eating.
}
}
Example 4: Default Methods in Interfaces
// Define the interface with a default method
interface Vehicle {
void start();
default void honk() {
System.out.println("Vehicle is honking.");
}
}
// Implement the interface in a class
class Car implements Vehicle {
@Override
public void start() {
System.out.println("Car is starting.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.start(); // Output: Car is starting.
car.honk(); // Output: Vehicle is honking.
}
}
Example 5: Interface as a Parameter
// Define the interface
interface Greeting {
void greet(String name);
}
// Implement the interface in different classes
class EnglishGreeting implements Greeting {
@Override
public void greet(String name) {
System.out.println("Hello, " + name + "!");
}
}
class SpanishGreeting implements Greeting {
@Override
public void greet(String name) {
System.out.println("¡Hola, " + name + "!");
}
}
// Method that uses the interface
public class Main {
public static void displayGreeting(Greeting greeting, String name)
{
greeting.greet(name);
}
public static void main(String[] args) {
Greeting english = new EnglishGreeting();
Greeting spanish = new SpanishGreeting();
displayGreeting(english, "Alice"); // Output: Hello, Alice!
displayGreeting(spanish, "Carlos"); // Output: ¡Hola, Carlos!
}
}
Example 6: Marker Interface
// Define a marker interface
interface Serializable {}
// A class implementing the marker interface
class Data implements Serializable {
// Class implementation
}
// Usage of the marker interface
public class Main {
public static void main(String[] args) {
Data data = new Data();
if (data instanceof Serializable) {
System.out.println("Data is serializable.");
} else {
System.out.println("Data is not serializable.");
}
// Output: Data is serializable.
}
}
Q4: Can you explain the concept of composition and how it
supports code reusability?
A: Composition involves building classes using references to other
classes, rather than inheriting from them. This allows for greater
flexibility and reusability, as you can combine different components
to create new functionality without the constraints of a class
hierarchy.
Example 1: Basic Composition
// Class representing an Engine
class Engine {
void start() {
System.out.println("Engine starting...");
}
}
// Class representing a Car that uses composition
class Car {
private Engine engine; // Reference to Engine
Car() {
this.engine = new Engine(); // Composition
}
void startCar() {
engine.start(); // Delegating the start action to the engine
System.out.println("Car is ready to go!");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.startCar();
// Output:
// Engine starting...
// Car is ready to go!
}
}
Example 2: Composition with Multiple Components
// Class representing a Wheel
class Wheel {
void roll() {
System.out.println("Wheel is rolling.");
}
}
// Class representing a Car that uses multiple components
class Car {
private Engine engine; // Engine component
private Wheel[] wheels; // Array of Wheel components
Car() {
this.engine = new Engine();
this.wheels = new Wheel[4]; // A car typically has 4 wheels
for (int i = 0; i < wheels.length; i++) {
wheels[i] = new Wheel();
}
}
void startCar() {
engine.start();
for (Wheel wheel : wheels) {
wheel.roll();
}
System.out.println("Car is ready to go!");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Car car = new Car();
car.startCar();
// Output:
// Engine starting...
// Wheel is rolling.
// Wheel is rolling.
// Wheel is rolling.
// Wheel is rolling.
// Car is ready to go!
}
}
Example 3: Using Interfaces for Composition
// Interface for Flyable
interface Flyable {
void fly();
}
// Class representing a Bird
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("Bird is flying.");
}
}
// Class representing a Plane
class Plane implements Flyable {
@Override
public void fly() {
System.out.println("Plane is flying.");
}
}
// Class that uses composition with Flyable components
class FlyingMachine {
private Flyable flyable; // Composition
FlyingMachine(Flyable flyable) {
this.flyable = flyable;
}
void performFlight() {
flyable.fly(); // Delegating the flight action
}
}
// Usage
public class Main {
public static void main(String[] args) {
FlyingMachine birdMachine = new FlyingMachine(new Bird());
FlyingMachine planeMachine = new FlyingMachine(new
Plane());
birdMachine.performFlight(); // Output: Bird is flying.
planeMachine.performFlight(); // Output: Plane is flying.
}
}
Example 4: Composition with Configuration
// Class representing a configuration
class Configuration {
private String setting;
Configuration(String setting) {
this.setting = setting;
}
String getSetting() {
return setting;
}
}
// Class that uses composition to apply a configuration
class Application {
private Configuration config; // Composition
Application(Configuration config) {
this.config = config;
}
void run() {
System.out.println("Application running with setting: " +
config.getSetting());
}
}
// Usage
public class Main {
public static void main(String[] args) {
Configuration config = new Configuration("High Performance");
Application app = new Application(config);
app.run(); // Output: Application running with setting: High
Performance
}
}
Example 5: Dynamic Composition
// Class representing a Printer
class Printer {
void print(String message) {
System.out.println("Printing: " + message);
}
}
// Class representing a Document that uses composition
class Document {
private Printer printer; // Composition
Document(Printer printer) {
this.printer = printer; // Dependency injection
}
void printDocument(String content) {
printer.print(content); // Delegating print action
}
}
// Usage
public class Main {
public static void main(String[] args) {
Printer printer = new Printer();
Document doc = new Document(printer);
doc.printDocument("Hello, World!"); // Output: Printing: Hello,
World!
}
}
Example 6: Composition Over Inheritance
// Class representing a Sound System
class SoundSystem {
void playMusic() {
System.out.println("Playing music...");
}
}
// Class representing a Home Theater that uses composition
class HomeTheater {
private SoundSystem soundSystem; // Composition
HomeTheater() {
this.soundSystem = new SoundSystem(); // Composition
}
void watchMovie() {
System.out.println("Setting up the home theater...");
soundSystem.playMusic(); // Using the composed object
System.out.println("Enjoy the movie!");
}
}
// Usage
public class Main {
public static void main(String[] args) {
HomeTheater homeTheater = new HomeTheater();
homeTheater.watchMovie();
// Output:
// Setting up the home theater...
// Playing music...
// Enjoy the movie!
}
}
Q5: What is the DRY principle, and how does it relate to code
reusability?
A: The DRY (Don't Repeat Yourself) principle emphasizes reducing
code duplication. By reusing code through methods, classes, or
libraries, developers can adhere to this principle, making their
codebase cleaner and easier to maintain.
Q6: How can libraries and frameworks aid in code
reusability?
A: Libraries and frameworks provide pre-written code for common
tasks, allowing developers to leverage existing solutions rather than
creating new ones. This accelerates development and ensures
consistency across applications.
Q7: What role do design patterns play in code reusability?
A: Design patterns are established solutions to common problems in
software design. By following these patterns, developers can create
reusable code structures that facilitate easier maintenance and
scalability.
Q8: How can generic programming enhance code reusability
in Java?
A: Generic programming allows developers to define classes,
interfaces, and methods with type parameters. This enables the
creation of flexible and reusable code that can work with any data
type, reducing redundancy.
Q9: What is the significance of modular programming in
terms of code reusability?
A: Modular programming involves breaking down a program into
smaller, manageable, and reusable modules. This makes it easier to
test, maintain, and reuse code across different projects.
Q10: Can you provide an example of how to achieve code
reusability with methods in Java?
A: Yes! Here’s a simple example:
java
Copy
public class MathUtils {
// Method to add two numbers
public static int add(int a, int b) {
return a + b;
}
// Method to multiply two numbers
public static int multiply(int a, int b) {
return a * b;
}
}
// Usage in another class
public class Main {
public static void main(String[] args) {
int sum = MathUtils.add(5, 10);
int product = MathUtils.multiply(5, 10);
System.out.println("Sum: " + sum); // Output: Sum: 15
System.out.println("Product: " + product); // Output: Product: 50
}
}
This example demonstrates how to create reusable methods in a
utility class, which can be called from other parts of the program.
Q11: What are static methods, and how do they promote
code reusability?
A: Static methods belong to the class rather than any instance of
the class. They can be called without creating an object, making
them ideal for utility or helper methods that can be reused
throughout the application.
Example 1: Basic Static Method
class MathUtils {
// Static method to add two numbers
static int add(int a, int b) {
return a + b;
}
}
// Usage
public class Main {
public static void main(String[] args) {
int sum = MathUtils.add(5, 10);
System.out.println("Sum: " + sum); // Output: Sum: 15
}
}
Example 2: Static Methods for Utility Functions
class StringUtils {
// Static method to reverse a string
static String reverse(String str) {
return new StringBuilder(str).reverse().toString();
}
}
// Usage
public class Main {
public static void main(String[] args) {
String original = "Hello";
String reversed = StringUtils.reverse(original);
System.out.println("Reversed: " + reversed); // Output:
Reversed: olleH
}
}
Example 3: Static Methods with Parameters
class Converter {
// Static method to convert Celsius to Fahrenheit
static double celsiusToFahrenheit(double celsius) {
return (celsius * 9/5) + 32;
}
}
// Usage
public class Main {
public static void main(String[] args) {
double celsius = 25;
double fahrenheit = Converter.celsiusToFahrenheit(celsius);
System.out.println(celsius + " °C = " + fahrenheit + " °F"); //
Output: 25.0 °C = 77.0 °F
}
}
Example 4: Static Block Initialization
class Config {
static String CONFIG;
// Static block to initialize static variables
static {
CONFIG = "Application Configuration Loaded";
}
// Static method to display configuration
static void displayConfig() {
System.out.println(CONFIG);
}
}
// Usage
public class Main {
public static void main(String[] args) {
Config.displayConfig(); // Output: Application Configuration
Loaded
}
}
Example 5: Static Methods in a Singleton Patter
class Singleton {
private static Singleton instance;
// Private constructor to prevent instantiation
private Singleton() {}
// Static method to provide access to the instance
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
void showMessage() {
System.out.println("Hello from Singleton!");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
singleton.showMessage(); // Output: Hello from Singleton!
}
}
Example 6: Static Methods with Overloading
class Display {
// Static method to display an integer
static void show(int number) {
System.out.println("Integer: " + number);
}
// Overloaded static method to display a string
static void show(String message) {
System.out.println("Message: " + message);
}
}
// Usage
public class Main {
public static void main(String[] args) {
Display.show(100); // Output: Integer: 100
Display.show("Hello!"); // Output: Message: Hello!
}
}
Example 7: Static Methods in a Math Library
class MathLibrary {
// Static method to compute the factorial of a number
static long factorial(int n) {
if (n == 0) return 1;
long result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
}
// Usage
public class Main {
public static void main(String[] args) {
int number = 5;
long fact = MathLibrary.factorial(number);
System.out.println("Factorial of " + number + " is " + fact); //
Output: Factorial of 5 is 120
}
}
Q12: How does the use of packages enhance code reusability
in Java?
A: Packages group related classes and interfaces, making it easier
to organize code. By using packages, developers can import and
reuse classes across different projects, promoting modular design
and reducing redundancy.
Example 1: Creating and Using a Package
MathUtils Class in Package
src/
└── com/
└── example/
└── utils/
└── MathUtils.java
// File: src/com/example/utils/MathUtils.java
package com.example.utils;
public class MathUtils {
public static int add(int a, int b) {
return a + b;
}
public static int subtract(int a, int b) {
return a - b;
}
}
Using the Package in Another Class
Create another class to use the MathUtils class:
// File: src/Main.java
import com.example.utils.MathUtils;
public class Main {
public static void main(String[] args) {
int sum = MathUtils.add(10, 5);
int difference = MathUtils.subtract(10, 5);
System.out.println("Sum: " + sum); // Output: Sum: 15
System.out.println("Difference: " + difference); // Output:
Difference: 5
}
}
Example 2: Creating a Package with Multiple Classes
src/
└── com/
└── example/
└── shapes/
├── Circle.java
└── Rectangle.java
Circle Class
// File: src/com/example/shapes/Circle.java
package com.example.shapes;
public class Circle {
private double radius;
public Circle(double radius) {
this.radius = radius;
public double area() {
return Math.PI * radius * radius;
}
Rectangle Class
// File: src/com/example/shapes/Rectangle.java
package com.example.shapes;
public class Rectangle {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
public double area() {
return width * height;
Using the Package
// File: src/Main.java
import com.example.shapes.Circle;
import com.example.shapes.Rectangle;
public class Main {
public static void main(String[] args) {
Circle circle = new Circle(5);
Rectangle rectangle = new Rectangle(4, 6);
System.out.println("Circle Area: " + circle.area()); // Output:
Circle Area: 78.53981633974483
System.out.println("Rectangle Area: " + rectangle.area()); //
Output: Rectangle Area: 24.0
Example 3: Using import Statements
1. Creating a New Package
src/
└── com/
└── example/
└── animals/
├── Dog.java
└── Cat.java
Dog Class
// File: src/com/example/animals/Dog.java
package com.example.animals;
public class Dog {
public void bark() {
System.out.println("Dog barks!");
Cat Class
// File: src/com/example/animals/Cat.java
package com.example.animals;
public class Cat {
public void meow() {
System.out.println("Cat meows!");
Using Import Statements
// File: src/Main.java
import com.example.animals.Dog;
import com.example.animals.Cat;
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
dog.bark(); // Output: Dog barks!
cat.meow(); // Output: Cat meows!
Example 4: Subpackages
1. Creating a Subpackage
src/
└── com/
└── example/
├── animals/
│ ├── Dog.java
│ └── Cat.java
└── services/
└── AnimalService.java
AnimalService Class
// File: src/com/example/services/AnimalService.java
package com.example.services;
import com.example.animals.Dog;
import com.example.animals.Cat;
public class AnimalService {
public void makeSound() {
Dog dog = new Dog();
Cat cat = new Cat();
dog.bark();
cat.meow();
Using the Subpackage
// File: src/Main.java
import com.example.services.AnimalService;
public class Main {
public static void main(String[] args) {
AnimalService animalService = new AnimalService();
animalService.makeSound();
// Output:
// Dog barks!
// Cat meows!
Example 5: Package Access Modifiers
1. Creating a Class with Default Access Modifier
// File: src/com/example/animals/Cat.java
package com.example.animals;
class Cat { // Default access modifier
public void meow() {
System.out.println("Cat meows!");
Accessing the Class from the Same Package
// File: src/com/example/animals/Dog.java
package com.example.animals;
public class Dog {
public void bark() {
Cat cat = new Cat(); // Accessible because it's in the same
package
cat.meow();
System.out.println("Dog barks!");
Using the Classes
// File: src/Main.java
import com.example.animals.Dog;
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.bark();
// Output:
// Cat meows!
// Dog barks!
}
}
Q13: What is the importance of Java libraries in promoting
code reusability?
A: Java libraries, such as the Java Standard Library, provide pre-
written code for various functionalities (e.g., data structures,
networking). Developers can reuse these libraries to save time and
effort, ensuring reliability and efficiency.
Example 1: Using the Java Collections Framework
The Java Collections Framework provides classes for storing and
manipulating groups of data.
import java.util.ArrayList;
import java.util.Collections;
public class Main {
public static void main(String[] args) {
// Create a list using ArrayList
ArrayList<String> names = new ArrayList<>();
names.add("Alice");
names.add("Bob");
names.add("Charlie");
// Sort the list
Collections.sort(names);
// Print the sorted list
System.out.println("Sorted names: " + names);
// Output: Sorted names: [Alice, Bob, Charlie]
}
}
Example 2: Using the Java Stream API
The Stream API allows for functional-style operations on streams of
elements.
import java.util.Arrays;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// Use Stream API to filter and sum
int sum = numbers.stream()
.filter(n -> n % 2 == 0) // Only even numbers
.mapToInt(Integer::intValue)
.sum();
System.out.println("Sum of even numbers: " + sum); // Output:
Sum of even numbers: 6
}
}
Example 3: Using the java.time Package for Date and Time
The java.time package provides a modern date and time API.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Get the current date
LocalDate today = LocalDate.now();
System.out.println("Today's date: " + today);
// Format the date
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern("dd-MM-yyyy");
String formattedDate = today.format(formatter);
System.out.println("Formatted date: " + formattedDate);
// Output: Today's date: 2024-09-24 (example output)
// Output: Formatted date: 24-09-2024
}
}
Q14: How does the concept of "loose coupling" relate to
code reusability?
A: Loose coupling refers to designing components that are
independent of each other. This allows for easier code reuse, as
changes to one component do not affect others. It simplifies
maintenance and enhances flexibility in code design.
Q15: Can you explain how annotations can be used to
support code reusability?
A: Annotations provide metadata about code elements, allowing
frameworks to process them in reusable ways. For example, Java's
Spring framework uses annotations for dependency injection,
enabling reusable and configurable components.
Q16: What is the role of abstract classes in code reusability?
A: Abstract classes provide a base for other classes, allowing shared
code implementation while enforcing a contract for subclasses. This
promotes code reusability by allowing subclasses to inherit common
behaviors while defining specific implementations.
Example 1: Basic Abstract Class
// Abstract class
abstract class Animal {
// Abstract method (does not have a body)
abstract void sound();
// Concrete method
void sleep() {
System.out.println("Sleeping...");
}
}
// Subclass that extends the abstract class
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks!");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.sound(); // Output: Dog barks!
myDog.sleep(); // Output: Sleeping...
}
}
Example 2: Abstract Class with Constructor
// Abstract class
abstract class Vehicle {
private String brand;
// Constructor
Vehicle(String brand) {
this.brand = brand;
}
// Abstract method
abstract void start();
// Concrete method
String getBrand() {
return brand;
}
}
// Subclass that extends the abstract class
class Car extends Vehicle {
Car(String brand) {
super(brand); // Call the constructor of Vehicle
}
@Override
void start() {
System.out.println(getBrand() + " car is starting.");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Vehicle myCar = new Car("Toyota");
myCar.start(); // Output: Toyota car is starting.
}
}
Example 3: Multiple Subclasses
// Abstract class
abstract class Shape {
abstract double area(); // Abstract method
}
// Subclass for Circle
class Circle extends Shape {
private double radius;
Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
// Subclass for Rectangle
class Rectangle extends Shape {
private double width;
private double height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
// Usage
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
System.out.println("Circle Area: " + circle.area()); // Output:
Circle Area: 78.53981633974483
System.out.println("Rectangle Area: " + rectangle.area()); //
Output: Rectangle Area: 24.0
}
}
Example 4: Abstract Class with Method Implementation
// Abstract class
abstract class Employee {
String name;
Employee(String name) {
this.name = name;
}
// Abstract method
abstract double calculateSalary();
// Concrete method
void display() {
System.out.println("Employee Name: " + name);
}
}
// Subclass for FullTimeEmployee
class FullTimeEmployee extends Employee {
private double monthlySalary;
FullTimeEmployee(String name, double monthlySalary) {
super(name);
this.monthlySalary = monthlySalary;
}
@Override
double calculateSalary() {
return monthlySalary * 12; // Annual salary
}
}
// Subclass for PartTimeEmployee
class PartTimeEmployee extends Employee {
private double hourlyWage;
private int hoursWorked;
PartTimeEmployee(String name, double hourlyWage, int
hoursWorked) {
super(name);
this.hourlyWage = hourlyWage;
this.hoursWorked = hoursWorked;
}
@Override
double calculateSalary() {
return hourlyWage * hoursWorked; // Total earnings
}
}
// Usage
public class Main {
public static void main(String[] args) {
Employee fullTime = new FullTimeEmployee("Alice", 3000);
Employee partTime = new PartTimeEmployee("Bob", 20, 80);
fullTime.display();
System.out.println("Annual Salary: " +
fullTime.calculateSalary()); // Output: Annual Salary: 36000.0
partTime.display();
System.out.println("Total Earnings: " +
partTime.calculateSalary()); // Output: Total Earnings: 1600.0
}
}
Example 5: Abstract Class with Final Method
// Abstract class
abstract class Animal {
abstract void sound(); // Abstract method
// Final method
final void info() {
System.out.println("Animals are living beings.");
}
}
// Subclass
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows!");
}
}
// Usage
public class Main {
public static void main(String[] args) {
Animal myCat = new Cat();
myCat.sound(); // Output: Cat meows!
myCat.info(); // Output: Animals are living beings.
}
}
Q17: How can exception handling contribute to code
reusability?
A: By defining custom exceptions, developers can create reusable
error-handling mechanisms across applications. This encapsulates
error logic and allows consistent handling of specific scenarios,
making code more maintainable.
Q18: What are lambda expressions, and how do they
enhance code reusability?
A: Lambda expressions allow for the creation of anonymous
functions. They enable developers to pass behavior as parameters,
leading to more reusable and concise code, especially in functional
programming paradigms.
Q19: How can unit testing frameworks promote code
reusability?
A: Unit testing frameworks like JUnit allow developers to write
reusable test cases for their code. Once written, these tests can be
run against different versions of the code, ensuring functionality
remains consistent across changes.
Q20: What is the significance of version control in
maintaining reusable code?
A: Version control systems (e.g., Git) help track changes in code
over time. This allows developers to reuse stable versions of code,
collaborate effectively, and maintain a history of changes,
facilitating better management of reusable components.
Q21: How do functional interfaces support code reusability?
A: Functional interfaces (interfaces with a single abstract method)
allow for the use of lambda expressions and method references.
This encourages reusable code patterns, especially in APIs that
require callbacks or event handling.
Q22: Can you provide an example of using interfaces for
code reusability?
A: Here’s an example illustrating the use of interfaces:
Java
// Define a reusable interface
interface Shape {
double area();
}
// Implement the interface in different classes
class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
}
// Usage in another class
public class Main {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
System.out.println("Circle Area: " + circle.area()); //
Output: Circle Area: 78.53981633974483
System.out.println("Rectangle Area: " + rectangle.area()); //
Output: Rectangle Area: 24.0
}
}
This example shows how different shapes can implement a common
interface, promoting code reusability and flexibility in handling
different shape types through a unified method.
What is the output of the following code?
class Parent {
void display() {
System.out.println("Parent");
class Child extends Parent {
void display() {
System.out.println("Child");
public class Main {
public static void main(String[] args) {
Parent obj = new Child();
obj.display();
A) Parent
B) Child
C) Compilation Error
D) Runtime Error
Answer: B) Child
Which of the following is an example of polymorphism in
Java?
A) Method Overloading
B) Method Overriding
C) Both A and B
D) None of the above
Answer: C) Both A and B
Question 6: Composition vs Aggregation
Which of the following best describes composition?
A) A relationship where one class can contain references to another
class.
B) A relationship where one class can exist independently of the
other.
C) A "has-a" relationship that implies ownership.
D) Both A and C.
Answer: D) Both A and C.
Question 7: Method Overloading
What will be the output of the following code?
class Test {
void display(int a) {
System.out.println("Integer: " + a);
void display(double b) {
System.out.println("Double: " + b);
public class Main {
public static void main(String[] args) {
Test test = new Test();
test.display(10); // Line A
test.display(10.5); // Line B
A) Integer: 10
Double: 10.5
B) Compilation Error
C) Integer: 10
Double: 10
D) Integer: 10
Double: 10.0
Answer: A) Integer: 10
Double: 10.5
Question 8: Interface Implementation
What is the output of the following code?
interface Animal {
void sound();
class Dog implements Animal {
public void sound() {
System.out.println("Dog barks!");
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog();
myDog.sound();
A) Dog barks!
B) Compilation Error
C) Runtime Error
D) No output
Answer: A) Dog barks!
Question 9: Abstract Method
What happens if a class extends an abstract class but does
not implement its abstract methods?
A) The class can be instantiated.
B) A compilation error occurs.
C) The class is automatically made abstract.
D) Both B and C.
Answer: D) Both B and C.
Question 10: Aggregation
Which of the following statements about aggregation is
correct?
A) The lifetime of the contained object is managed by the container
object.
B) It represents a "part-of" relationship.
C) The contained object can exist independently of the container
object.
D) Both B and C.
Answer: D) Both B and C.
Question 11: Method Overriding
What is the result of the following code?
class Base {
void show() {
System.out.println("Base class");
}
class Derived extends Base {
void show() {
System.out.println("Derived class");
public class Main {
public static void main(String[] args) {
Base obj = new Derived();
obj.show();
A) Base class
B) Derived class
C) Compilation Error
D) Runtime Error
Answer: B) Derived class
Question 12: Final Keyword
What happens if you declare a class as final in Java?
A) The class can be inherited.
B) The class cannot be inherited.
C) The class cannot have any methods.
D) The class cannot be instantiated.
Answer: B) The class cannot be inherited.
Question 13: Abstract Class vs Interface
Which of the following statements is true regarding abstract
classes and interfaces?
A) An abstract class can implement multiple interfaces, but an
interface cannot extend classes.
B) An interface can have constructors, but an abstract class cannot.
C) An abstract class can have instance variables, but an interface
cannot.
D) Both A and C.
Answer: D) Both A and C.
Question 14: Composition Example
Which of the following best describes the relationship shown
in the code below?
class Engine {
// Engine properties and methods
class Car {
private Engine engine; // Composition relationship
Car(Engine engine) {
this.engine = engine;
A) Aggregation
B) Composition
C) Inheritance
D) Polymorphism
Answer: B) Composition
Question 15: Polymorphism with Interfaces
What will be the output of the following code?
interface Shape {
void draw();
class Circle implements Shape {
public void draw() {
System.out.println("Drawing Circle");
class Square implements Shape {
public void draw() {
System.out.println("Drawing Square");
public class Main {
public static void main(String[] args) {
Shape shape1 = new Circle();
Shape shape2 = new Square();
shape1.draw();
shape2.draw();
A) Drawing Circle
Drawing Square
B) Compilation Error
C) Drawing Circle
Circle
D) Drawing Square
Square
Answer: A) Drawing Circle
Drawing Square
Question 16: Abstract Class Instantiation
Can you instantiate an abstract class in Java?
A) Yes, it can be instantiated.
B) No, it cannot be instantiated.
C) Only if it has concrete methods.
D) Only if it has a constructor.
Answer: B) No, it cannot be instantiated.
Question 17: Inheritance Hierarchy
Given the following class hierarchy, what will be the output
of the code?
class Animal {
void eat() {
System.out.println("Animal eats");
class Dog extends Animal {
void bark() {
System.out.println("Dog barks");
public class Main {
public static void main(String[] args) {
Animal obj = new Dog();
obj.eat();
// obj.bark(); // Uncommenting this line will cause an error
A) Animal eats
B) Dog barks
C) Compilation Error
D) Runtime Error
Answer: A) Animal eats
Question 18: Interface Inheritance
Which of the following is true about an interface inheriting
another interface?
A) An interface cannot extend another interface.
B) An interface can extend multiple interfaces.
C) An interface can have constructors.
D) An interface can implement other interfaces.
Answer: B) An interface can extend multiple interfaces.
Question 19: Method Overloading
What is method overloading?
A) Defining multiple methods with the same name in different
classes.
B) Defining multiple methods with the same name but different
parameters in the same class.
C) Overriding a method in a subclass.
D) Changing the return type of a method.
Answer: B) Defining multiple methods with the same name but
different parameters in the same class.
Question 20: Access Modifiers
Which access modifier allows a class to be accessible only
within its own package?
A) public
B) private
C) protected
D) Default (no modifier)
Answer: D) Default (no modifier)
Question 21: Interface Implementation
If a class implements an interface, what must it do?
A) Provide implementations for all methods declared in the
interface.
B) Only implement some methods from the interface.
C) It can leave the methods unimplemented.
D) It can inherit from another class.
Answer: A) Provide implementations for all methods declared in the
interface.
Question 22: Abstract Class with Final Method
What will happen if you declare a method in an abstract
class as final?
A) The method can be overridden in subclasses.
B) The method cannot be overridden in subclasses.
C) The method cannot be defined in the abstract class.
D) The method must be abstract.
Answer: B) The method cannot be overridden in subclasses.
Question 23: Composition vs Inheritance
Which statement best describes the difference between
composition and inheritance?
A) Composition is a "is-a" relationship; inheritance is a "has-a"
relationship.
B) Inheritance is a "is-a" relationship; composition is a "has-a"
relationship.
C) Both represent the same relationship.
D) Neither supports code reusability.
Answer: B) Inheritance is a "is-a" relationship; composition is a
"has-a" relationship.
Question 24: Polymorphism at Runtime
What is runtime polymorphism in Java?
A) It occurs when a method is overloaded.
B) It is achieved through method overriding.
C) It is determined at compile-time.
D) It cannot be achieved in Java.
Answer: B) It is achieved through method overriding.
Question 25: Abstract Classes and Interfaces
Which of the following statements is false?
A) An abstract class can have both abstract and concrete methods.
B) An interface can have only abstract methods.
C) A class can implement multiple interfaces.
D) An abstract class can implement multiple interfaces.
Answer: B) An interface can have only abstract methods. (As of
Java 8, interfaces can also have default and static methods.)