1.1 Program Structure, Primitives, Literals, Scopes, and var

Key Takeaways

  • A valid Java source file contains at most one top-level public class matching the source file name, with package declarations preceding import statements.
  • Java defines eight primitive types with fixed bit-widths, where class and instance fields receive implicit default values but local variables require definite assignment before reading.
  • Numeric literals allow underscore separators between digits for readability, while octal (leading 0), binary (0b/0B), and hexadecimal (0x/0X) prefixes specify non-decimal radixes.
  • Local Variable Type Inference (var) determines static compile-time types exclusively for initialized local variables, loop counters, and resource declarations, but cannot be used for fields, uninitialized variables, method parameters, or method return types.
Last updated: September 2026

Program Structure, Primitives, Literals, Scopes, and var

Mastering foundational syntax, type representations, and variable lifetimes is essential for the Oracle Certified Professional: Java SE 21 Developer (1Z0-830) examination. The compiler enforces strict rules regarding source file organization, primitive conversions, definite assignment, and type inference.


1. Java Source File Structure & Package Conventions

A Java source code file (.java) follows a strict ordering of top-level structural elements:

  1. Package Declaration (package ...;): Optional. If present, it must be the first non-comment token in the source file. Only one package declaration is allowed per file.
  2. Import Statements (import ...; or import static ...;): Optional. Must appear after the package declaration and before any type declarations.
  3. Type Declarations (class, interface, enum, record): Zero or more top-level declarations.
+-------------------------------------------------------------------+
| // 1. Package Declaration (Single, must be first non-comment)    |
| package com.oracle.cert.basics;                                   |
|                                                                   |
| // 2. Import Statements (Static and single/on-demand imports)    |
| import java.util.List;                                            |
| import static java.lang.Math.PI;                                  |
|                                                                   |
| // 3. Top-Level Type Declarations                                 |
| public class ApplicationLauncher { /* ... */ }                    |
| class HelperUtility { /* Package-private helper */ }              |
+-------------------------------------------------------------------+

Top-Level Class Constraints

  • Public Class Limit: A .java file can contain at most one public top-level class (or interface, enum, record). If a public type exists, the source file name must match the name of that public type exactly (case-sensitive), appending .java.
  • Multiple Non-Public Classes: A source file can declare multiple package-private (default access) top-level types. If there is no public top-level class, the source file name does not need to match any of the internal types.
  • Single-File Source-Code Launcher: Java supports running a source file directly via java SourceFile.java without explicit compilation (javac). In single-file execution mode, the first top-level class declared in the source file must contain the entry-point main method, regardless of class names.

Import Statement Mechanics & Conflicts

  • Single-Type Import: import java.util.Date; imports a specific type. Takes precedence over on-demand imports.
  • Type-Import-on-Demand (Wildcard): import java.util.*; imports all public types in java.util, but does not import subpackages (e.g., java.util.concurrent.* is not imported).
  • Static Imports: import static java.lang.Math.sqrt; or import static java.util.Collections.*; imports static members directly into lexical scope.
  • Naming Collisions: If two single-type imports import types with the same simple name (e.g., import java.util.Date; and import java.sql.Date;), the compiler generates an error. If one is imported via wildcard and the other via single-type import, the single-type import wins. If both are imported via wildcards, referencing the ambiguous simple name (Date) causes a compile-time error, requiring the fully qualified class name (java.util.Date).
package com.exam.structure;

import java.util.Date;        // Explicit single-type import
import java.sql.*;            // Wildcard import contains java.sql.Date
import static java.lang.Math.*; // Static wildcard import

public class ImportRules {
    public static void main(String[] args) {
        Date d = new Date();  // Resolves cleanly to java.util.Date
        java.sql.Date sqlDate = new java.sql.Date(1000L); // Fully qualified
        double val = sqrt(25.0); // Resolves to Math.sqrt
    }
}

The Application Entry Point (main Method)

The standard executable entry-point signature requires:

public static void main(String[] args)
  • public: Accessible to the JVM runtime from any package.
  • static: Invoked without instantiating the declaring class.
  • void: Does not return an exit code (System.exit() can be used for non-zero statuses).
  • Parameter: Array of String (String[] args, String args[], or varargs String... args).
  • Modifiers final, synchronized, or strictfp are legal on main, but abstract or private prevent it from functioning as the application entry point.

2. Java Primitive Data Types

Java provides eight primitive data types. Every primitive has a fixed bit-width and range across all platforms and operating systems.

PrimitiveCategoryBit WidthRange / FormatDefault (Field)Wrapper Class
byteSigned Integer8-bit$-128$ to $127$ ($-2^7$ to $2^7-1$)0java.lang.Byte
shortSigned Integer16-bit$-32,768$ to $32,767$ ($-2^{15}$ to $2^{15}-1$)0java.lang.Short
intSigned Integer32-bit$-2,147,483,648$ to $2,147,483,647$ ($-2^{31}$ to $2^{31}-1$)0java.lang.Integer
longSigned Integer64-bit$-2^{63}$ to $2^{63}-1$ (Suffix: L or l)0Ljava.lang.Long
floatIEEE 754 Floating32-bit$\approx \pm 1.4\times 10^{-45}$ to $\pm 3.4\times 10^{38}$ (Suffix: F or f)0.0fjava.lang.Float
doubleIEEE 754 Floating64-bit$\approx \pm 4.9\times 10^{-324}$ to $\pm 1.7\times 10^{308}$ (Default float, optional D/d)0.0djava.lang.Double
charUnsigned Unicode16-bit\u0000 ($0$) to \uffff ($65,535$)\u0000 (NUL)java.lang.Character
booleanLogical TruthJVM-dependenttrue or false (Not convertible to/from integers)falsejava.lang.Boolean

[!NOTE] Unlike C/C++, Java booleans cannot be cast or assigned to numeric values (0 or 1). Doing if (1) or boolean b = (boolean) 0; causes a compile-time error.


3. Literals, Numeric Systems, and Underscore Rules

Numeric Bases

  • Decimal (Base 10): Standard numbers without prefixes (e.g., 42, 1000).
  • Hexadecimal (Base 16): Prefix 0x or 0X. Digits 0-9 and letters A-F / a-f (e.g., 0xFF = 255, 0x1A = 26).
  • Octal (Base 8): Prefix 0 (zero) followed by digits 0-7. Digits 8 or 9 cause a compiler error. Example: 017 is $1\times 8^1 + 7\times 8^0 = 15$.
  • Binary (Base 2): Prefix 0b or 0B followed by digits 0 or 1 (e.g., 0b1010 = 10).
int dec = 26;     // Decimal 26
int hex = 0x1A;   // Hexadecimal 26
int oct = 032;    // Octal 26 (3 * 8 + 2)
int bin = 0b11010;// Binary 26
// All variables equal 26

Underscores in Numeric Literals (SE 7+)

Underscores (_) can be placed between digits to improve readability. However, underscores are strictly forbidden at boundary locations:

  • At the very beginning or end of a literal (_52, 52_ -> Error).
  • Adjacent to a decimal point (3._14, 3_.14 -> Error).
  • Prior to an L, F, or D suffix (45_L, 3.14_f -> Error).
  • In the prefix positions (0_x52, 0x_52, 0_b101, 0b_101 -> Error).
// Valid Literals
int million = 1_000_000;
long creditCard = 4532_1100_9876_4321L;
float pi = 3.14_15F;
double hexDouble = 0x1.0p-3; // Hexadecimal floating-point

// Invalid Literals (Compile Errors)
// int bad1 = _100;     // Underscore at start
// int bad2 = 100_;     // Underscore at end
// double bad3 = 100_.0;// Underscore before decimal
// double bad4 = 100._0;// Underscore after decimal
// long bad5 = 100_L;   // Underscore before suffix L
// int bad6 = 0x_FF;    // Underscore after radix prefix

4. Variable Scopes, Shadowing, and Definite Assignment

Variables in Java fall into four primary scoping tiers:

+---------------------------------------------------------------------+
| Static (Class) Variables                                            |
| - Scope: Entire class lifecycle; exists once per loaded class.      |
| - Default values: Initialized automatically upon class loading.     |
+---------------------------------------------------------------------+
   |--> Instance (Member) Fields
        - Scope: Lifetime of the enclosing object instance.
        - Default values: Initialized automatically during constructor call.
        +-------------------------------------------------------------+
           |--> Method Local Variables
                - Scope: From declaration point to end of enclosing block.
                - Definite Assignment: NO default value; compiler checks.
                +-----------------------------------------------------+
                   |--> Block & Loop Variables
                        - Scope: Strictly within loop or statement block.

Definite Assignment Rules for Local Variables

Local variables (variables declared inside methods, constructors, or initializers) do not receive default values. The Java compiler performs Definite Assignment Analysis. Reading a local variable before ensuring an assignment on every possible execution path causes a compile-time error:

public class DefiniteAssignmentDemo {
    public void compute(boolean condition) {
        int x;
        if (condition) {
            x = 10;
        } else {
            x = 20;
        }
        System.out.println(x); // Legal: x is assigned in both branches

        int y;
        if (condition) {
            y = 50;
        }
        // System.out.println(y); // COMPILE ERROR: y might not have been initialized
    }
}

Shadowing vs. Illegal Redeclaration

  • Field Shadowing: A local variable is permitted to have the same identifier as an instance or static field. The local variable shadows the field. Accessing the field requires this.fieldName or ClassName.fieldName.
  • Block Scope Redeclaration: Declaring a local variable with the same identifier as an existing local variable within the same method or an enclosed nested block is a compile-time error.
public class ScopeTrap {
    private int count = 100; // Instance field

    public void process() {
        int count = 10;      // Legal: Shadows instance field 'count'
        System.out.println(count);      // Prints 10
        System.out.println(this.count); // Prints 100

        {
            // int count = 5; // COMPILE ERROR: Variable 'count' already defined in scope
            int inner = 42;
        }
        int inner = 99; // Legal: Previous 'inner' went out of scope at closing brace
    }
}

5. Local Variable Type Inference (var)

Introduced in Java 10 (JEP 286) and refined in subsequent releases, var enables compiler type inference for local variables, reducing boilerplate while retaining strict static typing.

Where var IS Permitted

  1. Local variable declarations with initializers inside methods, constructors, and initialization blocks.
  2. Enhanced for loops (for (var item : collection)).
  3. Traditional for loops (for (var i = 0; i < 10; i++)).
  4. Try-with-resources statements (try (var stream = Files.lines(path))).
  5. Lambda formal parameters (Java 11+: (var x, var y) -> x + y), provided var is applied to all or none of the parameters.

Where var IS NOT Permitted (Compile-Time Errors)

  • Instance or Static Member Fields: public var count = 10; (Illegal).
  • Method Parameters: public void test(var a) (Illegal).
  • Method Return Types: public var calculate() (Illegal).
  • Constructor Parameters: public Person(var name) (Illegal).
  • Catch Block Exception Parameters: catch (var ex) (Illegal).
  • Uninitialized Variables: var x; (Illegal - requires an initializer to infer type).
  • Initialized to Literal null: var x = null; (Illegal - null has no inferable type).
  • Array Initializers without explicit array type: var arr = {1, 2, 3}; (Illegal; must be var arr = new int[]{1, 2, 3};).
  • Multiple Variable Declarations: var a = 1, b = 2; (Illegal).
public class VarRules {
    // var field = 10; // ERROR: Not allowed for fields

    public void legalUsage() {
        var message = "Hello Java 21"; // Inferred as java.lang.String
        var list = List.of(1, 2, 3);    // Inferred as List<Integer>
        var arr = new int[]{10, 20};    // Inferred as int[]

        // Type is fixed at compile time (static typing)
        // message = 42; // COMPILE ERROR: Incompatible types (int cannot be converted to String)

        for (var i = 0; i < list.size(); i++) { /* ... */ }
        for (var num : list) { /* ... */ }
    }
}

var is a Reserved Type Name, Not a Keyword

Because var is a context-sensitive reserved type name, existing code using var as a variable, method, or package name remains fully valid. However, declaring a class, interface, enum, or record named var is illegal.

public class VarIdentifierDemo {
    public void var() {     // Legal: Method named var
        int var = 10;       // Legal: Variable named var
        var x = var;        // Legal: First var is type inference, second is variable
    }
}
// class var {} // COMPILE ERROR: 'var' is restricted identifier and cannot be class name
Loading diagram...
Primitive Bit Widths, Scopes, and Variable Lifecycle
Test Your Knowledge

Given the following variable declarations, which numeric literal declaration will compile without error?

A
B
C
D
Test Your Knowledge

Which of the following method declarations demonstrates a valid and legal use of the 'var' reserved type name in Java SE 21?

A
B
C
D
Test Your Knowledge

Consider the following Java class: public class ScopeChallenge { static int x = 10; int y = 20; public void test() { int x = 30; { int y = 40; System.out.print(x + y + ScopeChallenge.x + this.y + " "); } } public static void main(String[] args) { new ScopeChallenge().test(); } } What is the output when this program is executed?

A
B
C
D
Test Your Knowledge

Examine the following method: public int evaluate(int flag) { int result; switch (flag) { case 1 -> result = 100; case 2 -> result = 200; } return result; } What is the outcome of compiling and running this code?

A
B
C
D