Fundamentals 45 min read

Master Java Fundamentals: Essential Interview Topics and Core Concepts

This comprehensive guide covers Java platform basics, JVM/JRE/JDK relationships, bytecode advantages, new features since Java 8, core OOP principles, common interview questions, exception handling, garbage collection, reference types, and practical code examples to solidify your Java expertise.

Su San Talks Tech
Su San Talks Tech
Su San Talks Tech
Master Java Fundamentals: Essential Interview Topics and Core Concepts

Strengthen your Java core skills by reviewing interview questions and building a systematic knowledge framework, avoiding fragmented learning.

As highlighted in the Redis series, learning a technology without a complete mental model leads to shallow understanding and quick forgetting.

Follow this guide to outline a relatively complete Java development skill map and solidify fundamentals.

Understanding the Java Platform

Code Master, how do you understand the Java platform?

Java is an object‑oriented language with two notable features:

Cross‑platform capability: Write once, run anywhere.

Garbage collection.

Java achieves cross‑platform execution through bytecode and the Java Virtual Machine (JVM), which abstracts away OS and hardware details.

The JVM’s garbage collector (GC) automatically reclaims memory, so developers usually do not manage allocation manually. Common collectors include SerialGC, ParallelGC, CMS, and G1.

JVM, JRE, JDK Relationship

Can you explain the relationship between JVM, JRE, and JDK?
JVM

(Java Virtual Machine) runs Java programs; each platform provides its own JVM implementation. JRE (Java Runtime Environment) includes the JVM and core class libraries needed to run Java applications.

The core library is java.lang, which contains essential classes such as primitive types, math functions, strings, threads, and exceptions.

Installing only the JRE is sufficient to run compiled Java programs. JDK (Java Development Kit) provides development tools (compiler, jar, etc.) and includes a JRE, so a separate JRE installation is unnecessary.

JVM JRE JDK diagram
JVM JRE JDK diagram

Is Java Interpreted?

Is Java interpreted?

The statement is inaccurate. Java source code is first compiled by javac into bytecode, then the JVM’s interpreter translates bytecode to machine code at runtime.

Most JVMs, such as Oracle’s HotSpot, also include a Just‑In‑Time (JIT) compiler that dynamically compiles hot code paths to native machine code, making that portion compiled rather than interpreted.

Benefits of Bytecode

What is bytecode and why is it beneficial?

Bytecode is the .class file generated after compiling Java source; it targets the JVM, not any specific processor.

Benefits include platform independence, as the same bytecode runs on any JVM, and a clear separation between compilation and execution phases.

Fundamental Syntax

New Features After JDK 1.8

Default methods in interfaces : Java 8 allows non‑abstract method implementations in interfaces using the default keyword.

Lambda expressions and functional interfaces : Lambdas are essentially anonymous inner classes that enable passing behavior as parameters, improving code conciseness when used judiciously.

Stream API : Provides functional‑style operations on collections, similar to SQL queries, and supports parallel execution.

Method references : Offer concise syntax to reference existing methods or constructors, often used with lambdas.

Date‑time API : Java 8 introduced a modern date‑time library.

Optional class : Helps avoid NullPointerException by representing optional values, inspired by Guava’s Optional.

New tools : Nashorn JavaScript engine ( jjs) and class dependency analyzer ( jdeps).

Can Constructors Be Overridden?

Constructors cannot be overridden, but they can be overloaded, allowing multiple constructors in a class.

Difference Between wait() and sleep()

sleep()

is defined in Thread, does not release the monitor, and can be called anywhere. wait() is defined in Object, releases the monitor, must be called within a synchronized block or method, and requires another thread to invoke notify() / notifyAll() to resume.

Difference Between & and &&

&

serves as a bitwise AND and a logical AND (non‑short‑circuit). && is the short‑circuit logical AND; if the left operand is false, the right side is not evaluated.

Java Data Types

Java is strongly typed with two categories:

Primitive types: byte, short, int, long, float, double, char, boolean.

Reference types: classes, interfaces, arrays.

Data type diagram
Data type diagram

Usage of this

this

refers to the current object instance.

Three common uses:

Direct reference to the current object.

Disambiguate member variables from parameters when they share the same name.

Invoke another constructor in the same class using this(...).

public Person(String name, int age) {
    this.name = name;
    this.age = age;
}
class Person {
    private String name;
    private int age;

    public Person() {}

    public Person(String name) {
        this.name = name;
    }

    public Person(String name, int age) {
        this(name);
        this.age = age;
    }
}

Usage of super

super

refers to the immediate superclass instance.

Three uses:

Directly access superclass members.

Disambiguate when subclass members hide superclass members.

Invoke a superclass constructor.

class Person {
    protected String name;
    public Person(String name) { this.name = name; }
}

class Student extends Person {
    private String name;
    public Student(String name, String parentName) {
        super(parentName);
        this.name = name;
    }
    public void getInfo() {
        System.out.println(this.name); // child
        System.out.println(super.name); // parent
    }
}

Member vs. Local Variables

Member variables belong to the class instance and reside in heap memory; they have default initial values.

Local variables exist within method scopes, reside on the stack, and must be explicitly initialized before use.

Dynamic Proxy Principle

Dynamic proxies are implemented using Java reflection, allowing runtime creation of proxy objects that delegate method calls.

What are typical use cases?

Common scenarios include AOP (aspect‑oriented programming) and wrapping RPC calls to decouple callers from implementations.

Difference Between int and Integer

int

is a primitive type; Integer is its wrapper class, enabling object‑oriented operations and supporting null values.

Since Java 5, autoboxing/unboxing automatically converts between the two.

Integer caching for values between –128 and 127 improves performance and equality checks.

public static void main(String[] args) {
    Integer a = new Integer(3);
    Integer b = 3; // autoboxed
    int c = 3;
    System.out.println(a == b); // false
    System.out.println(a == c); // true
    System.out.println(b == c); // true

    Integer a1 = 128;
    Integer b1 = 128;
    System.out.println(a1 == b1); // false

    Integer a2 = 127;
    Integer b2 = 127;
    System.out.println(a2 == b2); // true
}

Object‑Oriented Programming

What is the difference between OOP and procedural programming?

Procedural : Emphasizes performance, suitable for low‑level or embedded systems; lacks encapsulation and reuse.

Object‑Oriented : Provides encapsulation, inheritance, polymorphism, and abstraction, leading to easier maintenance, reuse, and extensibility, though with some performance overhead.

Four OOP Characteristics

Abstraction : Capture common features of objects, focusing on what an object does rather than how it does it.

Encapsulation : Hide internal state and expose behavior through methods.

Inheritance : Create new classes based on existing ones, reusing code while extending functionality.

Polymorphism : Allow a single interface to represent different underlying forms (methods overridden in subclasses or implemented via interfaces).

Polymorphism Mechanism

Java achieves polymorphism through inheritance, method overriding, and upcasting (assigning a subclass instance to a superclass reference).

Overloading vs. Overriding

Overloading : Same method name, different parameter lists within the same class (compile‑time polymorphism).

Overriding : Subclass provides its own implementation of a superclass method with identical signature (runtime polymorphism).

Difference Between == and equals()

==

compares primitive values or object references (memory addresses). equals() can be overridden to compare logical equality of object contents.

Why must hashCode() be overridden when equals() is?

If two objects are equal according to equals(), they must return the same hash code; otherwise collections like HashSet behave incorrectly.

Why hashCode Matters

HashSet

uses hashCode to locate buckets; equal hash codes trigger an equals() check to confirm actual equality, reducing the number of expensive equals() calls.

Basic OOP Principles (SOLID)

Single Responsibility Principle (SRP)

Open‑Closed Principle (OCP)

Liskov Substitution Principle (LSP)

Interface Segregation Principle (ISP)

Dependency Inversion Principle (DIP)

Exception vs. Error

What do they have in common?

Both inherit from Throwable and can be thrown or caught.

Exception : Represents recoverable conditions; includes checked (must be declared or caught) and unchecked (runtime) exceptions.

Error : Represents serious problems (e.g., OutOfMemoryError, StackOverflowError) that applications typically cannot recover from.

Exception vs Error diagram
Exception vs Error diagram

How JVM Handles Exceptions

When an exception occurs, the JVM creates an exception object and searches the call stack for a matching catch block. If none is found, the default handler prints the stack trace and terminates the program.

NoClassDefFoundError vs. ClassNotFoundException

NoClassDefFoundError

is an Error thrown by the JVM when a class definition cannot be found at runtime. ClassNotFoundException is a checked exception thrown when dynamic class loading (e.g., Class.forName) fails.

Common Java Exceptions

IllegalAccessError
InstantiationError
OutOfMemoryError
StackOverflowError
ClassCastException
ClassNotFoundException
ArithmeticException
ArrayIndexOutOfBoundsException

final, finally, finalize Differences

final

: Can modify classes (prevent inheritance), methods (prevent overriding), or variables (make constants). finally: Block that always executes after try / catch, typically for resource cleanup. finalize: Method called by the garbage collector before object reclamation; rarely used.

What is the use of final ?

It enforces immutability for classes, methods, or variables, improving safety and readability.

Does finally execute when catch returns?

Yes, the finally block runs before the method returns.

public static int getInt() {
    int a = 10;
    try {
        System.out.println(a / 0);
        a = 20;
    } catch (ArithmeticException e) {
        a = 30;
        return a; // finally still runs
    } finally {
        a = 40;
    }
    return a; // returns 30 because return in catch was already recorded
}
public static int getInt() {
    int a = 10;
    try {
        System.out.println(a / 0);
        a = 20;
    } catch (ArithmeticException e) {
        a = 30;
        return a;
    } finally {
        a = 40;
        return a; // overrides previous return, returns 40
    }
}

Reference Types in Java

What are strong, soft, weak, and phantom references?

Strong reference : Normal object reference; prevents garbage collection.

Soft reference : Collected only when memory is low; useful for memory‑sensitive caches.

Weak reference : Collected eagerly; used in structures like ThreadLocalMap keys.

Phantom reference : Does not prevent collection; used with a ReferenceQueue to track reclamation.

String, StringBuilder, StringBuffer

String is immutable; each modification creates a new object.

StringBuilder is mutable, non‑thread‑safe, and preferred for single‑threaded concatenation.

StringBuffer is mutable and thread‑safe (synchronized), incurring extra overhead.

Performance hierarchy: StringBuilder ≈ 10‑15% faster than StringBuffer, both far outperform repeated String concatenation.

String

Immutable class providing extensive utility methods; declared final with all fields final.

StringBuilder

Introduced in Java 1.5; same API as StringBuffer but without synchronization.

StringBuffer

Thread‑safe mutable character sequence; each method is synchronized.

Using String as HashMap Key

Strings are immutable and cache their hash code, making them efficient keys for HashMap lookups.

Interfaces vs. Abstract Classes

Both cannot be instantiated and can contain abstract methods that subclasses must implement.

Prefer interfaces for defining behavior contracts (aligns with SOLID’s ISP).

Use abstract classes when shared implementation or state is needed.

Interface

Defines a contract; all fields are implicitly public static final. Java 8 added default and static methods.

Abstract Class

Can contain both abstract and concrete methods, as well as state. Used for code reuse.

Can an abstract class be declared final ?

No, because final prevents inheritance, contradicting the purpose of an abstract class.

Value vs. Reference Passing

Java always uses pass‑by‑value. For primitives, the value is copied. For objects, the value of the reference is copied, so the method can modify the object's state but cannot reassign the caller’s reference.

Why does Java have only value passing?

Because the language passes a copy of the argument (primitive value or reference value), ensuring the method cannot alter the caller’s variable bindings.

Primitive Types Example

public static void main(String[] args) {
    int num1 = 10;
    int num2 = 20;
    swap(num1, num2);
    System.out.println("num1 = " + num1);
    System.out.println("num2 = " + num2);
}

public static void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    System.out.println("a = " + a);
    System.out.println("b = " + b);
}

Output shows original variables unchanged, demonstrating value passing.

Reference Types Example

public static void main(String[] args) {
    int[] arr = {1,2,3,4,5};
    System.out.println(arr[0]);
    change(arr);
    System.out.println(arr[0]);
}

public static void change(int[] array) {
    array[0] = 0; // modifies the original array
}

Output changes from 1 to 0, showing that the method can mutate the object referred to by the copied reference.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JVMMemory ManagementinterviewOOPfundamentalsExceptions
Su San Talks Tech
Written by

Su San Talks Tech

Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.