Core Java Basics

Welcome to the Master Guide for Core Java Basics. Whether you are a fresher or have up to 5 years of experience, these curated questions will help you clear technical rounds at top MNCs like TCS, Infosys, and EPAM.

Java Learning Progress 0% Completed

1. Java Program Structure & JVM

Q1: Write a simple Java program and explain 'public static void main'.
public class HelloWorld {
    // public: Accessible from anywhere
    // static: JVM can call it without creating an object
    // void: Does not return any value
    // main: Entry point of the program
    public static void main(String[] args) {
        System.out.println("Hello, Java!");
    }
}
Q2: What is the difference between Heap and Stack memory?
[Image of Java Heap vs Stack memory architecture]
  • Stack: Used for method execution and local variables. (Fixed size, LIFO).
  • Heap: Used for dynamic memory allocation of Objects. (Garbage collected).

2. Data Types & String Manipulation

Q3: How to reverse a String in Java without using built-in functions?
String str = "Indore";
String reversed = "";
for (int i = str.length() - 1; i >= 0; i--) {
    reversed += str.charAt(i);
}
System.out.println(reversed); // Output: erodnI
Q4: What is the String Constant Pool (SCP)?
SCP is a special memory area inside the Heap. When you create a String literal, Java checks the pool first. If it exists, the reference is reused, saving memory.
String s1 = "Java"; // Created in SCP
String s2 = "Java"; // Points to the same object
System.out.println(s1 == s2); // true

3. Keywords (Static, Final, This)

Q5: What is a 'static' variable and 'static' block?
Static members belong to the class, not the object. A static block is used to initialize static variables and runs before the main method.
class Test {
    static int count = 0;
    static {
        System.out.println("Static Block Executed");
    }
}
Q6: Difference between 'final', 'finally', and 'finalize'?
  • final: Keyword to make a variable/method/class unchangeable.
  • finally: Block used in try-catch to execute important code (like closing DB).
  • finalize: Method called by Garbage Collector before destroying an object.

4. Control Statements & Logic

Q7: How to check if a number is Prime in Java?
int num = 29;
boolean isPrime = true;
for (int i = 2; i <= num / 2; i++) {
    if (num % i == 0) {
        isPrime = false;
        break;
    }
}
System.out.println(isPrime ? "Prime" : "Not Prime");
Q8: What is the difference between 'break' and 'continue'?
  • break: Exits the loop entirely.
  • continue: Skips the current iteration and moves to the next one.

5. Arrays & Wrapper Classes

Q9: How to find the largest element in an Array?
int[] arr = {10, 50, 20, 90, 30};
int max = arr[0];
for (int i : arr) {
    if (i > max) max = i;
}
System.out.println("Largest: " + max);
Q10: What is Autoboxing and Unboxing?
  • Autoboxing: Automatic conversion of primitive to Wrapper (int to Integer).
  • Unboxing: Automatic conversion of Wrapper to primitive (Integer to int).
Integer a = 10; // Autoboxing
int b = a;     // Unboxing

6. Advance Levels

How does the Garbage Collector (GC) decide which Java objects to clean?
In Java, the Garbage Collector identifies "dead" objects that are no longer reachable by the application. It primarily uses two techniques:

  • Reference Counting (Old Method): Every object has a counter. If the count is zero, it's deleted. Note: This is rarely used now because it fails to handle "Circular References."
  • Reachability Analysis (Modern Method): The GC starts from GC Roots (like local variables, active threads, and static fields). If an object cannot be reached by a chain of references from a GC Root, it is marked as unreachable and eligible for collection.
The Marking States:
  1. Mark: GC traverses the object graph and marks all reachable objects.
  2. Sweep: Unmarked objects are removed from the heap.
  3. Compact: Remaining objects are moved together to prevent memory fragmentation.
			// Example of an object becoming eligible for GC
			Student s1 = new Student(); // Reachable
			s1 = null; // Now the object is eligible for Garbage Collection
What is the difference between Minor GC and Major GC?
The primary difference lies in where the garbage collection occurs within the Java Heap memory (Generational Heap).

  • Minor GC: This happens in the Young Generation (Eden and Survivor spaces). It is triggered when the Eden space is full. It is very fast and happens frequently because most objects die young.
  • Major GC (or Full GC): This happens in the Old Generation (Tenured space). It is triggered when the Old Generation is full or when a Minor GC fails to move objects. It is much slower and can cause "Stop-the-World" pauses.
Feature Minor GC Major GC
Area Young Generation Old Generation
Frequency High Low
Performance Very Fast Slow (Impacts App)

Note: A Full GC cleans both the Young and Old generations (and sometimes the Metaspace/Permanent Generation).

Why is String immutable in Java, and what are its benefits in a multi-threaded environment?
In Java, String immutability means that once a String object is created, its value cannot be changed. If you try to "modify" it, Java actually creates a completely new String object in memory.

1. Why is it Immutable?
  • String Constant Pool (SCP): If Strings were mutable, changing one String would unintentionally change all other variables pointing to that same reference in the pool.
  • Security: Strings are used for sensitive data like Database URLs, usernames, and passwords. Immutability ensures these values aren't tampered with by untrusted code.
  • Caching HashCode: Since the value is fixed, the hashCode() is calculated only once. This makes Strings very fast when used as keys in a HashMap.

2. Benefits in a Multi-threaded Environment

String is Thread-Safe by default. Because a String object cannot be modified, it provides the following advantages:

  • No Synchronization Needed: You don't need to use synchronized blocks or locks when sharing Strings between threads. This significantly improves performance.
  • Side-Effect Free: Multiple threads can read the same String instance simultaneously without the risk of one thread changing the value while another is reading it.
  • Prevents Data Corruption: In a mutable object, "Thread A" might update a value while "Thread B" is halfway through a process, leading to inconsistent states. With Strings, this is impossible.
// Thread Safety Example
String shared = "Fixed"; 
// Even if 10 threads access 'shared', 
// none can change "Fixed" to something else.
// They can only create a NEW string if they "modify" it.
How does the ClassLoader work in Java? Can we have multiple ClassLoaders in one JVM?
The ClassLoader is a part of the JRE (Java Runtime Environment) that dynamically loads Java classes into the JVM during runtime. It follows the Delegation Hierarchy Principle.

1. How it works (Delegation Principle):

When a request is made to load a class, the ClassLoader follows these steps:

  • Check Cache: It first checks if the class is already loaded.
  • Delegate Up: If not loaded, it delegates the request to its Parent ClassLoader.
  • Load Down: If the parent cannot find the class, only then does the current ClassLoader attempt to load it from its own classpath.

2. The Hierarchy of ClassLoaders:
  1. Bootstrap ClassLoader: Loads core Java APIs (rt.jar). Written in native code (C/C++).
  2. Extension (Platform) ClassLoader: Loads classes from the jre/lib/ext directory.
  3. Application (System) ClassLoader: Loads classes from the application's CLASSPATH.

3. Can we have multiple ClassLoaders in one JVM?

Yes, a single JVM can (and usually does) have multiple ClassLoaders. This is useful for several reasons:

  • Isolation: You can load two different versions of the same class (e.g., in a Web Server like Tomcat where different apps need different library versions).
  • Security: It separates "trusted" core Java classes from "untrusted" user-defined classes.
  • Custom Loading: You can create a Custom ClassLoader by extending the java.lang.ClassLoader class to load classes from a database or a remote URL.
// Example of checking the ClassLoader of a class
System.out.println(String.class.getClassLoader()); // Returns null (Bootstrap)
System.out.println(MyClass.class.getClassLoader()); // Returns AppClassLoader
What is the difference between String and StringBuilder? Which one should be used where?
The fundamental difference between String and StringBuilder is Immutability.


1. Main Differences:
  • Immutability: String is immutable (cannot be changed). StringBuilder is mutable (can be modified in-place).
  • Memory Usage: Every time you modify a String, a new object is created in the String Constant Pool. StringBuilder modifies the existing object in the Heap, saving memory.
  • Performance: StringBuilder is significantly faster when performing heavy string manipulations (like loops).
Feature String StringBuilder
Storage String Constant Pool Heap Memory
Modifiable No (Immutable) Yes (Mutable)
Thread Safe Yes No

2. Which one to use where?

Choosing the right class depends on the frequency of changes:

  • Use String: If the data is not going to change frequently (e.g., a username, a fixed error message, or a configuration key). It is safe and memory-efficient for fixed values.
  • Use StringBuilder: If you are performing a lot of modifications, such as concatenating strings inside a for or while loop.
// BAD Practice (Creates 1000 String objects)
String s = "";
for(int i=0; i<1000; i++) s += i; 

// GOOD Practice (Uses only 1 StringBuilder object)
StringBuilder sb = new StringBuilder();
for(int i=0; i<1000; i++) sb.append(i);

Note: If you need a thread-safe mutable string, use StringBuffer instead of StringBuilder.

Which Java version have you worked on, and why is it preferred?
In modern enterprise development, Java 17 (LTS) is the industry standard. It is the baseline requirement for Spring Boot 3.x and offers significant performance and syntax improvements over older versions like Java 8 or 11.

1. Why Java 17 is the Preferred Choice:
  • LTS (Long Term Support): Companies prefer Java 17 because it receives security updates and support until at least 2029, making it stable for production.
  • Performance: The G1 Garbage Collector is much more efficient in Java 17, leading to lower latency and better memory management for Microservices.
  • Modern Syntax: It reduces "Boilerplate" code, making the application easier to maintain and read.

2. Key Java 17 Features I Use Daily:
  • Records: Replaces heavy POJO classes. A single line replaces Private fields, Getters, toString(), and hashCode().
  • Sealed Classes: Provides better control over inheritance by specifying exactly which classes can extend a parent.
  • Switch Expressions: Allows the switch to return a value directly using the -> arrow syntax, eliminating the need for break keywords.
  • Text Blocks: Makes writing SQL queries or JSON strings inside Java code much cleaner.
// Traditional Switch vs Java 17 Switch Expression
String result = switch (day) {
    case MONDAY, FRIDAY -> "Busy";
    case SATURDAY, SUNDAY -> "Relax";
    default -> "Normal";
};

// Text Blocks for SQL
String query = """
               SELECT user_name, email 
               FROM users 
               WHERE status = 'ACTIVE'
               """;

Pro-Tip for Interviews: Mentioning that you use Java 17 because of Spring Boot 3 compatibility shows that you understand the full technology stack, not just the language.

Will using Strings for millions of records create a memory problem in Java?
Yes, storing millions of String objects can lead to an OutOfMemoryError (OOM) or high Garbage Collection (GC) overhead if not handled correctly. This is because Strings in Java are objects, and every object has a memory overhead.


1. Why it creates a problem:
  • Object Overhead: Every String object has an overhead of ~24-32 bytes (Header + Fields) plus the actual character data. For 1 million empty Strings, you've already lost ~32MB just in headers!
  • Duplicate Data: If 1 million records contain the same value (e.g., "India" repeated 500,000 times), creating a new String() for each one wastes massive amounts of Heap memory.
  • GC Pressure: Millions of short-lived Strings fill up the Young Generation rapidly, causing frequent Minor GCs that slow down your application.
2. How to fix it (Java 17 Solutions):
  • String Interning: Use string.intern() to store only one copy of repeated strings in the String Constant Pool.
  • Compact Strings (Java 9+): Java 17 automatically uses Compact Strings. If your data is just Latin-1 (standard English), Java uses 1 byte per character instead of 2 bytes, saving 50% memory.
  • Use Enums or IDs: For fields like "Status" or "Country," use an Enum or an Integer ID instead of a String.

3. Performance Comparison:

If you have 1 million records of the word "Completed":

  • Without Interning: ~40 MB of Heap used.
  • With Interning: ~50 Bytes (only 1 object shared by all 1 million references).
// Optimization Example
List<String> records = new ArrayList<>();
for (String data : databaseResult) {
    // Instead of: records.add(data);
    records.add(data.intern()); // Saves massive memory if values repeat
}

Pro-Tip: In Java 17, the String Pool is part of the Heap, so it is safely garbage collected when no longer needed.

What are Default Methods in Interfaces, and why were they introduced?
Default methods (introduced in Java 8) allow you to add new methods to an interface with a full implementation, using the default keyword. Prior to this, interfaces could only have abstract methods (no body).

1. Why were they introduced? (Backward Compatibility)

The main reason was to allow the Java Collection API to evolve. For example, the forEach() method was added to the Iterable interface. If it weren't a default method, every existing Java application in the world would have failed to compile because their custom collections didn't implement forEach().


2. Key Rules for Default Methods:
  • Optional Override: Implementing classes can use the default logic or provide their own specific override.
  • Multiple Inheritance (The Diamond Problem): If a class implements two interfaces that have the same default method signature, Java will throw a compilation error. You must manually resolve this by overriding the method in the class.
  • Static vs Default: Unlike static methods, default methods are inherited and can be overridden.

3. The "Diamond Problem" Resolution:
interface InterfaceA {
    default void sayHello() { System.out.println("Hello from A"); }
}

interface InterfaceB {
    default void sayHello() { System.out.println("Hello from B"); }
}

public class MyClass implements InterfaceA, InterfaceB {
    // Must override to resolve ambiguity
    @Override
    public void sayHello() {
        InterfaceA.super.sayHello(); // Or provide custom logic
    }
}

Pro-Tip for Java 17: In modern Java, we often use Private Methods inside interfaces to help break down complex logic used by multiple default methods, keeping the interface code clean.

Scenario: A Bank interface is used by multiple branches, but only the Mumbai branch needs a specific "Special Benefit" method. How can you achieve this using Interfaces?
In a large banking system, we can use Java 8+ Default Methods to introduce new functionality to specific branches without forcing every other branch (like Delhi or Indore) to implement it.

1. The Solution:

We define the "Special Benefit" as a default method in the base BankService interface. By default, it returns a standard value or "No Benefit." Only the Mumbai branch will @Override this method to provide its specific logic.


2. Implementation Example:
interface BankService {
    void deposit(double amount);
    void withdraw(double amount);

    // Default method: Other branches don't need to touch this code
    default double getSpecialBenefit() {
        return 0.0; // Standard benefit for most branches
    }
}

class DelhiBranch implements BankService {
    public void deposit(double a) { /* Logic */ }
    public void withdraw(double a) { /* Logic */ }
    // Uses default getSpecialBenefit() automatically
}

class MumbaiBranch implements BankService {
    public void deposit(double a) { /* Logic */ }
    public void withdraw(double a) { /* Logic */ }

    @Override
    public double getSpecialBenefit() {
        return 500.0; // Specific benefit only for Mumbai
    }
}

3. Why this is the best approach:
  • Backward Compatibility: If you have 100 branches already using BankService, they won't throw compilation errors when you add the benefit.
  • Clean Code: You avoid instanceof checks or type-casting in your main business logic.
  • Flexibility: If tomorrow the Bangalore branch also needs a benefit, they simply override the method as well.

Interview Tip: Mention that this follows the Interface Segregation Principle (part of SOLID) while utilizing the power of Java 8+ evolution.

Q: You need a thread-safe cache in a Java application. What would you use? Hard
Choosing a thread-safe cache depends on whether you need a Local (In-Memory) cache or a Distributed cache.

1. Local (Single Instance) Solutions:
  • ConcurrentHashMap (The Baseline): Best for simple key-value storage. It uses Lock Striping (segment-level locking), which allows multiple threads to read and write simultaneously without blocking the entire map.
  • Caffeine / Guava Cache (The Professional Choice): These are high-performance caching libraries. Unlike a simple Map, they handle Eviction Policies (Least Recently Used), Expiration (TTL), and automatic loading. Caffeine is the standard for Spring Boot 3 applications.

2. Distributed (Multiple Instances) Solutions:
  • Redis: Use this if you have multiple Microservices and they all need to share the same cache. It stores data in memory outside the JVM, so if your application restarts, the cache is still there.
  • Hazelcast: An "In-Memory Data Grid" that distributes the cache across your application nodes. It is often used in high-frequency trading or large-scale banking systems.
Feature ConcurrentHashMap Caffeine / Redis
Eviction (LRU) No (Must code manually) Yes (Automatic)
Data Expiry No Yes (Time-to-Live)
Complexity Low Medium to High
// Using ConcurrentHashMap for simple thread-safe caching
Map<String, String> cache = new ConcurrentHashMap<>();
cache.putIfAbsent("key", "value");

// Using Caffeine (Recommended for Spring Boot)
Cache<String, Object> cache = Caffeine.newBuilder()
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .maximumSize(10_000)
    .build();

Pro-Tip for Interviews: Always clarify the Eviction Strategy. A cache that never deletes old data is just a Memory Leak.

Q: You need a map that is both Sorted and has Fast Lookups. Which one would you choose? Medium
In Java, the choice depends on how you want the data sorted (by Insertion Order or by Natural/Key Order).

1. LinkedHashMap (Fastest + Insertion Order):
  • Performance: O(1) for lookups (same as HashMap).
  • Sorting: It maintains the Insertion Order (the order in which keys were added).
  • Use Case: Use this if you need a "Recent Items" list or a cache where the sequence of entry matters.
2. TreeMap (Natural Sorting + Slightly Slower):
  • Performance: O(log n) for lookups (Logarithmic time).
  • Sorting: It maintains Natural Sorting Order (e.g., Alphabetical or Numerical) or a custom Comparator.
  • Use Case: Use this if you need the map to always be sorted by the keys themselves (e.g., a Price List from lowest to highest).
Feature LinkedHashMap TreeMap
Lookup Speed O(1) - Constant O(log n) - Logarithmic
Sorting Type Insertion Order Natural / Key Order
Internal Data Structure Hash Table + Doubly Linked List Red-Black Tree (Self-balancing)
// Use LinkedHashMap for O(1) speed + Insertion Order
Map<String, Integer> fastMap = new LinkedHashMap<>();

// Use TreeMap for Alphabetical Order (but O(log n) speed)
Map<String, Integer> sortedMap = new TreeMap<>();

Interview Pro-Tip: If the interviewer asks for Thread-Safety as well, mention ConcurrentSkipListMap. It is the concurrent version of TreeMap and is highly efficient for sorted lookups in multi-threaded environments.


🚀 Ready to Crack Your Interview?

If you found these Java 17 questions helpful, don't miss our daily updates!

Finished studying this topic?

Return to Home Page

Comments

More Related

For Any Help Related to coding exams follow me on Instagram : codingsolution75

Popular Posts

EPAM Latest Coding Questions with Solutions 2026

Java Interview Questions

Fresco Play Hands-on Latest Solutions

Accenture Latest Coding Questions with Solutions

MindTree Latest Coding Questions with Solutions

Infosys | InfytTq | Infosys Certification Exam Latest Coding Questions with Solutions

LTI (Larsen & Toubro Infotech ) Coding Questions and Solutions 2022-23

Cognizant

TCS Digital Exam | DCA | Direct Capability Assessment

TypeScript Complete Course With Completed Hands-on