Quick answer: declare the type with [], then either give the size with new or list the values in braces.

int[] scores;                          // declaration only
scores = new int[5];                   // allocate: {0, 0, 0, 0, 0}
int[] primes = {2, 3, 5, 7};           // declare + initialize in one line
String[] browsers = new String[]{"chrome", "firefox"};

Declare and Initialize an Array in Java: The Complete Guide

If you're learning Java, one of the very first hurdles you'll cross is understanding arrays — and more specifically, how to declare and initialize them correctly.

It sounds simple on the surface, but a surprising number of developers, even those with a few years of experience, still fumble the subtle differences between declaration, instantiation, and initialization.

This guide clears up every bit of that confusion.

By the end of this article, you'll know not just the syntax for declaring and initializing arrays in Java, but why that syntax works the way it does, what happens in memory when you run your code, which mistakes to avoid, and how to explain the concept confidently in an interview.


Advertisement

What Is an Array in Java?

An array in Java is a container object that holds a fixed number of values of a single data type.

Think of it as a labeled row of storage slots, where each slot has a position (called an index) starting at zero.

Once you decide how big an array should be, that size cannot change — arrays in Java are fixed-length by design. This is different from dynamic structures like ArrayList, which can grow and shrink at runtime.

Arrays are one of Java's oldest and most fundamental data structures. They exist at the language level (not just the library level), which means the compiler and JVM give them special treatment for performance.

Understanding arrays deeply pays off everywhere:

  • In interviews
  • In everyday coding
  • In understanding how higher-level collections like ArrayList work internally (since ArrayList is literally backed by an array)

Every array in Java has three defining characteristics:

  • A fixed size, determined either at compile time or at runtime, but never changed afterward.
  • A single data type, so an int[] can only hold integers, a String[] can only hold strings, and so on.
  • Zero-based indexing, meaning the first element sits at index 0 and the last element sits at index length - 1.

Declaring an Array in Java

Declaring an array simply tells the compiler:

"I intend to have a variable that will refer to an array of this type."

At the declaration stage, no actual array object exists yet in memory — you've only created a reference variable that currently points to nothing (technically, null).

Java allows two syntactic styles for declaring an array.

int[] numbers;   // Recommended style
int numbers[];   // Legal but discouraged style

Both lines compile and behave identically, but the first form — with the brackets attached to the type — is considered the idiomatic Java style.

It communicates clearly that "array of int" is the type of the variable, rather than looking like a strange variant of a primitive variable.

Style guides at Google, Oracle, and virtually every professional Java shop recommend the int[] numbers form.

You can declare arrays of any type — primitives or objects.

int[] scores;
double[] prices;
String[] names;
boolean[] flags;
Employee[] employees;   // Array of a custom object type

At this point, none of these variables reference an actual array yet.

Declaration is just a promise of a type; the array object itself is created separately during initialization.


Initializing an Array in Java

Initialization is the step where memory is actually allocated for the array and (optionally) filled with starting values.

Java offers a few distinct ways to do this, and picking the right one depends on whether you already know the values or just the size.

Method 1: Using the new Keyword With a Size

If you know how many elements you need but not their values yet, you can allocate the array with a specific size.

Java will fill it with default values automatically:

  • 0 for numeric types
  • false for boolean
  • null for objects and String
int[] numbers = new int[5];
// Creates an array of 5 ints,
// all initialized to 0 by default

Method 2: Using Array Literals

If you already know the values, you can use a literal (curly-brace) initializer.

int[] numbers = {10, 20, 30, 40, 50};

This shorthand only works at the point of declaration — you cannot use it to reassign an already-declared array (more on that in Common Mistakes).


Method 3: Using new With Explicit Values

This is a more verbose but sometimes necessary form, especially useful when passing an array literal as a method argument or returning one from a method.

int[] numbers = new int[]{10, 20, 30, 40, 50};

Method 4: Assigning Values Element by Element

You can also initialize an array one index at a time after declaring it with a size.

int[] numbers = new int[5];

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

This approach is common when values come from user input, a file, or a loop calculation rather than being known in advance.


Declaration and Initialization Together

In real-world code, developers almost always combine declaration and initialization into a single statement since it's cleaner and less error-prone.

public class ArrayInitialization {

    public static void main(String[] args) {

        int[] numbers = {10, 20, 30, 40, 50};

        for (int i = 0; i < numbers.length; i++) {
            System.out.println(numbers[i]);
        }
    }
}

This single line:

int[] numbers = {10, 20, 30, 40, 50};

does two jobs at once:

  • Declares the reference variable numbers.
  • Creates and fills a 5-element array in memory.

The array's size is implicitly determined by how many values you list — you never state 5 directly.


11 Ways to Initialize an Array in Java (with Output)

Besides new int[3] and {10, 20, 30}, Java has several helpers that save time in test code — filling an array with one value, generating values from the index, creating a range, copying, 2D arrays and var. All of them in one program:

import java.util.Arrays;
import java.util.stream.IntStream;

public class ArrayInitWays {
    public static void main(String[] args) {
        int[] a = new int[3];                                   // 1. size only -> default values
        int[] b = {10, 20, 30};                                 // 2. array literal
        int[] c = new int[]{10, 20, 30};                        // 3. new + values (needed when passing to a method)
        int[] d = new int[5];  Arrays.fill(d, 7);               // 4. same value everywhere
        int[] e = new int[5];  Arrays.setAll(e, i -> i * i);    // 5. value from the index
        int[] f = IntStream.rangeClosed(1, 5).toArray();        // 6. a range of numbers
        int[] g = Arrays.copyOf(b, 5);                          // 7. copy into a bigger array
        String[] h = new String[2];                             // 8. object arrays default to null
        int[][] grid = {{1, 2, 3}, {4, 5, 6}};                  // 9. 2D array
        int[][] jagged = new int[3][];  jagged[0] = new int[]{1}; jagged[1] = new int[]{1, 2}; jagged[2] = new int[]{1, 2, 3}; // 10. jagged
        var names = new String[]{"Selenium", "Playwright"};     // 11. var (Java 10+)

        System.out.println("1  " + Arrays.toString(a));
        System.out.println("2  " + Arrays.toString(b));
        System.out.println("3  " + Arrays.toString(c));
        System.out.println("4  " + Arrays.toString(d));
        System.out.println("5  " + Arrays.toString(e));
        System.out.println("6  " + Arrays.toString(f));
        System.out.println("7  " + Arrays.toString(g));
        System.out.println("8  " + Arrays.toString(h));
        System.out.println("9  " + Arrays.deepToString(grid));
        System.out.println("10 " + Arrays.deepToString(jagged));
        System.out.println("11 " + Arrays.toString(names) + " length=" + names.length);
        System.out.println("printing the array directly: " + (b.toString().startsWith("[I@") ? "[I@<hash>  (use Arrays.toString)" : b));
        try { System.out.println(b[3]); } catch (ArrayIndexOutOfBoundsException ex) { System.out.println("b[3] -> " + ex.getMessage()); }
    }
}

Output

1  [0, 0, 0]
2  [10, 20, 30]
3  [10, 20, 30]
4  [7, 7, 7, 7, 7]
5  [0, 1, 4, 9, 16]
6  [1, 2, 3, 4, 5]
7  [10, 20, 30, 0, 0]
8  [null, null]
9  [[1, 2, 3], [4, 5, 6]]
10 [[1], [1, 2], [1, 2, 3]]
11 [Selenium, Playwright] length=2
printing the array directly: [I@<hash>  (use Arrays.toString)
b[3] -> Index 3 out of bounds for length 3
WayUse it when
new int[n]You know the size, values come later (defaults: 0, 0.0, false, null)
{a, b, c}You know the values now — only allowed in the declaration line
new int[]{a, b}Assigning later or passing straight to a method
Arrays.fillEvery element gets the same value
Arrays.setAllEach value is calculated from its index
IntStream.rangeClosed(1, n).toArray()A sequence of numbers (test data, IDs)
Arrays.copyOfCopy, grow or shrink an existing array
int[][]Tables, grids, test-data rows from Excel

Watch out: int[] x; x = {1, 2}; does not compile (error: illegal start of expression) — the short {…} form only works where the array is declared. Use x = new int[]{1, 2}; instead.

Step-by-Step Code Walkthrough

Let's break the full example down piece by piece, the way you'd want to explain it in a code review or an interview.

Class Declaration

public class ArrayInitialization

Every runnable Java program needs to live inside a class because Java is a purely object-oriented language at the structural level.

The class name should describe what the program does.


The Main Method

public static void main(String[] args)

This is the JVM's designated entry point.

  • public makes it visible to the JVM launcher.
  • static means it can run without an object being created first.
  • void tells us it returns nothing.

Variable Declaration and Initialization

int[] numbers = {10, 20, 30, 40, 50};

Creates a reference variable numbers and points it at a freshly created array containing five integers.


The Loop

for (int i = 0; i < numbers.length; i++)

This is a classic indexed loop.

It:

  • Starts at 0 (the first valid index).
  • Continues while i is less than numbers.length (5 in this case).
  • Increments by 1 each pass.

Printing

System.out.println(numbers[i]);

Accesses the element at the current index and prints it.

Over five iterations, this prints:

10
20
30
40
50

each on its own line.


Internal Working: Heap vs Stack Memory

Understanding what happens under the hood is what separates developers who memorize syntax from developers who genuinely understand Java.

When you write:

int[] numbers = {10, 20, 30, 40, 50};

two separate memory events occur:

  1. The array object itself — the five contiguous integer slots — is created on the heap. This is true for all arrays in Java, regardless of whether they hold primitives or objects, because arrays are themselves objects.
  2. The reference variable numbers — which is really just a pointer to the array's location in the heap — lives on the stack, inside whichever method created it (here, main).

This distinction matters enormously in practice.

If you pass an array to a method, you're passing a copy of the reference, not a copy of the underlying data.

That means changes made to array elements inside a called method are visible to the caller after the method returns — a frequent source of both bugs and "aha" interview moments.

Memory Region What's Stored Example
Stack Reference variable numbers, loop variable i Pointer to heap address
Heap Actual array data: [10, 20, 30, 40, 50] Contiguous int slots

Real-Life Analogy

Picture a row of numbered lockers at a gym, numbered starting from 0 instead of 1.

Declaring the array is like reserving a row of lockers of a specific size — you know how many lockers you'll have, but they're all empty.

Initializing the array is like actually placing an item into each locker.

Once the lockers are built, you can't add a sixth locker to the row. If you need more storage, you have to build an entirely new row (a new array) and move everything over.


Best Practices

  • Prefer the int[] name declaration style over int name[] — it's the accepted Java convention and reads more naturally.
  • Initialize arrays at the point of declaration whenever the values are known ahead of time. It's more concise and less error-prone than assigning values one by one.
  • Use meaningful, plural variable names (prices, scores, usernames) so the array's purpose is obvious at a glance.
  • Use Arrays.toString() for quick debugging output instead of manually looping and printing.
  • Consider final for array references that shouldn't be reassigned to a different array object, even though the contents can still change.
  • Validate size inputs before creating arrays dynamically (for example, from user input) to avoid NegativeArraySizeException.

Common Mistakes

1. Trying to Use Array Literal Syntax After Declaration

This is illegal.

int[] numbers;

numbers = {10, 20, 30};   // Compile-time error

Instead, you must use:

numbers = new int[]{10, 20, 30};

if you're assigning values after the declaration line.


2. Confusing Declaration With Initialization

Declaring:

int[] numbers;

does not create an array.

It only creates a reference variable that points to null.

Attempting to access:

numbers[0];

before initialization throws a NullPointerException.


3. Forgetting Arrays Are Fixed-Size

Beginners often try to "add" another element to a full array.

Arrays cannot grow after creation.

Instead, you must:

  • Create a new larger array.
  • Copy the existing elements.
  • Add the new value.

Or simply use an ArrayList.


4. Off-by-One Errors

Remember:

An array of size n has valid indices from:

0 to n - 1

For example:

int[] arr = new int[5];

Valid indexes are:

0
1
2
3
4

Accessing:

arr[5];

throws an ArrayIndexOutOfBoundsException.


5. Mixing Primitive and Wrapper Types

For example, expecting:

int[]

to work wherever

Integer[]

is required.

Although related, primitive arrays and wrapper object arrays are different types.


Expert Tips

When declaring multiple arrays on one line, be careful.

int[] a, b;

declares two arrays.

Whereas:

int a[], b;

declares:

  • a → array
  • b → normal integer

This is another reason why int[] variable is the preferred style.


For debugging multi-dimensional arrays, use:

Arrays.deepToString()

instead of:

Arrays.toString()

If you need an immutable list backed by an array, use:

Arrays.asList(...)

Remember that it creates a fixed-size list, so methods like add() and remove() are not supported.


In Java 10+, you can use var for local array declarations.

var numbers = new int[]{1, 2, 3};

The compiler automatically infers the type.


Arrays vs ArrayList: Quick Comparison

Feature Array ArrayList
Size Fixed at creation Dynamic, grows and shrinks automatically
Data Types Primitives and objects Objects only (uses autoboxing for primitives)
Performance Slightly faster with less overhead Slightly slower due to internal resizing
Built-in Methods Minimal (length, Arrays utility methods) Rich API (add(), remove(), contains(), indexOf(), etc.)
Syntax Simplicity Very simple for fixed-size data Slightly more verbose but flexible
Best Use Case Known, fixed-size datasets Data whose size changes during runtime

Pros and Cons of Using Arrays

Pros

  • Extremely fast, low-overhead access by index (O(1)).
  • Works with both primitive types and objects, avoiding autoboxing overhead.
  • Simple syntax for fixed-size datasets.
  • Foundational knowledge for learning ArrayList, Vector, and other collections.

Cons

  • Fixed size — cannot grow or shrink after creation.
  • No built-in methods for searching, sorting, or resizing (must use the Arrays utility class).
  • Manual bounds checking is required, otherwise you'll encounter ArrayIndexOutOfBoundsException.
  • Less flexible than collections for generic programming.

Prove It With a TestNG Test

A good way to lock in these rules — and a common SDET interview follow-up — is to write tests that demonstrate them:

import java.util.Arrays;
import org.testng.Assert;
import org.testng.annotations.Test;

public class ArrayInitializationTest {

    @Test
    public void newArrayHoldsDefaultValues() {
        int[] numbers = new int[3];
        boolean[] flags = new boolean[2];
        String[] names = new String[2];
        Assert.assertEquals(numbers, new int[]{0, 0, 0});
        Assert.assertFalse(flags[0]);
        Assert.assertNull(names[0]);                  // object arrays start with null
    }

    @Test
    public void allThreeInitializationStylesAreEqual() {
        int[] literal = {10, 20, 30};
        int[] withNew = new int[]{10, 20, 30};
        int[] indexed = new int[3];
        indexed[0] = 10; indexed[1] = 20; indexed[2] = 30;
        Assert.assertEquals(withNew, literal);
        Assert.assertEquals(indexed, literal);
    }

    @Test
    public void assigningCopiesTheReferenceNotTheArray() {
        int[] original = {1, 2, 3};
        int[] sameArray = original;
        int[] realCopy = Arrays.copyOf(original, original.length);
        original[0] = 99;
        Assert.assertEquals(sameArray[0], 99);         // both names point to one array
        Assert.assertEquals(realCopy[0], 1);           // the copy is independent
        Assert.assertNotSame(realCopy, original);
    }

    @Test(expectedExceptions = ArrayIndexOutOfBoundsException.class)
    public void readingPastTheEndFails() {
        int[] arr = {10, 20, 30};
        int x = arr[3];
    }

    @Test(expectedExceptions = NegativeArraySizeException.class)
    public void negativeSizeFails() {
        int size = -1;                                 // e.g. a bad value from test data
        int[] arr = new int[size];
    }
}

Result:

PASS allThreeInitializationStylesAreEqual
PASS assigningCopiesTheReferenceNotTheArray
PASS negativeSizeFails -> NegativeArraySizeException
PASS newArrayHoldsDefaultValues
PASS readingPastTheEndFails -> ArrayIndexOutOfBoundsException
Total: 5, Passed: 5, Failed: 0

We compiled these tests with Java 21 and ran them with a minimal TestNG-compatible runner (the full TestNG library wasn't available in our environment); they use only standard TestNG annotations and Assert methods, so they run unchanged with mvn test in a TestNG project.

The third test shows the point interviewers most often probe: int[] sameArray = original; copies the reference, so changing one changes "both"; Arrays.copyOf() creates a separate array. Watch both variables point at the same heap object — and the copy get its own — in the Java Code Visualizer. More on TestNG: TestNG Interview Questions.

From Real Projects

My automation work has been in Java — Selenium WebDriver scripts with TestNG in Eclipse — and I use OOP concepts such as classes and objects, method overloading, overriding and constructors in page classes and utilities. Small programs like this one are the building blocks of real framework code: looping through data, comparing expected and actual values, and handling edge cases. On Canolog, the many forms and screens across sales, inventory, finance and service are where keeping page details in POM classes and reusable steps in a business library paid off. Remember that assigning one array to another copies the reference, not the values. Further reading: Find Maximum Element in Array in Java.


📚 Official documentation: Oracle Java Tutorials: Arrays · Java 21 API: java.util.Arrays

👉 See also: Find Minimum Element in an Array in Java

🧩 Java Array Programs — 1 of 43

← Previous: Sort Words Alphabetically Java

Next: Print All Elements of an Array in Java →

See every program in the Java coding programs index.

Multidimensional Arrays and the Arrays Utility Class

A two-dimensional array is an array of arrays, handy for grids and table-like test data:

int[][] grid = new int[3][4];                 // 3 rows, 4 columns, all 0
String[][] logins = {
    {"standard_user", "secret_sauce"},
    {"locked_out_user", "secret_sauce"}
};
System.out.println(logins[1][0]);             // locked_out_user
System.out.println(logins.length);            // 2 rows

int[][] jagged = new int[3][];                // rows can have different lengths
jagged[0] = new int[]{1};
jagged[1] = new int[]{1, 2, 3};

The java.util.Arrays class has the helpers you'll use most:

MethodWhat it does
Arrays.toString(a) / Arrays.deepToString(grid)Readable output for 1D / 2D arrays (printing an array directly shows only its type and hash)
Arrays.sort(a)Sorts in place
Arrays.binarySearch(a, key)Finds a value in a sorted array
Arrays.equals(a, b) / Arrays.deepEqualsCompares contents (== compares references)
Arrays.fill(a, v)Sets every element to one value
Arrays.copyOf(a, n) / copyOfRangeCopies, optionally resizing
Arrays.asList(...) / Arrays.stream(a)Fixed-size list view / stream for further processing

Frequently Asked Questions (FAQs)

1. What is the difference between declaring and initializing an array in Java?

Declaring an array creates a reference variable without allocating memory.

Initializing an array allocates memory on the heap and optionally fills it with values.


2. Can I declare an array without specifying its size?

Yes.

int[] numbers;

However, when using the new keyword, you must specify the size unless you're using an array literal.

int[] numbers = {1, 2, 3};

3. What are the default values of array elements in Java?

Data Type Default Value
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0
char '\u0000'
boolean false
Object / String null

4. Can I resize an array after it's created?

No.

Arrays are fixed-size.

To "resize" an array, create a new one and copy the elements using:

Arrays.copyOf()

or a manual loop.


Both compile successfully.

int[] numbers;
int numbers[];

However, the recommended Java style is:

int[] numbers;

6. What happens if I access an invalid index?

Java throws an:

ArrayIndexOutOfBoundsException

For example:

int[] arr = {10, 20, 30};

System.out.println(arr[3]);

Output:

Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException

7. Are arrays stored on the stack or heap?

The array object is always stored on the heap.

The reference variable that points to the array lives on the stack (when declared as a local variable).


8. Can an array store different data types?

No.

An array stores only one declared type.

However, an Object[] array can hold different object types, though this sacrifices type safety and is generally not recommended.


9. How do I initialize a 2D array?

Using an array literal:

int[][] matrix = {
    {1, 2},
    {3, 4}
};

Or by specifying dimensions:

int[][] matrix = new int[3][3];

10. When should I use ArrayList instead of an array?

Use an ArrayList whenever the number of elements isn't known in advance or may change during program execution.


11. Can an array size be zero or negative?

A size of zero is valid.

int[] arr = new int[0];

This creates an empty array.

A negative size throws:

NegativeArraySizeException

12. What does numbers.length return?

numbers.length returns the total number of elements the array was created with.

Example:

int[] numbers = {10, 20, 30};

System.out.println(numbers.length);

Output:

3

Note: length is a field, not a method, so do not use parentheses.

numbers.length      // Correct

numbers.length()    // Compile-time error

13. How do you initialize an array with the same value in Java?

Create the array, then call Arrays.fill(arr, value), for example int[] a = new int[10]; Arrays.fill(a, -1);. It sets every element in one call.


14. How do you declare an array of strings in Java?

String[] names = new String[3]; creates three null slots, while String[] names = {"Asha", "Ravi", "Meera"}; declares and fills it in one line.


15. What is the difference between int[] a and int a[] in Java?

Both declare an int array and compile to the same thing. int[] a is the preferred style because the type reads as "int array". The C-style int a[] is allowed but can confuse, as in int[] a, b; (two arrays) versus int a[], b; (one array and one int).


16. How do you print a 2D array in Java?

Use Arrays.deepToString(grid) for a one-line view, or nested for loops to print it row by row.