How Arrays work differently in Java?

How Arrays work differently in Java?

Arrays lets you store multiple similar values under one name. They're efficient for accessing data, save memory space, and make code cleaner by organising related information into a single structure. Arrays also enable easy iteration and passing collections of data to functions.

How to declare an array?

dataType[] variableName = new dataType[size];

In Java, arrays are treated as objects, these are special kind of object that doesn't have a specific class . Instead, arrays in Java are instances of dynamically created classes, which are created by the Java Virtual Machine (JVM) at runtime. Let's understand it better,

We will explore the concepts of stack and heap in Java below to better understand their roles in memory management.

Stack and heap memory

Stack and heap are two different regions of memory used for different purposes:

When you create an array or an object using new in Java, suppose, int[] marks = new int[5];, the memory for that array is allocated in the heap.

However, the reference to that memory location (the object) is stored in the stack if marks is a local variable within a method.

Declaration: happens at compile time (in Stack)
Initialisation: happens at run time. (in heap)

Based on our understanding:

  1. Arrays in Java, being a special type of objects, are facilitated by the JVM. Objects, including arrays, reside in the heap.

  2. Java Language Specification (JLS), says heap objects aren't necessarily continuous.

The heap, responsible for dynamic memory allocation, is where memory for classes and array instances is obtained.

Hence, array objects in Java might not always be contiguous due to their allocation in the heap. It is actually an array of reference variable that is continuous.

You can explore more on this topic by heading to: Java: Are 1-D arrays always contiguous in memory?

Indices of array:

Indices start at 0 for the first element and increment by 1 for each subsequent element. In our array marks, myArray[0] refers to the first element, myArray[1] refers to the second element, and so on.

If an int[] is not initialised, its values default to 0, while for a String[], the default values are set to null.

null:

Null is a special literal or value that can not be assigned to primitive types (int, double, etc.) .

null is used to indicate that a reference type variable doesn't currently refer to any object, while primitive types like int cannot hold null as they store values directly.

User Input to Fill Array & Display Output:

Suppose we have an empty array named 'marks' our goal is to populate it by obtaining input from the user.

We can fill it up using a for loop

We're increasing i to systematically access each subsequent element in the marks array, beginning from marks[0] and then marks[1], marks[2], and onwards, enabling us to fill these array elements with user-provided input.

Similarly, we can use a for loop to show elements

Enhanced for loop (for-each loop):

The for-each loop makes it easy to traverse arrays and lists without worrying about index numbers. But, it can not be used for getting user input and storing it.

Syntax:

for (dataType refernceVariable : arrayName)

toString() method:

toString() method is available in all classes, including arrays, it displays entire array at once, which can be handy for debugging or displaying the entire array's content in one go.

In Java, when using prebuilt methods, there's a convention to follow: ClassName.methodName(variableName) (variable as argument is passed to the method).

How these things behave in function ?

In Java, only call by value is used. The reference variable holds the memory address or reference to the object in the heap. When a reference is passed to a method, it's the value of this reference (memory address) that gets copied, not the entire object itself.

This copied reference still points to the same object in memory.

so, original will also be changed.

2D array:

It is an 'array of arrays', creating a matrix-like structure where elements are organised in rows and columns.

Row is mandatory

arr is our 2D array, which contains the following elements:


int [][] arr = {
                {1,2,3},
                {4,5,6},
                {7,8,9}
                };

Accessing Specific Elements in a 2D Array:

Accessing elements in a 2D array involves using indices to pinpoint and retrieve values stored in rows and columns.

By specifying the row and column index, you can access particular elements within a 2D array.Let's look at the following example.

A 2D array is an array of arrays. When we declared and initialised a 2D array like int[][] arr = new int[3][2];, we are creating an array that contains three arrays (rows), and each of those arrays contains two elements (columns).

The length of the 2D array (arr.length) gives you the number of rows in the array. In this case, arr.length would be 3 because you've initialised the array to have three rows.

User Input to Fill 2D Array & Display Output:

The outer loop (for row) iterates over the rows ,It starts at i = 0. Inside the outer loop, there's another loop (for col) that iterates over the columns within each row.

It starts at col = 0 and continues until col reaches the number of columns (cols) present in each row.

each row can have a different number of columns. Using arr[row].length helps us know how many columns each row has.

int[][] arr = { {1, 2, 3}, // row 0 with 3 columns 

{4, 5}, // row 1 with 2 columns 

{6, 7, 8, 9} // row 2 with 4 columns 

};