Java Pass-by-reference not working?

2.4k Views Asked by At

I'm trying to make this little game in Java but I seem to have stumbled upon a variable reference problem. My Entity class, which Player extends from, keeps a variable of type Dimension. This Dimension gets set via the constructor of the Entity class like so:

protected Dimension dimension;

public Entity(Dimension dimension) {
    this.dimension = dimension;
}

In my player class, this is how I pass the dimension object via his constructur:

public Player(Dimension dimension) {
    super(dimension);
}

I also have a Game class, which keeps all the possible dimensions, plus an extra variable called activedimension which keeps a reference to the active game dimension.

private Dimension activedimension;
private Dimension overworld;
private Dimension otherdimension;

public Game() {
    overworld = new OverWorldDimension();
    otherdimension = new OtherDimension();
    activedimension = overworld;
}

When I want my overworld dimension to reset, I use this method:

public void resetOverWorld() {
    overworld = new OverWorldDimension();
    activedimension = overworld;
}

Now, whenever I call this resetOverWorld method from anywhere, it seems like my activedimension really did refresh, but the dimension stored in my Player/Enitity class didn't. I'm fairly new to Java, so I don't know if I'm doing something wrong with the variable-references being passed through constructors and methods. My application seems to copy a dimension object somewhere instead of passing the reference, but I can't figure out where.

Any help or thoughts are welcome. Thanks in advance ~Krikke

4

There are 4 best solutions below

1
On BEST ANSWER

The problem is that you aren't updating the reference in your Player class. When you store your Dimension in your Entity constructor you are storing a reference to that Dimension in memory. In your resetOverWorld() method you change the overworld and activedimension variables to point to a new OverWorldDimension but all the references elsewhere (e.g. your Entity objects) haven't changed. They still refer to the initial Dimension they were constructed with.

You might want to consider having a DimensionTracker class that your Entity could hold instead, allowing you to change it's internal Dimension from a single location. Otherwise you need to update every Entity to refer to the new Dimension.

public class DimensionTracker {
    public Dimension dimension;
    public DimensionTracker(Dimension d) {
        dimension = d;
    }
}

...

protected DimensionTracker dimensionTracker;

public Entity(DimensionTracker dt) {

    dimensionTracker = dt;
}

...

public Player(DimensionTracker dt){
    super(dt);
}

...

private DimensionTracker activedimension;
private Dimension overworld;
private Dimension otherdimension;

public Game() {
    overworld = new OverWorldDimension();
    otherdimension = new OtherDimension();
    activedimension.dimension = overworld;
}

...

public void resetOverWorld() {
    overworld = new OverWorldDimension();
    activedimension.dimension = overworld;
}
0
On

You don't save the reference to the variable overworld, but to value of overworld with this:

this.dimension = dimension;

So you have to update the reference for Entity manually when the reference changes in the game, else it will point to the old value since it's independent from the variable overworld.

0
On

You pass a dimension object to your Player object, and it stores a reference to that object in one of its fields.

In your Game object you set activedimension to refer to a Dimension object. By changing its value you change it to refer to a different Dimension object.

Even if activedimension used to refer to the same Dimension object you passed to Player, changing it to a different Dimension object does not change which object is refered to in Player.

Consider, if the system starts like this:

Game
-  activedimension --> Dimension object A

Player
- dimension --> Dimension object A

Changes to Dimension object A will be seen by both the Player and Game objects.

However, changing activedimension to point to Dimension object B, a totally different object does not make dimension change to point to it.

Game
-  activedimension --> Dimension object A

Player
- dimension --> Dimension object B
0
On
public void resetOverWorld() {
    overworld = new OverWorldDimension();
    activedimension = overworld;
}

this will just update the Game class variable private Dimension activedimension ;

after call to resetOverWorld(), you have to set this new reference to Entity class by doing something like

entity.setDimension(activedimension)