2

So, i have an array of Integers

Integer[] distances = new Integer[n];

Then, I have a PriorityQueue of Nodes, where the structure contains a "to" and "distance", sortable by the distance.

class Node implements Comparable<Node>{
    Integer distance;
    int to;
    Node(int To, Integer Dist){
      to = To;
      distance = Dist;
    }

    @Override
    public int compareTo(Node o) {
      if(this.distance < o.distance)return -1;
      if(this.distance > o.distance) return 1;
      return 0;
    }
  }

What I'd like to do is add nodes onto the priority queue like the following:

PriorityQueue<Node> q = new PriorityQueue<Node>();
q.add(0, distances[0]);

Now, I'd like to change the value of dist[0] and get it reflected inside the Node object in the PriorityQueue. First question: since I'm passing in an Integer in the constructor, will it be passed in by reference, and have a functionality similar to doing something similar using C++ pointers:

class Node {
  int* distance;
  int to;
  Node(int To, int* dist){
    distance = dist; to = To;
  }

and I'd create the node as int[] distances = new int[n]; Node nd = new Node(0, &distances[0]); So when I change distances[0], my *nd.distance also gets changed.

Second question: If it's possible, is this a good practice or are there any possibilities where the array gets disposed by the garbage collector before my priority queue is disposed of?

arviman
  • 4,587
  • 37
  • 44
  • 2
    No, your plan fails as soon as you realize that `Integer` is an immutable class, so you can't change it nor have any changes reflected anywhere. It's not a good practice to simulate other languages in a programming language either. – Kayaman Jul 03 '16 at 07:40
  • Possible duplicate of [Is Java "pass-by-reference" or "pass-by-value"?](http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value) – Raedwald Jul 03 '16 at 07:43

1 Answers1

1

As has been already pointed out in the comments, your attempt will fail because Integer objects are immutable. I would still like to post an answer for non-immutable objects, which will point out the key difference to C++ pointers.

Short answer to your first question: For a "normal" (non-immutable) object it will have a similiar functionality but not exactly the same.

In Java, functions receive a copy of the reference to an object. Strictly speaking this makes it pass-by-value. The following example shall demonstrate the key differences to C++ pointers.

public class Main {
    public static class Test {
        public String text;
        public Test(String text) {
            this.text = text;
        }
        public void doit() {
            System.out.println(text);
        }
    }

    static void reference() {
        Test[] t = {new Test("This is class 0"), new Test("This is class 1")};

        attemptSwitch(t[0], t[1]);
        System.out.println();
        System.out.println("calling t[0].doit() outside attemptSwitch():");
        t[0].doit();
        System.out.println("calling t[1].doit() outside attemptSwitch():");
        t[1].doit();

        manipulate(t[0]);
        manipulate(t[1]);
        System.out.println();
        System.out.println("calling t[0].doit() after manipulate()");
        t[0].doit();
        System.out.println("calling t[1].doit() after manipulate()");
        t[1].doit();
    }

    static void attemptSwitch(Test t0, Test t1) {
        Test tmp = t0;
        t0 = t1;
        t1 = tmp;

        System.out.println("calling t0.doit() from inside attemptSwitch():");
        t0.doit();
        System.out.println("calling t1.doit() from inside attemptSwitch():");
        t1.doit();

    return;
    }

    public static void manipulate(Test t) {
        t.text = "This class has been manipulated!";
    }

}

The above class will first create an array with two Test objects. Then it will attempt to switch those objects in attemptSwitch() and after that it will try to change the content of text by calling mainpulate(). The output will look like this:

calling t0.doit() from inside attemptSwitch():
This is class 1
calling t1.doit() from inside attemptSwitch():
This is class 0

calling t[0].doit() outside attemptSwitch():
This is class 0
calling t[1].doit() outside attemptSwitch():
This is class 1

calling t[0].doit() after manipulate()
This class has been manipulated!
calling t[1].doit() after manipulate()
This class has been manipulated!

As you can see, the switch is successful inside attemptSwitch(), but this switch is not persistent. Outside of the function attemptSwitch() the references were not affected at all and the Test objects were not switched. This is due to the fact, that attemptSwitch() received only a copy of the references to our Test objects. Only those copies were switched inside the function.

As the call to manipulate() shows, it is possible to persistently alter the contents of a class. In this case, it does not matter that the function receives just a copy of the reference, since it also points to the same address where the class stores its contents.

As for your second question, I have used similiar constructs. This approach is probably more prone to produce a memory leak, i.e., keep an object longer in memory than required, than losing data. As long as there is at least one reference pointing to your object it will not get garbage collected - if the reference is not a weak reference or something similiar. AFAIK, PriorityQueue uses regular references.