Java Question Bank with Answers
Answers for Core Java Question Bank
Chapter 2: Objects and Classes.
Moderate Level Questions
8. Describe the concept of "defining user-defined classes" with respect to real-world entities. Provide a Java code snippet for a simple Student class including relevant attributes (e.g., name, rollNo).
Answer:
Defining User-Defined Classes with Real-World Entities:
In Object-Oriented Programming using Java, "defining user-defined
classes" involves creating custom blueprints that model real-world
entities or concepts. This process allows developers to structure their programs
in a way that closely mirrors the problem domain. When modeling real-world
entities (e.g., a student, a car), we identify their characteristics
(properties/attributes) and actions (behaviors/methods). A user-defined class
encapsulates these properties (as instance variables) and behaviors (as
methods) into a single, cohesive unit, promoting modularity and reusability.
Java Code Snippet for a Simple Student Class:
public class Student {
// Attributes (instance variables) of a Student
String name;
int rollNo;
String major;
double cgpa; // Cumulative Grade Point Average
// Constructor to initialize a Student object
public Student(String name, int rollNo, String major, double cgpa) {
this.name = name;
this.rollNo = rollNo;
this.major = major;
this.cgpa = cgpa;
}
// Method to display student’s information (behavior)
public void displayStudentInfo() {
System.out.println("— Student Details —");
System.out.println("Name: " + name);
System.out.println("Roll No: " + rollNo);
System.out.println("Major: " + major);
System.out.println("CGPA: " + cgpa);
System.out.println("———————–");
}
// Example of another behavior: checking eligibility
public boolean isEligibleForScholarship() {
return cgpa >= 3.5;
}
// Main method for demonstration
public static void main(String[] args) {
// Create objects (instances) of the Student class
Student student1 = new Student("Alice Smith", 101, "Computer Science", 3.8);
Student student2 = new Student("Bob Johnson", 102, "Mathematics", 3.2);
// Call methods on the objects
student1.displayStudentInfo();
System.out.println(student1.name + " is eligible for scholarship: " + student1.isEligibleForScholarship());
student2.displayStudentInfo();
System.out.println(student2.name + " is eligible for scholarship: " + student2.isEligibleForScholarship());
}
}
9. Compare and contrast the protected and default (package-private) access specifiers in Java. Provide a scenario where protected would be preferred over default.
Answer:
Comparison Table:
|
Feature |
protected |
default (package-private) |
|
Keyword |
protected |
No keyword (implicit if no other modifier is used) |
|
Same Class |
Yes |
Yes |
|
Same Package, Subclass |
Yes |
Yes |
|
Same Package, Non-Subclass |
Yes |
Yes |
|
Different Package, Subclass |
Yes (through inheritance) |
No |
|
Different Package, Non-Subclass |
No |
No |
|
Purpose |
Provides inheritance-based access. Designed for members that should be accessible to subclasses even if they are in different packages, but hidden from unrelated classes outside the package. |
Provides package-level access. Designed for internal components within a package that don’t need to be exposed to the outside world, or to subclasses outside the package. |
Scenario where protected would be preferred over default:
A protected member is preferred when you intend for certain internal functionalities or data to be accessible by subclasses, even if those subclasses reside in different packages. This is common in framework design where core components are defined in one package, and users extend them in their own application packages.
Example:
Consider a base Renderer class in a com.graphics.core
package, which has a protected method renderPrimitive() that
subclasses should use and potentially customize. User-defined renderers, residing
in a different package (e.g., com.mygame.renderer),
would extend this Renderer class. If renderPrimitive() were default, the
subclass in a different package would not be able to access it. With protected, the
subclass can access and utilize renderPrimitive() for
its rendering logic.
package com.graphics.core;
public class Renderer {
// Protected method: accessible by subclasses in any package
protected void renderPrimitive(Shape shape) { // <– added parameter
System.out.println("Core rendering of a primitive shape.");
// Complex rendering logic
}
// Default access method: accessible only within com.graphics.core package
void internalUtility() {
System.out.println("Internal utility for the graphics core.");
}
}
// Placeholder Shape class
class Shape {}
package com.mygame.renderer;
import com.graphics.core.Renderer;
import com.graphics.core.Shape; // Import Shape if needed
public class CustomGameRenderer extends Renderer {
public void drawGameScene() {
System.out.println("Drawing game scene using custom renderer.");
Shape circle = new Shape();
this.renderPrimitive(circle); // Works because renderPrimitive is protected
// super.internalUtility(); // Won’t compile: internalUtility has default access
}
public static void main(String[] args) {
CustomGameRenderer gameRenderer = new CustomGameRenderer();
gameRenderer.drawGameScene();
}
}
10. Write a Java program to create an Array of Objects for the Student class defined in Question 8. Store details for three students and then display their information.
Answer:
// Program 10: Create an Array of Student Objects and Display Their Information
public class StudentArrayDemo {
public static void main(String[] args) {
// Step 1: Declare and create an array of Student objects (size 3)
Student[] studentList = new Student[3];
// Step 2: Create Student objects and assign them to the array elements
studentList[0] = new Student("Alice Wonderland", 101, "Computer Science", 3.8);
studentList[1] = new Student("Bob The Builder", 102, "Mechanical Engineering", 3.1);
studentList[2] = new Student("Charlie Chaplin", 103, "Film Studies", 3.9);
System.out.println("— Displaying Student Information from Array —");
// Step 3: Using normal for loop
for (int i = 0; i < studentList.length; i++) {
System.out.println("\nStudent " + (i + 1) + ":");
studentList[i].displayStudentInfo();
}
// Step 4: Using enhanced for loop
System.out.println("\n— Displaying Student Information using Enhanced For Loop —");
int count = 1;
for (Student student : studentList) {
System.out.println("\nStudent " + (count++) + ":");
student.displayStudentInfo();
}
}
}
// Reusing Student class from Question 8
class Student {
String name;
int rollNo;
String major;
double cgpa;
// Constructor
public Student(String name, int rollNo, String major, double cgpa) {
this.name = name;
this.rollNo = rollNo;
this.major = major;
this.cgpa = cgpa;
}
// Method to display student information
public void displayStudentInfo() {
System.out.println("Name: " + name);
System.out.println("Roll No: " + rollNo);
System.out.println("Major: " + major);
System.out.println("CGPA: " + cgpa);
}
}
11. Explain "Constructor Overloading" with a suitable Java example. Demonstrate how different constructors can be used to initialize an object in various ways.
Answer:
Constructor Overloading:
Constructor overloading is a feature in Java that allows a class to have
multiple constructors, provided that each constructor has a unique parameter
list (i.e., different number of parameters, different types of parameters, or
different order of parameters). The compiler differentiates between overloaded
constructors based on their signatures. This mechanism provides flexibility in
object creation, enabling objects to be initialized with varying sets of
initial data, making the class more versatile.
Java Example:
Consider a Book class where you might want to create a book
object with just a title and author, or with a title, author, and an ISBN, or
even with a full set of details.
// Java Example: Demonstration of Constructor Overloading and Constructor Chaining
public class Book {
String title;
String author;
String isbn;
double price;
// 1. Default Constructor
public Book() {
this.title = "Untitled";
this.author = "Unknown";
this.isbn = "N/A";
this.price = 0.0;
System.out.println("Book created with default values.");
}
// 2. Constructor with Title and Author
public Book(String title, String author) {
this(); // Calls the default constructor first
this.title = title;
this.author = author;
System.out.println("Book created with title and author.");
}
// 3. Constructor with Title, Author, and ISBN
public Book(String title, String author, String isbn) {
this(title, author); // Calls the (title, author) constructor
this.isbn = isbn;
System.out.println("Book created with title, author, and ISBN.");
}
// 4. Constructor with all details
public Book(String title, String author, String isbn, double price) {
this(title, author, isbn); // Calls the (title, author, isbn) constructor
this.price = price;
System.out.println("Book created with all details.");
}
// Method to display book details
public void displayBookDetails() {
System.out.println("————————-");
System.out.println("Title : " + title);
System.out.println("Author: " + author);
System.out.println("ISBN : " + isbn);
System.out.println("Price : $" + String.format("%.2f", price));
System.out.println("————————-");
}
// Main method to demonstrate different constructors
public static void main(String[] args) {
// 1. Default constructor
Book book1 = new Book();
book1.displayBookDetails();
// 2. Constructor with title and author
Book book2 = new Book("The Java Programming Language", "James Gosling");
book2.displayBookDetails();
// 3. Constructor with title, author, and ISBN
Book book3 = new Book("Effective Java", "Joshua Bloch", "978-0134685991");
book3.displayBookDetails();
// 4. Constructor with all details
Book book4 = new Book("Clean Code", "Robert C. Martin", "978-0132350884", 45.99);
book4.displayBookDetails();
}
}
This example shows how Book objects can be created and initialized using four different constructors, each catering to a different level of detail required at the time of object creation. The this() call within constructors demonstrates constructor chaining, where one constructor calls another constructor of the same class.
12. Discuss two distinct uses of the this keyword in Java with illustrative code examples for each.
Answer:
The this
keyword in Java is a reference to the current object. It is implicitly passed
to every non-static method and constructor.
1. To Differentiate Between Instance Variables and Local Variables/Parameters:
- Purpose: When a method parameter or a local variable has the same name as an instance variable, it creates a name conflict. The this keyword is used to explicitly refer to the instance variable of the current object, distinguishing it from the local variable.
public class Product {
String name; // Instance variable
double price; // Instance variable
// Constructor with parameters
public Product(String name, double price) {
// ‘name’ and ‘price’ on the right are parameters.
// ‘this.name’ and ‘this.price’ refer to the instance variables.
this.name = name;
this.price = price;
}
// Method to display product details
public void display() {
System.out.println("Product: " + this.name + ", Price: $" + this.price);
}
// Main method to test the Product class
public static void main(String[] args) {
Product p1 = new Product("Laptop", 85000.50);
Product p2 = new Product("Smartphone", 29999.99);
p1.display();
p2.display();
}
}
In the constructor, this.name = name; assigns the value of the name parameter to the name instance variable of the Product object being created.
2. To Invoke the Current Class’s Constructor:
- Purpose: The this() (with parentheses) keyword is used to call another constructor of the same class from within a constructor (Knüppel et al., 2018). This is known as constructor chaining and is useful for reducing code duplication when multiple constructors perform common initialization tasks (Knüppel et al., 2018). this() must be the first statement in the constructor.
- Example:
public class Employee {
int id;
String name;
double salary;
// Constructor 1: Initializes ID and Name, calls Constructor 2
public Employee(int id, String name) {
this(id, name, 0.0); // Calls the 3-parameter constructor
System.out.println("Employee created with ID and Name.");
}
// Constructor 2: Initializes ID, Name, and Salary
public Employee(int id, String name, double salary) {
this.id = id;
this.name = name;
this.salary = salary;
System.out.println("Employee created with ID, Name, and Salary.");
}
// Constructor 3: Default Constructor (initializes with default values)
public Employee() {
this(0, "Guest", 0.0); // Calls the 3-parameter constructor
System.out.println("Default Employee created.");
}
public static void main(String[] args) {
Employee emp1 = new Employee(); // Calls default constructor
System.out.println("emp1 Name: " + emp1.name);
Employee emp2 = new Employee(101, "Alice"); // Calls (101, "Alice")
System.out.println("emp2 Salary: " + emp2.salary);
}
}
In this example, the two-parameter constructor Employee(int id, String name) uses this(id, name, 0.0) to call the three-parameter constructor, ensuring that the salary is also initialized (to a default value) without duplicating the id and name initialization logic.
13. Explain the concept of a "Static Block" in Java. When is a static block executed, and what is its typical use? Provide a code example.
Answer:
Static Block:
A static block in Java is a block of code within a class that is prefixed with
the static
keyword. It is used to initialize static data
members (variables) of a class or to perform any one-time setup that needs to
happen when the class is first loaded . A class can have multiple static
blocks, and they will be executed in the order they appear in the class.
When is a static block
executed?
A static block is executed exactly once when the class is loaded into
memory by the Java ClassLoader . This happens at the very first time the class
is accessed in any way, such as:
- When an object of the class is created (new ClassName()).
- When any static member (method or variable) of the class is accessed .
- When Class.forName("ClassName") is called.
Typical Use:
- Complex Static Variable Initialization: For initializing static variables that require more complex logic than a simple one-line assignment .
- Loading Native Libraries: If a class relies on native (non-Java) code, the static block is a suitable place to load these libraries (System.loadLibrary()).
- Registering Drivers: Database drivers often use static blocks to register themselves with the DriverManager.
- One-Time Resource Setup: Any other setup that is expensive or only needs to be done once for the entire class, rather than for each object.
Code Example:
import java.util.ArrayList;
import java.util.List;
public class StaticBlockExample {
// Static variables
public static String COMPANY_NAME = "MyTech Solutions";
public static int MAX_USERS;
public static final List<String> FEATURES = new ArrayList<>(); // Static list
// 🔹 Static Block 1
static {
System.out.println("Static Block 1 executed.");
// Initialize static variable MAX_USERS
MAX_USERS = 1000;
System.out.println("MAX_USERS initialized to: " + MAX_USERS);
}
// 🔹 Static Block 2 (demonstrating multiple static blocks)
static {
System.out.println("Static Block 2 executed.");
// Initialize static list
FEATURES.add("Login");
FEATURES.add("Dashboard");
FEATURES.add("Reports");
System.out.println("Features list initialized.");
}
// 🔹 Constructor — runs when an object is created
public StaticBlockExample() {
System.out.println("Constructor executed.");
}
// 🔹 Static Method — can access only static members
public static void displayStaticInfo() {
System.out.println("\n— Static Information —");
System.out.println("Company: " + COMPANY_NAME);
System.out.println("Max Allowed Users: " + MAX_USERS);
System.out.println("Available Features: " + FEATURES);
System.out.println("————————–");
}
// 🔹 Main Method — entry point
public static void main(String[] args) {
System.out.println("Main method started.");
// Static blocks execute before this line (class loading time)
StaticBlockExample.displayStaticInfo();
// Creating an object (constructor will run, static blocks won’t)
StaticBlockExample obj = new StaticBlockExample();
StaticBlockExample.displayStaticInfo(); // Static blocks won’t run again
System.out.println("Main method finished.");
}
}
As seen in the output, the static blocks execute first, even before the main method (which is itself a static method) is fully processed. They execute only once.
14. What are Inner Classes in Java? Briefly describe two common types of inner classes (e.g., Member Inner Class, Anonymous Inner Class) and when you might use them.
Answer:
Inner Classes:
An inner class (or nested class) in Java is a class defined within another
class . The enclosing class is called the outer class. Inner classes allow you
to logically group classes that are only used in one place, increase
encapsulation, and create more readable and maintainable code. They have full
access to all the members (including private) of the outer class.
Two Common Types of Inner Classes:
1. Member Inner Class:
o Description: A member inner class is a non-static class defined inside another class, outside of any method . It behaves like an instance member of the outer class, meaning it must be instantiated with respect to an instance of the outer class. It can access all members of the outer class, both static and non-static.
o When to Use:
§ When the inner class needs to directly access the instance members of the outer class.
§ When the inner class is conceptually a component of the outer class and has a strong "is-part-of" relationship.
§ Example: A Car class might have an Engine as a member inner class, as an engine is an integral part of a car.
o Example Structure:
// Demonstration of Member Inner Class
public class OuterClass {
// Private instance variable of the outer class
private int outerData = 10;
// Member Inner Class (non-static)
class MemberInnerClass {
public void display() {
// Can access even private members of the outer class
System.out.println("Outer data: " + outerData);
System.out.println("This is a Member Inner Class accessing outer class data.");
}
}
// Main method to demonstrate usage
public static void main(String[] args) {
// Step 1: Create an object of the outer class
OuterClass outer = new OuterClass();
// Step 2: Create an object of the inner class using the outer class instance
OuterClass.MemberInnerClass inner = outer.new MemberInnerClass();
// Step 3: Call inner class method
inner.display();
}
}
Anonymous Inner Class:
o Description: An anonymous inner class is an inner class without a name . It is defined and instantiated in a single expression, often used for implementing an interface or extending a class . They are typically used when you need to create a class that will be used only once .
o When to Use:
§ To provide a concrete implementation of an interface or an abstract class on the fly.
§ When the class is very small and used only at the point of its definition (e.g., event listeners in GUI programming, custom comparators).
§ To avoid creating a separate .java file for a small, single-use class.
o Example Structure (implementing an interface):
// Example of Anonymous Inner Class
interface Greeting {
void sayHello();
}
class MyClass {
public void greet() {
// Anonymous Inner Class implementing the Greeting interface
Greeting englishGreeting = new Greeting() {
@Override
public void sayHello() {
System.out.println("Hello!");
}
};
// Calling the implemented method
englishGreeting.sayHello();
}
public static void main(String[] args) {
// Creating an object and invoking greet()
new MyClass().greet();
}
}
15. Describe the process of "Creating, Accessing, and Using Packages" in Java. Explain the role of the package keyword and the import statement. Provide an example of how you would structure a simple project with two packages.
Answer:
Creating, Accessing, and Using Packages in Java:
Packages in Java are a mechanism to organize classes, interfaces, and
sub-packages into logical units, providing a way to prevent naming conflicts
and to control access to elements . They are essentially directories in the
file system.
Process:
1. Creation:
o To create a package, you declare it at the top of a Java source file using the package keyword, followed by the package name.
o The package name usually follows a reverse domain name convention (e.g., com.example.myapp).
o The .java file containing the class must reside in a directory structure that matches the package name (e.g., com/example/myapp/MyClass.java).
2. Accessing/Using:
o Classes within the same package can access each other directly using their names.
o To use a class from a different package, you generally need to use an import statement.
Role of Keywords:
- package keyword:
- Role: The package statement must be the very first non-comment statement in a Java source file . It declares the package to which the classes, interfaces, and enums defined in that file belong.
- Significance: It defines the namespace for the types declared within the file, preventing naming clashes between classes with the same name from different packages . It also influences access control (e.g., default and protected access levels) (Garmendía et al., 2019).
- import statement:
- Role: The import statement is used to bring classes or entire packages into the current file’s scope, making them directly accessible by their simple names without having to specify their fully qualified names (package name + class name) every time.
- Significance: It simplifies code readability and reduces verbosity by avoiding long fully qualified names. You can import specific classes (import java.util.ArrayList;) or all classes in a package (import java.util.*;).
Example of Project Structure with Two Packages:
Let’s imagine a simple project for a "Library Management System" with two packages: com.library.model for data structures and com.library.app for the application logic.
Project Directory Structure:
LibraryProject/
├── src/
│ ├── com/
│ │ ├── library/
│ │ │ ├── model/
│ │ │ │ └── Book.java
│ │ │ └── app/
│ │ │ └── LibraryApp.java
├── bin/ (where compiled .class files go)
Book.java (in com.library.model package):
// File: src/com/library/model/Book.java
package com.library.model; // Declares this class belongs to ‘com.library.model’
public class Book {
// Instance variables
private String title;
private String author;
private String isbn;
// Constructor — note the parentheses and parameters
public Book(String title, String author, String isbn) {
this.title = title;
this.author = author;
this.isbn = isbn;
}
// Getter methods
public String getTitle() { return title; }
public String getAuthor() { return author; }
public String getIsbn() { return isbn; }
// Overriding toString() for readable output
@Override
public String toString() {
return "Book [Title=" + title + ", Author=" + author + ", ISBN=" + isbn + "]";
}
}
LibraryApp.java (in com.library.app package):
// File: src/com/library/app/LibraryApp.java
package com.library.app; // Declares this class belongs to ‘com.library.app’
import com.library.model.Book; // Imports the Book class from ‘com.library.model’
public class LibraryApp {
public static void main(String[] args) {
// Create Book objects using the Book class from ‘com.library.model’
Book book1 = new Book("The Great Gatsby", "F. Scott Fitzgerald", "978-0743273565");
Book book2 = new Book("1984", "George Orwell", "978-0451524935");
Book book3 = new Book("To Kill a Mockingbird", "Harper Lee", "978-0061120084");
// Display details of each book
System.out.println("— Library Collection —");
System.out.println(book1);
System.out.println(book2);
System.out.println(book3);
System.out.println("————————–");
}
}
To compile these, you would typically use javac -d bin src/com/library/model/Book.java src/com/library/app/LibraryApp.java and then run java -cp bin com.library.app.LibraryApp.
16. Explain why Wrapper Classes are necessary in Java, especially when working with collections.
Answer:
Wrapper classes are essential in Java primarily because of the fundamental
distinction between primitive data types and objects, particularly when
interacting with the Java Collections Framework and other object-oriented.
Core Reason: Collections
Framework Requires Objects:
The Java Collections Framework (e.g., ArrayList, HashMap, HashSet, LinkedList, Vector) is
designed to work exclusively with objects . It provides classes and
interfaces for storing and manipulating groups of objects. Primitive data types
(like int, double, boolean, char) are
not objects.
- Cannot store primitives directly: You cannot directly store a primitive int into an ArrayList<int>. Attempting to declare ArrayList<int> will result in a compile-time error. Instead, you must use ArrayList<Integer> .
Other Reasons for Necessity:
1. Generics: Java Generics work only with objects . To define collections or methods that handle different types of data while maintaining type safety, wrapper classes are indispensable (e.g., List<Integer>, Map<String, Double>) .
2. null Values: Primitive types cannot hold a null value. Wrapper classes, being objects, can hold null, which can be useful in certain programming scenarios to indicate the absence of a value.
3. Utility Methods: Wrapper classes provide useful utility methods for converting primitive values to and from strings, performing various numerical operations, or comparing values (e.g., Integer.parseInt(), Double.valueOf()).
4. Serialization: If you need to serialize (save to a file or send over a network) a primitive value, it must first be wrapped in its corresponding wrapper class, as only objects can be serialized.
5. Synchronization: In multi-threaded environments, if you need to synchronize access to a primitive value (e.g., using synchronized blocks or wait()/notify()), it must be encapsulated within an object, usually a wrapper class instance.
Autoboxing and Unboxing:
To make working with wrapper classes more convenient, Java introduced autoboxing
and unboxing since Java 5 .
- Autoboxing: Automatic conversion of a primitive type to its corresponding wrapper class object (e.g., int i = 5; Integer obj = i;) .
- Unboxing:
Automatic conversion of a wrapper class object to its corresponding
primitive type (e.g., Integer obj = 10; int i = obj;)
.
While these features reduce the need for explicit conversions, they do not negate the underlying necessity of wrapper classes themselves when objects are required.
In essence, wrapper classes bridge the gap between Java’s primitive type system and its object-oriented nature, enabling primitives to participate fully in object-oriented constructs like collections, generics, and object-based APIs.