Java Interview Questions (Free Preview)
Free sample of 15 from 150 questions available
Java Basics
What are the main differences between the JDK, JRE, and JVM?
The three components form a hierarchy where each serves a specific purpose in Java development and execution:
| Component | Full Name | Purpose | Contains |
|---|---|---|---|
| JDK | Java Development Kit | Development environment | JRE + development tools (javac, debugger) |
| JRE | Java Runtime Environment | Execution environment | JVM + runtime libraries |
| JVM | Java Virtual Machine | Execution engine | Bytecode interpreter/compiler |
// This code requires different components:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
// JDK needed to compile (javac HelloWorld.java)
// JRE needed to run (java HelloWorld)
// JVM executes the bytecode
The JDK is for developers who write Java code, JRE is for users who run Java applications, and JVM is the core execution engine that makes Java platform-independent.
References:
↑ Back to topWhy is Java considered platform-independent?
Java achieves platform independence through bytecode compilation and the Java Virtual Machine (JVM):
- Source Code → Bytecode: Java source code is compiled into platform-neutral bytecode (.class files)
- JVM per Platform: Each operating system has its own JVM implementation
- Bytecode Execution: The same bytecode runs on any JVM, regardless of the underlying OS
// This same .class file runs on Windows, Linux, macOS
public class PlatformIndependent {
public static void main(String[] args) {
System.out.println("Runs everywhere with JVM!");
}
}
The principle "Write Once, Run Anywhere" (WORA) means developers write code once, and it executes on any platform with a JVM installed.
References:
↑ Back to topHow do you define the main method in a Java class, and what is its significance?
The main method serves as the entry point for Java applications and must follow this exact signature:
public static void main(String[] args) {
// Application code starts here
System.out.println("Hello World!");
}
Each keyword has specific significance:
public: Accessible from anywhere, allowing JVM to call itstatic: Can be called without creating class instancesvoid: Returns no value to the operating systemString[] args: Command-line arguments passed to the program
// Example using command-line arguments
public class CommandLineExample {
public static void main(String[] args) {
if (args.length > 0) {
System.out.println("First argument: " + args[0]);
}
}
}
// Run: java CommandLineExample hello
// Output: First argument: hello
The JVM looks specifically for this method signature to start program execution.
References:
↑ Back to topWhat is the difference between byte, short, int, and long data types?
These are Java's integral primitive types, differing in size and range:
| Type | Size | Range | Use Case |
|---|---|---|---|
| byte | 8 bits | -128 to 127 | Memory-efficient arrays, file I/O |
| short | 16 bits | -32,768 to 32,767 | Unicode characters, small numbers |
| int | 32 bits | -2³¹ to 2³¹-1 (~±2 billion) | Default integer type |
| long | 64 bits | -2⁶³ to 2⁶³-1 | Large numbers, timestamps |
public class IntegerTypes {
public static void main(String[] args) {
byte smallNumber = 100;
short mediumNumber = 30000;
int defaultNumber = 2000000000;
long bigNumber = 9000000000000000000L; // Note the 'L' suffix
System.out.println("Byte max: " + Byte.MAX_VALUE);
System.out.println("Int max: " + Integer.MAX_VALUE);
System.out.println("Long max: " + Long.MAX_VALUE);
}
}
Choose the appropriate type based on the expected range of values and memory constraints.
References:
↑ Back to topWhat are the default values of primitive data types in Java?
Default values apply only to instance variables and static variables, not local variables:
| Type | Default Value | Note |
|---|---|---|
| byte | 0 | |
| short | 0 | |
| int | 0 | |
| long | 0L | |
| float | 0.0f | |
| double | 0.0d | |
| char | '\u0000' | Null character |
| boolean | false |
public class DefaultValues {
// Instance variables get default values
private int number; // 0
private boolean flag; // false
private char character; // '\u0000'
public void demonstrateDefaults() {
System.out.println("Default int: " + number); // 0
System.out.println("Default boolean: " + flag); // false
System.out.println("Default char code: " + (int)character); // 0
// Local variables must be initialized
int localVar;
// System.out.println(localVar); // Compilation error!
}
}
Important: Local variables in methods must be explicitly initialized before use.
References:
↑ Back to topWhat is the difference between "==" and equals() when comparing objects and primitives?
The == operator and equals() method serve different purposes depending on what you're comparing:
For Primitives:
==: Compares actual values
For Objects:
==: Compares memory references (identity)equals(): Compares content (when properly overridden)
public class ComparisonExample {
public static void main(String[] args) {
// Primitive comparison
int a = 5, b = 5;
System.out.println(a == b); // true - same values
// String comparison (objects)
String str1 = new String("hello");
String str2 = new String("hello");
String str3 = "hello";
String str4 = "hello";
System.out.println(str1 == str2); // false - different objects
System.out.println(str1.equals(str2)); // true - same content
System.out.println(str3 == str4); // true - string pool
// Custom object comparison
Person person1 = new Person("John");
Person person2 = new Person("John");
System.out.println(person1 == person2); // false - different objects
System.out.println(person1.equals(person2)); // depends on equals() implementation
}
}
Rule of thumb: Use == for primitives and reference comparison, use equals() for content comparison of objects.
References:
↑ Back to topHow do you convert a String to an int and vice versa?
Java provides several methods for converting between String and int:
String to int:
public class StringToInt {
public static void main(String[] args) {
// Method 1: Integer.parseInt() - preferred
String numberStr = "123";
int number1 = Integer.parseInt(numberStr);
// Method 2: Integer.valueOf() - returns Integer object, auto-unboxed
int number2 = Integer.valueOf(numberStr);
// Handling exceptions
try {
int invalidNumber = Integer.parseInt("abc"); // NumberFormatException
} catch (NumberFormatException e) {
System.out.println("Invalid number format");
}
System.out.println("Converted: " + number1); // 123
}
}
int to String:
public class IntToString {
public static void main(String[] args) {
int number = 456;
// Method 1: String.valueOf() - preferred
String str1 = String.valueOf(number);
// Method 2: Integer.toString()
String str2 = Integer.toString(number);
// Method 3: String concatenation (less efficient)
String str3 = number + "";
System.out.println("Converted: " + str1); // "456"
}
}
Best practices: Use Integer.parseInt() for String→int and String.valueOf() for int→String conversions.
References:
↑ Back to topWhat is a package in Java, and how do you import classes from it?
A package is a namespace mechanism that groups related classes, interfaces, and sub-packages. It provides organization and prevents naming conflicts.
Package Declaration:
// File: com/example/utils/MathHelper.java
package com.example.utils;
public class MathHelper {
public static int add(int a, int b) {
return a + b;
}
}
Importing Classes:
// Single class import (preferred)
import java.util.List;
import java.util.ArrayList;
import com.example.utils.MathHelper;
// Package wildcard import (use sparingly)
import java.util.*;
public class ImportExample {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
int result = MathHelper.add(5, 3);
// Fully qualified name (no import needed)
java.util.Date date = new java.util.Date();
}
}
Package Benefits:
- Organization: Groups related functionality
- Access Control: Package-private visibility
- Namespace: Prevents class name conflicts
Naming Convention: Reverse domain name (com.company.project.module)
References:
↑ Back to topWhat is the use of the "final" keyword in Java?
The final keyword provides immutability and inheritance control at different levels:
1. Final Variables (Constants):
public class FinalVariable {
// Compile-time constant
public static final int MAX_SIZE = 100;
// Runtime constant
private final String name;
private final List<String> items = new ArrayList<>();
public FinalVariable(String name) {
this.name = name; // Can be initialized once in constructor
// this.name = "changed"; // Compilation error!
}
public void addItem(String item) {
items.add(item); // Object is mutable, reference is final
// items = new ArrayList<>(); // Compilation error!
}
}
2. Final Methods (Cannot be overridden):
public class Parent {
public final void criticalMethod() {
System.out.println("This implementation cannot be changed");
}
}
public class Child extends Parent {
// public void criticalMethod() { } // Compilation error!
}
3. Final Classes (Cannot be extended):
public final class ImmutableClass {
private final String value;
public ImmutableClass(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
// public class Extended extends ImmutableClass { } // Compilation error!
Use Cases:
- Security: Prevent modification of critical values/methods
- Design: Enforce immutability and prevent inheritance
- Performance: Enable compiler optimizations
References:
↑ Back to topHow does Java handle memory allocation for primitive and reference types?
Java uses different memory areas for different types of data, managed by the JVM memory model:
Memory Areas:
public class MemoryAllocation {
// Static variables - stored in Method Area/Metaspace
private static int staticCounter = 0;
// Instance variables - stored in Heap
private int instanceVar = 42;
private String name = "Example"; // Reference in heap, object in heap
public void demonstrateMemory() {
// Local primitives - stored in Stack
int localInt = 10;
char localChar = 'A';
// Local object reference - reference in Stack, object in Heap
StringBuilder sb = new StringBuilder("Hello");
// Method call creates new stack frame
helperMethod(localInt);
}
private void helperMethod(int parameter) {
// New stack frame created
// Parameter and local variables in this frame
int localResult = parameter * 2;
}
}
Memory Allocation Summary:
| Type | Location | Managed By | Lifetime |
|---|---|---|---|
| Primitive locals | Stack | Automatic | Method scope |
| Object references | Stack | Automatic | Method scope |
| Objects | Heap | Garbage Collector | Until no references |
| Instance variables | Heap | Garbage Collector | Object lifetime |
| Static variables | Method Area/Metaspace | Class loading | Program lifetime |
Key Points:
- Stack: Fast allocation/deallocation, limited size, thread-specific
- Heap: Shared memory, garbage collected, larger capacity
- References: Always stored where the variable is declared
- Objects: Always created in heap memory
References:
↑ Back to topObject-Oriented Programming in Java
What are abstract classes and interfaces, and when do you use each?
Comparison Table:
| Feature | Abstract Class | Interface |
|---|---|---|
| Methods | Can have concrete and abstract methods | Abstract methods (default/static allowed since Java 8) |
| Variables | Instance variables allowed | Only public static final constants |
| Inheritance | Single inheritance (extends) |
Multiple inheritance (implements) |
| Constructor | Can have constructors | No constructors |
| Access Modifiers | All modifiers allowed | Public methods only (before Java 9) |
// Abstract class - partial implementation
abstract class DatabaseConnection {
protected String url; // Instance variable
public DatabaseConnection(String url) { // Constructor
this.url = url;
}
public void connect() { // Concrete method
System.out.println("Connecting to: " + url);
}
public abstract void executeQuery(String sql); // Must implement
}
// Interface - contract definition
interface Drawable {
int MAX_SIZE = 1000; // public static final
void draw(); // abstract method
default void setColor(String color) { // default method (Java 8+)
System.out.println("Setting color to: " + color);
}
}
// Implementation
class MySQLConnection extends DatabaseConnection implements Drawable {
public MySQLConnection(String url) {
super(url);
}
@Override
public void executeQuery(String sql) {
System.out.println("Executing MySQL query: " + sql);
}
@Override
public void draw() {
System.out.println("Drawing database schema");
}
}
When to Use:
- Abstract Class: When you need shared implementation and state among related classes
- Interface: When you need to define a contract that unrelated classes can implement
What does it mean that Java is an object-oriented programming language?
Java is object-oriented because it structures programs around objects rather than functions or procedures. Everything in Java (except primitives) is an object that contains:
- Data (attributes/fields)
- Behavior (methods)
- Identity (unique reference)
Java enforces OOP principles by requiring all code to exist within classes, supporting inheritance, encapsulation, and polymorphism natively.
// Everything revolves around objects and classes
public class Car {
private String model; // Data
public void start() { // Behavior
System.out.println("Car starting...");
}
}
This design promotes code reusability, modularity, and maintainability by modeling real-world entities as software objects.
↑ Back to topWhat are the four main principles of OOP, and how are they implemented in Java?
| Principle | Definition | Java Implementation |
|---|---|---|
| Encapsulation | Bundling data and methods, hiding internal details | private fields, public getters/setters |
| Inheritance | Creating new classes based on existing ones | extends keyword, class hierarchies |
| Polymorphism | Same interface, different implementations | Method overriding, interfaces |
| Abstraction | Hiding complex implementation details | abstract classes, interface keyword |
// All four principles in action
abstract class Animal { // Abstraction
private String name; // Encapsulation
public Animal(String name) { // Constructor
this.name = name;
}
public abstract void makeSound(); // Abstract method
}
class Dog extends Animal { // Inheritance
public Dog(String name) {
super(name);
}
@Override
public void makeSound() { // Polymorphism
System.out.println("Woof!");
}
}
These principles work together to create flexible, maintainable, and scalable software systems.
↑ Back to topHow do you achieve encapsulation in Java?
Encapsulation is achieved by restricting direct access to class internals and providing controlled access through methods:
Key Techniques:
- Private fields - Hide data from external access
- Public methods - Provide controlled access (getters/setters)
- Access modifiers - Control visibility levels
public class BankAccount {
private double balance; // Hidden from outside
private String accountNumber; // Protected data
// Controlled access through methods
public double getBalance() {
return balance;
}
public void deposit(double amount) {
if (amount > 0) { // Validation logic
balance += amount;
}
}
public boolean withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
return true;
}
return false;
}
}
Benefits: Data integrity, validation, flexibility to change internal implementation without breaking client code.
Reference: Oracle Java Encapsulation Guide
↑ Back to topWhat is inheritance, and how do you implement it?
Inheritance allows a class to acquire properties and methods from another class, promoting code reuse and establishing "is-a" relationships.
Implementation:
- Use
extendskeyword - Child class inherits all non-private members
- Can override parent methods
// Base class (parent)
public class Vehicle {
protected String brand;
protected int year;
public void start() {
System.out.println("Vehicle starting...");
}
public void displayInfo() {
System.out.println(brand + " " + year);
}
}
// Derived class (child)
public class Car extends Vehicle {
private int doors;
public Car(String brand, int year, int doors) {
this.brand = brand; // Inherited field
this.year = year; // Inherited field
this.doors = doors;
}
@Override
public void start() { // Method overriding
System.out.println("Car engine starting...");
}
}
Key Points: Java supports single inheritance only (one parent class), but multiple interface implementation is allowed.
↑ Back to top