Pass by reference and pass by value java

Pass by reference and pass by value java

Variables give you the comfort that you do not have to know where your data is stored in your computers memory. You define a variable, make your calculations and pass the variable from one function to another, and your operating system automatically deals with where your data is physically located.
However, sometimes it is very useful to know what happens behind variables. Especially in lower-level languages (for example Assembler, or C in some circumstances), it is sometimes even necessary to know where a value is stored in memory. This article will explain how variables are passed around between functions, and specifically explains how it works in Java. In Java, there is a slight but important difference of passing by value and passing by reference.

This article will use a simplified syntax in the code examples, since the theory of passing values is applicable to most programming languages.

Passing a variable

The term “passing a variable” is used when a function is called with a variable you defined previously. Let’s look at the following example:

The variable myAge is “passed” to the function calculateBirthYear. The function can then use that variable, for example:

There are two possibilities how you could have passed the variable myAge to the function. The terms “pass by value” and “pass by reference” are used to describe how variables are passed on. To make it short: pass by value means the actual value is passed on. Pass by reference means a number (called an address) is passed on which defines where the value is stored.

Читайте также:  Error fetching http headers soapfault php

How memory works

A basic knowledge of how memory works and how your variables are stored in memory will help to better understand this topic. Since an actual physical memory is hard to draw and different memory types look different (a hard disc vs. RAM for example), it is useful to have an abstract and simple way to imagine how memory looks like.

This article uses a simple and easily understandable approach to explain how values are stored in memory. For most uses (especially for programming beginners), it is enough to understand the concepts. However, once one gets experienced in programming, it is very useful to know more about different memory types and memory regions (harddrives, RAM, heap, stack, etc.).

How memory works

To make it simple, lets think of memory as many blocks which are next to each other. Each block has a number (the memory address). If you define a variable in your code, the value of the variable will be stored somewhere in the memory (your operating system will automatically decide where the best storage place is). The illustration on the right shows a part of some memory. The gray numbers on top of each block show the address of the block in memory, the colored numbers at the bottom show values which are stored in memory.

Taking the previous examples again, the variables myAge and month are defined in your code, and they will be stored in memory as shown in the illustration on the right. As example, the value of myAge is stored at the address 106 and the value of month is stored at the address 113.

Pass by value

Passing by value means that the value of the function parameter is copied into another location of your memory, and when accessing or modifying the variable within your function, only the copy is accessed/modified and the original value is left untouched. Passing by value is how your values are passed on most of the time.
The following example shows a variable passed by value:

Источник

Is Java Pass-By-Reference or Pass-By-Value?

A simple Google search of this question will return a straightforward answer that Java is always pass-by-value. The reason this question is confusing is because Java achieves its functionality using special variable types known as object references.

Before we continue, let’s briefly define the terms pass-by-reference and pass-by-value:

  • Pass-by-reference: When a method is called, the method arguments reference the same variable in memory as the caller.
  • Pass-by-value: When a method is called, the caller passes a copy of the argument variables to the method resulting in two values in memory.

Let’s look at these concepts more closely with the code snippet below:

public class Mug < private String contents; public Mug(String contents) < this.contents = contents; >public void setContents(String contents) < this.contents = contents; >public String getContents() < return contents; >> public class Run < public static void spill(Mug myMug) < myMug.setContents("nothing"); >public static void main(String args[]) < Mug myMug = new Mug("tea"); // myMug contains "tea" System.out.println(myMug.getContents()); spill(myMug); // myMug now contains "nothing" System.out.println(myMug.getContents()); >>

In example above, the contents of the Mug object are manipulated in a way that is functionally very similar to a native pass-by-reference system. However, there is a key difference that is explained by the mechanism of storing non-primitive variable types in Java.

Primitive types in Java, such as char , int , and boolean , are passed-by-value in the purest sense of the term.

Consider the code snippet below:

public class Run < public static void main(String args[])< int foo = 13; System.out.println(foo); // this will print "1" setFoo(foo); System.out.println(foo); // this will still print "1" >public static void setFoo(int bar) < bar = 2; >>

When the primitive int type foo is passed, it results in two separate int variables on the stack, foo and bar , like this:

Showing two Stacks, the first where the variable foo is pointing to bar showing it copied the value. The second shows bar being updated but foo remaining unchanged.

  1. Calling setFoo() will create a copy of foo ’s value inside the variable bar and place this on the stack.
  2. Then, setFoo() updates bestNum ’s value to 2 without modifying foo ’s value.

Non-primitive types in Java – that is, objects – are accessed by object references. An object reference is a unique identifier that tells the compiler where to find the referenced object in heap memory. This reference is stored as a value on the stack, to which a variable name is assigned. For every instance of an object that is created, a new reference value is stored on the stack and a new object is created in the heap.

To explain this, let’s return to our Mug example.

(1) public class Mug < (2) (3) private String contents; (4) (5) public Mug(String contents) < (6) this.contents = contents; (7) >(8) (9) public void setContents(String contents) < (10) this.contents = contents; (11) >(12) (13) public String getContents() < (14) return contents; (15) >(16) > (17) (18) public class Run < (19) (20) public static void spill(Mug mugToBeSpilled) < (21) mugToBeSpilled.setContents("Nothing"); (22) >(23) (24) public static void main(String args[]) < (25) Mug myMug = new Mug("Tea"); // myMug contains "Tea". (26) System.out.println(myMug.getContents()); (27) (28) spill(myMug); // myMug now contains "Nothing". (29) System.out.println(myMug.getContents()); (30) (31) >(32) >

The following diagrams show the behavior of the object in memory during the various manipulations in the code above. This should help illustrate the differences in how Java passes object references by value and a native pass-by-reference system.

Showing the Stack with a pointer to the actual Mug object on the Heap

First, we create an instance of the object Mug called myMug , and set the attribute contents to «Tea» . This object is created on the heap and the variable myMug is given a reference value on the stack. This object reference on the stack points to the object on the heap.

Showing two items on the Stack, one pointing to the other and both pointing to the single Mug object on the Heap

When the spill() method is called, the parameter mugToBeSpilled will get a copy of the object reference variable myMug passed-by-value. Then the contents attribute of both Mug objects change to «Nothing» . Functionally, this is similar to passing myMug by reference. However, the key difference is that we have two copies of the reference type value on the stack.

Modern programming languages, such as Java, rarely use a true pass-by-reference system. However, with the use of reference type variables, the end result for the developer is very much the same. The main difference is that a few more instances of reference type variables are created on the stack.

More information on the topic:

Further reading about heap space and stack memory in Java:

Источник

Оцените статью