Jump to content
Frequently Asked Questions
  • Are you not able to open the client? Try following our getting started guide
  • Still not working? Try downloading and running JarFix
  • Help! My bot doesn't do anything! Enable fresh start in client settings and restart the client
  • How to purchase with PayPal/OSRS/Crypto gold? You can purchase vouchers from other users
  • Java - Pass By Value


    Explicit

    Recommended Posts

    I wrote this awhile ago on another site but I figured I'd post it here as well.

     

    I feel like this is a common issue among people who are just learning the language, and took me awhile to fully grasp the underlying concept. If you want to even begin understanding this you're going to need to know about two areas of memory, the stack and the heap. To start off, let's have a quick look at what happens in memory when we define variables in Java.

     

    When we start our Java program, the system automatically allocates a chunk of RAM (if you don't know what this is just think of it as memory) for the JVM to use. Two categories contained inside of that memory are called the stack and the heap. You should be familiar with them if you're an experienced Java developer, but if not here's a quick definition of both (and a nice little picture to go along with it):

    1. Stack - Used for storing variables/commands
    2. Heap - Area of memory which holds data about reference type objects

    ccc8a541aff7fe0363b2f78a0e3d8780.png

     

    Now were going to create a basic Java class with a main method, followed by a simple primitive variable declaration:

    public class Learning {
    
        public static void main(String... args) {
            int exampleInt = 5;
        }
    
    } 

    What happened to the Stack/Heap? As the stack holds the variable values, we are going to push (I will be using common stack terminology in this tutorial so if you're unfamiliar with it a quick Google search will do you wonders) the initialized variable exampleInt onto the stack (the JVM will allocate the appropriate memory to hold the variable value) with the value of 5:

     

    92079dfec17d53fb9dc7187a0f651c13.png

     

    Easy enough right? Now to give an example of what happens when I create an object, let's first make a simple class called Person with a field called name:

    public class Person {
    
        private String name;
    
        public Person(String name) {
            this.name = name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
    }

    Create a simple Person object with the name of Bob, and the JVM will create the necessary memory location for our new Person object:

    public class Learning {
    
        public static void main(String... args) {
            int exampleInt = 5;
            Person bob = new Person("Bob");
        }
    
    }

    5cd55edeb8d799ce8780737a20e08f56.png

     

    Wait, didn't you just say variables were initialized and placed on the stack? Yes they are, however when it comes to reference types the only thing created on the stack is a variable with a pointer to the object that is created on the heap (in this case if you can read it it's 709F) with a bunch of meta data among other things were not going to worry about right now. Now that we finished covering the absolute basics of what's going on under the hood when we make variables, let's take a look at how this applies to passing variables to methods.

     

    Let's create a method which takes our exampleInt and attempts to change the value:

    public class Learning {
    
        public static void main(String... args) {
            int exampleInt = 5;
            attemptToChange(exampleInt);
            System.out.println(exampleInt);
        }
    
        public static void attemptToChange(int testInt) {
            testInt = 10;
            System.out.println(testInt);
        }
    
    }

    Now before you look at my commented code try to think about what's going to happen. Remember, Java is pass by value, so what do you expect is going to happen to this int?

    public class Learning {
    
        public static void main(String... args) {
            int exampleInt = 5; //variable with the name of exampleInt is pushed on the stack
            attemptToChange(exampleInt); //invoking the method on the int
            System.out.println(exampleInt); //prints 5
        }
    
        public static void attemptToChange(int testInt) {
            testInt = 10;
            System.out.println(testInt); //prints 10
        }
    
    }

    When we passed our exampleInt to the #attemptToChange(int testInt) method, we passed the actual value of the variable and created a whole new variable called testInt which now holds the exact same value exampleInt did (essentially a complete copy)! That's why when we printed our the value of exampleInt after we invoked the method on it, it still contained the same value. Just to reiterate that one more time:

    1. We created an int variable called exampleInt
    2. We passed it to a method which took the value and placed a copy in another int called testInt
    3. The value of testInt was printed inside of the method which showed 10
    4. exampleInt was printed right after the method call inside of the main method and printed 5

    Great, now we understand what happens to primitives when their passed to methods. Regarding reference types, let's look at the same general code we've been working with and think about what's going to happen to the Person object bob:

    public class Learning {
    
        public static void main(String... args) {
            Person bob = new Person("Bob");
            attemptToChange(bob);
            System.out.println(bob);
        }
    
        public static void attemptToChange(Person person) {
            person.setName("Jake");
            System.out.println(person);
        }
    
    }

    Think carefully! When you think you know the outcome look below at my comments:

    public class Learning {
    
        public static void main(String... args) {
            Person bob = new Person("Bob"); //creates a new instance on the stack with a reference to the newly created object on the heap
            attemptToChange(bob); //pass the person object to our method
            System.out.println(bob); //prints Jake
        }
    
        public static void attemptToChange(Person person) {
            person.setName("Jake"); //attempt to set the name to Jake
            System.out.println(person); //prints Jake
        }
    
    }

    Let's see what happened here if you don't understand:

    1. Created a new Person object called bob with the name field set to Bob
    2. Passed bob to our method
    3. Our new object person now contains the value passed to it (a pointer to the object on the heap)
    4. We call the #setName(String name) on person
    5. This call changes the value which is points to, AKA the original bob object we set
    6. We print out the name for person
    7. The name for bob is printed, which we can see has changed!
    Link to comment
    Share on other sites

    • 2 weeks later...

    Archived

    This topic is now archived and is closed to further replies.

    ×
    ×
    • Create New...

    Important Information

    We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.