skip to content

What are the default values of primitive fields, and when do defaults apply versus when must you initialize?

level: juniorimportance: must knowfreq 55%

answer

  1. Fields auto-default: numbers 0, char '', boolean false
  2. Local variables get NO default -> compile error if read first
  3. Array elements default like fields (0 / false / '')
  4. Primitives never null; wrapper fields (Integer) default to null -> NPE risk
  5. 'definite assignment' is a compile-time check

basics

~10 s

Uninitialized primitive fields get defaults: 0 for numbers, 0.0 for float/double, '' for char, false for boolean. Local variables get NO default — you must assign before use or the code won't compile.

solid answer

~40 s

Primitive instance and static fields are automatically initialized to a 'zero' default if you don't assign one: numeric types (byte, short, int, long) to 0, float to 0.0f, double to 0.0, char to '' (numeric 0), and boolean to false. Array elements get the same defaults when the array is allocated. The crucial exception is **local variables** (declared inside a method): they receive *no* default, and the compiler enforces 'definite assignment' — reading one before it is assigned is a compile error, not a runtime surprise. This is a deliberate safety feature. Primitives can never be null, so unlike reference types there is no NullPointerException risk from an uninitialized primitive field; instead you risk silently using a 0 or false you didn't intend.

code

java · 16 lines
java
class Box {
    int n;          // -> 0
    double d;       // -> 0.0
    boolean flag;   // -> false
    char c;         // -> ''
}

void demo() {
    int local;
    // System.out.println(local); // COMPILE ERROR: might not be initialized
    local = 5;
    System.out.println(local);    // 5

    int[] arr = new int[3];
    System.out.println(arr[0]);   // 0 (array elements get field-style defaults)
}

go deeper

for a junior

Knows the default-value table and that local variables must be initialized before use.

for a middle

Explains definite-assignment analysis, that array elements default like fields, and the int-vs-Integer null distinction.

for a senior

Articulates why the field/local distinction exists, blank-final rules, and the NPE risk from auto-unboxing null wrappers.

for a principal

Sets conventions to avoid silent-default bugs (e.g. preferring explicit initialization, validating constructed state) and reasons about null-safety strategy across primitive/wrapper boundaries.

## Two categories of variables Where a variable lives determines whether it gets a default value: 1. **Fields** — variables declared directly in a class. These are *instance fields* (one per object) or *static fields* (one per class). Also array elements. 2. **Local variables** — variables declared inside a method, constructor, or block. ## Field defaults (automatic) When an object is created (or a class is loaded, for static fields), the JVM **zero-initializes** every field before any constructor code runs. Each primitive gets its 'zero' value: | Type | Default | |------|---------| | byte, short, int, long | 0 | | float | 0.0f | | double | 0.0 | | char | '' (numeric 0) | | boolean | false | (Reference-type fields default to `null`, but that is a separate family.) **Array elements** follow the same table: `new int[3]` is `{0,0,0}`, `new boolean[2]` is `{false,false}`. So this compiles and prints `0` and `false`: ```java class Counter { int count; // default 0 boolean active; // default false } ``` ## Local variables: NO default Local variables are the important exception. They are **not** auto-initialized. Instead the Java compiler performs **definite assignment analysis**: it proves that every local variable is assigned a value on *every* path before it is read. If it cannot prove that, the program **fails to compile**: ```java int x; System.out.println(x); // COMPILE ERROR: variable x might not have been initialized ``` This is a deliberate design choice — it turns a whole class of 'used uninitialized memory' bugs (common in C) into compile-time errors. ## Why this distinction matters - **Fields** can be safely read immediately because their default is guaranteed. The risk is *semantic*: a forgotten initialization silently leaves a 0 or false that the program treats as meaningful (e.g. a price of 0). - **Locals** force you to be explicit, catching the mistake at compile time. - Because primitives are never `null`, an uninitialized primitive field never throws `NullPointerException` — but a *boxed* wrapper field (`Integer`, `Boolean`) defaults to `null` and *will* NPE if auto-unboxed. That is a frequent real bug: `Integer count;` defaults to null, and `int n = count;` throws NPE. ## blank finals A `final` field with no initializer (a 'blank final') does **not** get the zero default treatment for the purpose of the rules — it must be definitely assigned exactly once in every constructor, or the class won't compile.

  • What is the default of an Integer field versus an int field?
    An int field defaults to 0; an Integer field (a wrapper reference type) defaults to null, which will throw NullPointerException if auto-unboxed into an int.
  • Why are local variables treated differently from fields?
    The compiler enforces definite assignment for locals to catch use-before-assign bugs at compile time; fields are zero-initialized by the JVM because they can be touched from many places and a guaranteed default is safer.

saying these in an interview costs you the question

  • Thinking local variables default to 0 like fields (they don't — it's a compile error)
  • Saying an uninitialized int field is null (primitives are never null; it's 0)
  • Confusing an int field (defaults 0) with an Integer field (defaults null, can NPE on unboxing)
  • Assuming array elements are uninitialized garbage like in C

context