CSE310Semester 4 • 4 CreditsCore Subjects

Programming In Java

This course focuses on Java programming constructs, Object-Oriented Programming principles, inheritance, exception handling, multithreading, and the use of collections and generics. It aims to develop skills in creating efficient, reusable code and managing advanced Java applications involving database connectivity.

Syllabus PDF
6 Units • Notes • Model Answers • MCQs
Select Course Unit (6 Units)
Active: Unit 1
Unit 1:Unit 1: Introduction to Java
25 min read•High-Yield Unit Guide

Unit 1: Introduction to Java

Unit 1 Exam Focus & Core Takeaways

Review the core definitions, standard architectures, and syntax patterns below. Pay special attention to sections highlighted with bullet points for your mid-term and end-term subjective questions.

Unit 1: Introduction to Java


1. History, Evolution, and Architectural Philosophy of Java

1.1 Genesis and Historical Context

In June 1991, James Gosling, Mike Sheridan, and Patrick Naughton initiated the Java language project at Sun Microsystems (the "Green Team"). The original objective was to architect a lightweight, reliable, hardware-independent programming language for embedded consumer electronics (such as smart set-top cable television boxes and interactive home appliances).

CODE
+-------------------------------------------------------------------------------------------------+
|                                     Evolutionary Timeline                                       |
+-------------------------------------------------------------------------------------------------+
|                                                                                                 |
|   1991: Project initiated by James Gosling; originally designated "Greentalk"                   |
|     |                                                                                           |
|     v                                                                                           |
|   1992: Renamed to "Oak" (inspired by the grand oak tree outside Gosling's office window)       |
|     |                                                                                           |
|     v                                                                                           |
|   1995: Renamed to "Java" (after trademark conflicts with Oak Technology; inspired by coffee)   |
|     |   Public release of Java 1.0 focusing on web interactive Applets                          |
|     v                                                                                           |
|   2004: Java 5.0 (Tiger) released: Generics, Enums, Autoboxing/Unboxing, Varargs, Annotations   |
|     |                                                                                           |
|     v                                                                                           |
|   2010: Oracle Corporation acquires Sun Microsystems                                            |
|     |                                                                                           |
|     v                                                                                           |
|   2014: Java 8 released: Lambda expressions, Functional interfaces, Stream API, Optional API    |
|     |                                                                                           |
|     v                                                                                           |
|   Modern LTS Releases: Java 11 (2018), Java 17 (2021), Java 21 (2023 with Virtual Threads)      |
|                                                                                                 |
+-------------------------------------------------------------------------------------------------+

The defining design motto of Java was "Write Once, Run Anywhere" (WORA). Unlike traditional compiled languages (such as C/C++) that compile directly into platform-specific machine code (e.g., x86 or ARM assembly), Java compiles source code into an intermediate, architecture-neutral representation termed Bytecode (.class files), executed uniformly by a virtual environment termed the Java Virtual Machine (JVM).

1.2 Core Architectural Buzzwords (The Java White Paper)

Sun Microsystems articulated the fundamental engineering philosophy of Java across eleven foundational characteristics:

  1. Simple: Syntactically derived from C and C++ to minimize learning curves, but deliberately purged of error-prone, unsafe low-level constructs: explicit pointer arithmetic, direct memory allocation/deallocation (malloc/free), multiple inheritance of classes, and operator overloading.
  2. Object-Oriented: Focuses on data (objects) and interfaces rather than procedural routines. Strictly implements four core OOP pillars: Encapsulation, Inheritance, Polymorphism, and Data Abstraction.
  3. Platform-Independent & Architecture-Neutral: The compiler generates bytecode instructions whose format is independent of processor architectures and operating system ABIs. Any system equipped with a compatible JVM can execute the bytecode.
  4. Robust: Emphasizes compile-time type checking, explicit runtime exception handling, strict array bounds checking, and automatic garbage collection (GC) to prevent memory leaks and dangling pointers.
  5. Secure: Operates within a sandboxed virtual runtime environment. Bytecode verifiers ensure code does not violate memory access rules or forge pointers before execution.
  6. Distributed: Designed for internet networking, featuring native TCP/IP networking libraries, Remote Method Invocation (RMI), and distributed enterprise primitives.
  7. Multithreaded: Built-in language-level primitives for concurrent programming (e.g., the Thread class, Runnable interface, synchronized keyword, and Java Memory Model guarantees).
  8. Dynamic: Adapts dynamically to evolving execution environments by loading classes on-demand at runtime.
  9. High Performance: Employs Just-In-Time (JIT) compilers and adaptive optimization (HotSpot technology) to compile frequently executed bytecode sequences into native machine instructions at runtime.

2. The Java Virtual Environment Architecture: JDK, JRE, and JVM

Understanding Java's software development and execution ecosystem requires distinguishing three nested components:

CODE
+-------------------------------------------------------------------------------------------------+
|                                 JDK, JRE, and JVM Relationship                                  |
+-------------------------------------------------------------------------------------------------+
|  Java Development Kit (JDK)                                                                     |
|  +-------------------------------------------------------------------------------------------+  |
|  | Development Tools: `javac` (compiler), `javadoc`, `jar`, `jdb` (debugger), `jconsole`     |  |
|  |                                                                                           |  |
|  |  Java Runtime Environment (JRE)                                                           |  |
|  |  +-------------------------------------------------------------------------------------+  |  |
|  |  | Core Class Libraries: `rt.jar` (java.lang, java.util, java.io, java.net)              |  |  |
|  |  | Integration Libraries, Configuration Files                                             |  |  |
|  |  |                                                                                     |  |  |
|  |  |  Java Virtual Machine (JVM)                                                         |  |  |
|  |  |  +-------------------------------------------------------------------------------+  |  |  |
|  |  |  | ClassLoader Subsystem | Runtime Data Areas (Heap, Stack, Metaspace)            |  |  |  |
|  |  |  | Execution Engine (JIT, Interpreter, GC) | JNI Native Method Interface         |  |  |  |
|  |  |  +-------------------------------------------------------------------------------+  |  |  |
|  |  +-------------------------------------------------------------------------------------+  |  |
|  +-------------------------------------------------------------------------------------------+  |
+-------------------------------------------------------------------------------------------------+
  • JVM (Java Virtual Machine): An abstract computing machine defined by a strict specification. It executes compiled Java bytecode. While bytecode is platform-independent, JVM implementations are platform-dependent (distinct native executables for Windows, Linux, macOS).
  • JRE (Java Runtime Environment): The physical bundle containing the JVM implementation alongside core runtime class libraries (java.lang, java.util, etc.) and supporting files necessary to run compiled Java programs.
  • JDK (Java Development Kit): The complete software development package containing everything inside the JRE, plus compilation and profiling tools (javac, jar, jdb, javap) required to write and compile Java applications.

2.3 JVM Internal Subsystems

The JVM internal specification comprises five distinct architectural modules:

CODE
+-------------------------------------------------------------------------------------------------+
|                                   Detailed JVM Architecture                                     |
+-------------------------------------------------------------------------------------------------+
|                                                                                                 |
|   +-----------------------------------------------------------------------------------------+   |
|   |                                  ClassLoader Subsystem                                  |   |
|   |   Loading (Bootstrap, Platform, App) -> Linking (Verify, Prepare, Resolve) -> Initialize|   |
|   +-----------------------------------------------------------------------------------------+   |
|                                                |                                                |
|                                                v                                                |
|   +-----------------------------------------------------------------------------------------+   |
|   |                                   Runtime Data Areas                                    |   |
|   |  +------------------+  +------------------+  +------------------+  +------------------+ |   |
|   |  |  Method Area /   |  |    Heap Area     |  |    JVM Stack     |  |   PC Registers   | |   |
|   |  |    Metaspace     |  | (Objects, Arrays)|  | (Frames, Locals) |  | (Instr. Pointers)| |   |
|   |  +------------------+  +------------------+  +------------------+  +------------------+ |   |
|   |  | Native Method Stack (C/C++ native invocation frames)                                 | |   |
|   +-----------------------------------------------------------------------------------------+   |
|                                                |                                                |
|                                                v                                                |
|   +-----------------------------------------------------------------------------------------+   |
|   |                                     Execution Engine                                    |   |
|   |  +------------------+  +------------------+  +------------------+  +------------------+ |   |
|   |  |   Interpreter    |  |  JIT Compiler    |  |     HotSpot      |  | Garbage Collector| |   |
|   |  | (Bytecode line)  |  |  (C1 Client/C2)  |  |     Profiler     |  | (G1, ZGC, CMS)   | |   |
|   |  +------------------+  +------------------+  +------------------+  +------------------+ |   |
|   +-----------------------------------------------------------------------------------------+   |
|                                    |                        |                                   |
|                                    v                        v                                   |
|                 +--------------------+    +--------------------+                                |
|                 | JNI Native Interface|    | Native Libraries   |                                |
|                 +--------------------+    +--------------------+                                |
|                                                                                                 |
+-------------------------------------------------------------------------------------------------+

1. ClassLoader Subsystem

Loads, links, and initializes binary .class files using the Delegation-Hierarchy Principle:

  • Loading Phase:
    • Bootstrap ClassLoader: Loads fundamental JDK classes from rt.jar / java.base module (written in native C/C++).
    • Platform / Extension ClassLoader: Loads extensions from the runtime modular path.
    • Application / System ClassLoader: Loads user classes located in the system CLASSPATH.
    • Parent-Delegation Rule: When requested to load a class, a ClassLoader first delegates the request to its parent before attempting to load the class itself.
  • Linking Phase:
    • Verification: Validates that bytecode is structurally well-formed, adheres to JVM format constraints, and does not cause stack overflows or illegal pointer operations.
    • Preparation: Allocates memory for static variables and assigns default initial values (e.g., 0, null, false).
    • Resolution: Replaces symbolic references in the constant pool with direct memory pointers.
  • Initialization Phase: Executes static initialization blocks and assigns explicit initial values to static variables (<clinit>).

2. Runtime Data Areas

  • Method Area / Metaspace (Shared across all threads): Stores class-level data: runtime constant pool, field and method metadata, static variables, and method bytecode. Since Java 8, Metaspace resides in off-heap native memory.
  • Heap Area (Shared across all threads): The centralized runtime data area where all class instances (objects) and arrays are allocated. Managed automatically by the Garbage Collector.
  • JVM Stack (Per-thread): Created upon thread creation. Stores stack frames. Each stack frame contains Local Variable Arrays, Operand Stacks, and Frame Data (references to runtime constant pool).
  • Program Counter (PC) Register (Per-thread): Tracks the memory address of the JVM instruction currently being executed by that thread.
  • Native Method Stack (Per-thread): Allocates stack frames for native C/C++ methods invoked through the Java Native Interface (JNI).

3. Execution Engine

  • Interpreter: Reads bytecode instructions sequentially and interprets them into machine instructions. Fast startup, but slow execution for repeated loops.
  • Just-In-Time (JIT) Compiler: Identifies "hot spots" (frequently executed methods and loops). Compiles hot bytecode directly into optimized native machine code. Incorporates the C1 Client Compiler (quick compilation with basic optimization) and C2 Server Compiler (deep speculative optimization, method inlining, loop unrolling, and escape analysis).
  • Garbage Collector (GC): Automatically reclaims heap memory occupied by unreferenced, unreachable objects using tracing algorithms (e.g., G1, ZGC, Parallel GC).

3. Anatomy of a Java Application

A standard Java program follows strict structural conventions:

java
// Package Declaration (Must be first non-comment statement)
package com.university.cse;

// Import Statements
import java.util.Scanner;

// Class Definition (Must match filename if declared public: Application.java)
public class Application {

    // Main Method Entry Point
    public static void main(String[] args) {
        System.out.println("Execution Entry Point Initiated.");
    }
}

3.1 Detailed Deconstruction of public static void main(String[] args)

Every standard standalone Java application begins execution at this method signature. Each keyword serves an exact architectural purpose:

CODE
+-------------------------------------------------------------------------------------------------+
|                                 Signature Decomposition of `main`                               |
+-------------------------------------------------------------------------------------------------+
| Keyword        | Architectural Function                                                         |
+----------------+--------------------------------------------------------------------------------+
| `public`       | Access modifier that makes the method globally visible to the JVM runtime      |
|                | regardless of package boundaries.                                              |
| `static`       | Allows the JVM to invoke the method directly on the class (`Application.main`)|
|                | without instantiating an object of the class beforehand.                        |
| `void`         | Return type indicating that the method returns no value to the operating system|
|                | upon termination.                                                              |
| `main`         | Exact identifier searched by the JVM launcher as the application entry point.  |
| `String[] args`| Array of `java.lang.String` objects storing command-line arguments passed into|
|                | the application at launch time. Can also be written as `String... args`.       |
+----------------+--------------------------------------------------------------------------------+

3.2 Compilation and Execution Commands

  • Compilation: javac -d ./bin Application.java (invokes compiler, produces Application.class).
  • Execution: java -cp ./bin com.university.cse.Application arg1 arg2 (launches JVM, loads bytecode, executes main).
  • Disassembly: javap -c -v Application.class (disassembles compiled bytecode to inspect opcode sequences).

4. Java Type System, Variables, and Memory Representation

Java features a hybrid type system consisting of two primary categories: Primitive Types and Reference Types.

CODE
+-------------------------------------------------------------------------------------------------+
|                                     Java Type Hierarchy                                         |
+-------------------------------------------------------------------------------------------------+
|                                                                                                 |
|                                        Java Data Types                                          |
|                                        /             \                                          |
|                                       /               \                                         |
|                       Primitive Types                   Reference Types                         |
|                       /             \                   /       |       \                       |
|             Numeric Types         boolean            Classes  Arrays  Interfaces                |
|             /           \            (1-bit logical)    |                                       |
|      Integral         Floating-Point                 String, Object                             |
|      /  |   \   \         /        \                                                            |
|  byte short int long   float      double                                                        |
|  (1B)  (2B) (4B) (8B)   (4B)       (8B)                                                         |
|                                                                                                 |
+-------------------------------------------------------------------------------------------------+

4.1 Primitive Data Types

Java defines exactly eight primitive types, whose memory sizes and representations are fixed across all platforms:

CODE
+-------------------------------------------------------------------------------------------------+
|                                     Primitive Types Summary                                     |
+-------------------------------------------------------------------------------------------------+
| Type     | Size     | Wrapper Class | Range of Values                               | Default   |
+----------+----------+---------------+-----------------------------------------------+-----------+
| `byte`   | 8 bits   | `Byte`        | $-2^7$ to $2^7 - 1$ ($-128$ to $127$)         | `0`       |
| `short`  | 16 bits  | `Short`       | $-2^{15}$ to $2^{15} - 1$ ($-32,768$ to $32,767$)| `0`     |
| `int`    | 32 bits  | `Integer`     | $-2^{31}$ to $2^{31} - 1$ (approx $\pm 2.14 \times 10^9$)| `0`|
| `long`   | 64 bits  | `Long`        | $-2^{63}$ to $2^{63} - 1$ (suffix `L` required)| `0L`      |
| `float`  | 32 bits  | `Float`       | IEEE 754 single precision (suffix `f` required)| `0.0f`    |
| `double` | 64 bits  | `Double`      | IEEE 754 double precision (default float type)| `0.0d`    |
| `char`   | 16 bits  | `Character`   | $0$ to $2^{16} - 1$ (`\u0000` to `\uffff`, UTF-16)| `\u0000`|
| `boolean`| JVM-dep. | `Boolean`     | `true` or `false` (no numerical mapping in Java)| `false`   |
+----------+----------+---------------+-----------------------------------------------+-----------+

4.2 Variable Classifications and Scopes

Variables in Java are classified into three distinct categories based on lifetime, allocation location, and default initialization:

  1. Local Variables:
    • Declared inside methods, constructors, or code blocks.
    • Allocated directly on the JVM thread stack.
    • No default initialization: Must be explicitly initialized prior to first read access, or the compiler issues an error (variable might not have been initialized).
    • Destroyed as soon as the method or enclosing scope pops off the stack.
  2. Instance Variables (Non-Static Fields):
    • Declared inside a class body, outside any method or constructor.
    • Allocated on the Heap Area as part of an instantiated object.
    • Created upon new instantiation and destroyed by the Garbage Collector when unreachable.
    • Automatically initialized to default values (numbers →0\to 0, boolean →false\to \text{false}, references →null\to \text{null}).
  3. Class Variables (Static Fields):
    • Declared with the static keyword inside a class body.
    • Allocated in the Metaspace / Method Area when the class is loaded by the ClassLoader.
    • Exactly one shared copy exists across all instances of the class.

4.3 Type Conversion and Casting Mechanics

Java enforces strong typing. Conversions between numeric primitive types occur under strict rules:

CODE
+-------------------------------------------------------------------------------------------------+
|                                 Widening Primitive Conversion Path                              |
+-------------------------------------------------------------------------------------------------+
|                                                                                                 |
|   byte (1B) ---> short (2B) ---> int (4B) ---> long (8B) ---> float (4B) ---> double (8B)      |
|                   ^                                                                             |
|                   |                                                                             |
|   char (2B) ------+                                                                             |
|                                                                                                 |
|   --> Widening (Implicit/Automatic): Safe; no precision loss except potential LSB round on      |
|       int/long -> float.                                                                        |
|   <-- Narrowing (Explicit Cast Required): Risks bit truncation, sign inversion, and overflow.   |
|                                                                                                 |
+-------------------------------------------------------------------------------------------------+

Narrowing Cast Behavior and Binary Truncation

When narrowing a larger integer type to a smaller integer type (e.g., int to byte), Java discards all leading high-order bits and retains only the lowest NN bits:

java
int a = 130;
byte b = (byte) a; // b evaluates to -126

Binary Derivation:

  • 130130 in 32-bit two's complement binary: 00000000 00000000 00000000 10000010
  • Truncating to 8 bits: 10000010
  • The most significant bit is 1 (negative in two's complement).
  • Value: −(27)+21=−128+2=−126-(2^7) + 2^1 = -128 + 2 = -126.

5. Modifiers, Literals, and Wrapper Classes

5.1 Access and Non-Access Modifiers

CODE
+-------------------------------------------------------------------------------------------------+
|                                    Access Modifier Visibility                                   |
+-------------------------------------------------------------------------------------------------+
| Modifier             | Same Class | Same Package | Subclass (Outside) | World (Everywhere)      |
+----------------------+------------+--------------+--------------------+-------------------------+
| `private`            | Yes        | No           | No                 | No                      |
| default (no keyword) | Yes        | Yes          | No                 | No                      |
| `protected`          | Yes        | Yes          | Yes (via inherit)  | No                      |
| `public`             | Yes        | Yes          | Yes                | Yes                     |
+----------------------+------------+--------------+--------------------+-------------------------+

Non-Access Modifiers

  • static: Denotes class-level ownership rather than instance-level membership.
  • final: Applied to variables (constant; cannot be reassigned), methods (cannot be overridden), or classes (cannot be subclassed).
  • abstract: Declares incomplete signatures requiring concrete subclass implementation.
  • volatile: Guarantees thread visibility by forcing reads and writes directly from/to main memory rather than thread-local CPU caches.
  • transient: Directs the serialization engine to ignore this field during object serialization.

5.2 Numeric Literals and Underscore Formatting

Java supports diverse literal representations:

  • Integer Literals: Decimal (100), Octal prefix 0 (012 →10\to 10), Hexadecimal prefix 0x or 0X (0x1F →31\to 31), Binary prefix 0b or 0B (0b1010 →10\to 10).
  • Underscores in Literals (Java 7+): Improve code readability without affecting the evaluated numerical value:
    java
    long creditCardNumber = 1234_5678_9012_3456L;
    int hexBytes = 0xFF_EC_DE_5E;
    

5.3 Wrapper Classes and Autoboxing Mechanics

Wrapper classes encapsulate primitive data types inside heap-allocated reference objects:

java
// Autoboxing: Automatic conversion of primitive to wrapper object
Integer boxed = 42; // Equivalent to: Integer.valueOf(42)

// Unboxing: Automatic extraction of primitive from wrapper object
int primitive = boxed; // Equivalent to: boxed.intValue()

The Flyweight Pattern and Integer Cache

To optimize memory usage, Java implements an object caching mechanism for Byte, Short, Integer, Long, Character, and Boolean.
For java.lang.Integer, Integer.valueOf(int) caches objects within the range −128-128 to 127127 (inclusive):

java
Integer x = 127;
Integer y = 127;
System.out.println(x == y); // true (points to identical cached object in memory)

Integer p = 128;
Integer q = 128;
System.out.println(p == q); // false (allocates distinct heap objects!)
System.out.println(p.equals(q)); // true (compares internal primitive values)

6. Operators and Evaluation Semantics

Java provides operators for arithmetic, bitwise manipulation, comparison, and logical evaluation.

6.1 Short-Circuit vs. Bitwise Logical Operators

Java distinguishes between short-circuit logical operators (&&, ||) and eager bitwise/logical operators (&, |):

java
int count = 0;
// Short-Circuit AND (&&): Left operand evaluates to false; right operand is NEVER evaluated!
if (false && (++count > 0)) { /* Unreachable */ }
System.out.println(count); // Prints: 0

// Non-Short-Circuit / Bitwise AND (&): BOTH operands are ALWAYS evaluated!
if (false & (++count > 0)) { /* Unreachable */ }
System.out.println(count); // Prints: 1

6.2 Bitwise Shift Operators

Java implements three bitwise shift operators:

  1. Left Shift (<<): a≪na \ll n shifts bits to the left by nn positions, filling vacated low-order bits with zeros. Equivalent to multiplying by 2n2^n (ignoring overflow).
  2. Signed (Arithmetic) Right Shift (>>): a≫na \gg n shifts bits to the right, preserving the sign bit (copies the sign bit into vacated high-order positions). Equivalent to dividing by 2n2^n.
  3. Unsigned (Logical) Right Shift (>>>): a⋙na \ggg n shifts bits to the right, filling vacated high-order positions with zeros regardless of whether the original number was positive or negative.
java
int val = -8;
System.out.println(val >> 1);  // -4 (Sign preserved)
System.out.println(val >>> 1); // 2147483644 (Zero fill; turns into large positive integer!)

6.3 Operator Precedence and Associativity Summary

CODE
+-------------------------------------------------------------------------------------------------+
|                                  Operator Precedence Hierarchy                                  |
+-------------------------------------------------------------------------------------------------+
| Category               | Operators                                      | Associativity         |
+------------------------+------------------------------------------------+-----------------------+
| Postfix                | `expr++`, `expr--`                             | Left to Right         |
| Unary                  | `++expr`, `--expr`, `+`, `-`, `~`, `!`         | Right to Left         |
| Multiplicative         | `*`, `/`, `%`                                  | Left to Right         |
| Additive               | `+`, `-`                                       | Left to Right         |
| Shift                  | `<<`, `>>`, `>>>`                              | Left to Right         |
| Relational             | `<`, `>`, `<=`, `>=`, `instanceof`             | Left to Right         |
| Equality               | `==`, `!=`                                     | Left to Right         |
| Bitwise AND            | `&`                                            | Left to Right         |
| Bitwise XOR            | `^`                                            | Left to Right         |
| Bitwise OR             | `|`                                            | Left to Right         |
| Logical AND            | `&&`                                           | Left to Right         |
| Logical OR             | `||`                                           | Left to Right         |
| Ternary Conditional    | `? :`                                          | Right to Left         |
| Assignment             | `=`, `+=`, `-=`, `*=`, `/=`, `%=`, `&=`, `|=`  | Right to Left         |
+------------------------+------------------------------------------------+-----------------------+

7. Control Flow Statements

7.1 Selection Statements: if-else and switch

Control flow branching directs execution trajectories based on boolean conditions.

The Classic switch Statement

Evaluates an expression against multiple case labels. Supported types:

  • byte, short, char, int (and their corresponding wrapper classes Byte, Short, Character, Integer).
  • java.lang.String (Java 7+).
  • Enumerated types (enum).
java
// Fall-through hazard without explicit `break`
switch (day) {
    case 1: System.out.println("Monday"); break;
    case 2: System.out.println("Tuesday"); break;
    default: System.out.println("Other day"); break;
}

Modern Enhanced switch Expressions (Java 14+)

Modern Java provides switch expressions using arrow syntax (->) that eliminate accidental fallthrough and allow returning values directly:

java
String season = switch (month) {
    case DECEMBER, JANUARY, FEBRUARY -> "Winter";
    case MARCH, APRIL, MAY           -> "Spring";
    case JUNE, JULY, AUGUST          -> "Summer";
    case SEPTEMBER, OCTOBER, NOVEMBER -> "Autumn";
    default -> {
        System.err.println("Invalid month provided");
        yield "Unknown";
    }
};

8. Summary Checklist of Foundational Java Rules

  1. WORA Architecture: .java source files compile to architecture-neutral .class bytecode; the platform-specific JVM translates bytecode to machine code via JIT and interpreter engines.
  2. Type Safety: Java enforces strict type conversions. Widening is implicit, while narrowing requires an explicit cast that truncates high-order bits.
  3. Memory Organization: Objects and arrays reside in the Heap; local variables and method call frames reside in the JVM Stack; class metadata and constants reside in Metaspace.
  4. Equality Evaluation: == checks reference identity (memory addresses) for reference types; .equals() checks logical value equivalence.