Jump to content
  • Advertisement
Sign in to follow this  
eCustic

Java - References

This topic is 2610 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

So I'm mainly a C# developer and I'm used to objects being passed by reference in methods. However I am currently attempting to make a small-medium sized game in Java and I've hit a bit of a bump.
Usually when I create my game objects I like each object to have a reference to my main Game object. So currently I have the following (only the relevant part of the code is shown here):


public abstract class Entity {
private Game game;

public Entity(Game game) {
this.game = game;
}
}


So when I instantiate a new Entity object from my Game class I just pass [font="Courier New"]this[/font] in the constructor. I expected any changes made to the Game object to be reflected by the game variable of the Entity class, but due to Java's pass-by-value property they aren't. This however is not the main problem as I can live without having a Game reference in each entity. The problem is that I had the same thoughts when making my input handler. I'm currently using Java 2D for the rendering and I'm just drawing on a canvas (my Game class extends Canvas) so I'm just extending the KeyAdapter class with my KeyInputHandler and passing it to the addKeyListener() method in my Game class. However I'd also like to be able to pass the KeyInputHandler object to my Player object so that I can handle all movement of the player within the Player class. However, since the KeyInputHandler is just copied into the Player object it doesn't update the instance variables when the KeyEvents are fired.

I might be going about this the wrong way (this is how I usually do it with XNA in C#) or I might just be missing something in the way I've implemented it, but if anyone could help point me in the right direction I'd be really grateful. :)


I'll just paste some of the relevant pieces of code from my KeyInputHandler class and my Player class, so that it might be a bit clearer what I'm trying to do.



public class KeyInputHandler extends KeyAdapter {
private boolean rightDown;
private boolean leftDown;
private boolean downDown;
private boolean upDown;

public boolean isRightDown() { return rightDown; }
public boolean isLeftDown() { return leftDown; }
public boolean isUpDown() { return upDown; }
public boolean isDownDown() { return downDown; }

public void keyPressed(KeyEvent e) { ... } // here the rightDown, leftDown, etc. variables are changed.
public void keyReleased(KeyEvent e) { ... }
}




public class Player extends Actor {
public void updateInput(KeyInputHandler keyHandler) {
if(keyHandler.isLeftDown() && !keyHandler.isRightDown()) { this.setHorizontalVelocity(-1); }
if(keyHandler.isRightDown() && !keyHandler.isLeftDown()) { this.setHorizontalVelocity(1); }
...
}
}

Share this post


Link to post
Share on other sites
Advertisement
In Java all objects are passed by reference. Primitive types on the other hand are always passed by value.

Share this post


Link to post
Share on other sites

I expected any changes made to the Game object to be reflected by the game variable of the Entity class, but due to Java's pass-by-value property they aren't.
[/quote]
Java is pass-reference-by-value for non-primitive types, which is exactly like how C# handles classes. Were you assuming this, or have you actually tried it?

It should work, unless you try to do something like this:

public class Game {

private int test;

public Game(int test) {
this.test = test;
}

public void someMethod() {
++test;
}

@Override
public String toString() {
return "Game (" + test + ")";
}

}

public class Entity {

public void run(Game game) {
// Changes the field of the game instance in main()
game.someMethod();
System.out.println("run(): " + game);

// Doesn't change the value main()'s game reference
game = new Game(42);
System.out.println("run(): " + game);

// Changes local game's field only
game.someMethod();
System.out.println("run(): " + game);
}

}

public class Main {

public static void main(String [] args) {
Game game = new Game(1);
System.out.println("main(): " + game);

Entity entity = new Entity();
entity.run(game);

System.out.println(("main(): " + game);
}

}

I haven't tested it, but it should print:

main(): Game(1)
run(): Game(2)
run(): Game(42)
run(): Game(43)
main(): Game(2)
[/quote]

Share this post


Link to post
Share on other sites
Wow, I feel foolish now. I just realized that the error was not due to reference issues but something else entirely.
I just assumed that the object wasn't being passed as it should and found several websites saying that java was pass-by-value only which seemed to make sense to me based on the results I was getting.
However I just debugged it and it is definitely doing what it is supposed to do. I'm just handling the result badly.

Anyway, I suppose this thread is now just a waste of space. Thank you all for helping me realize my mistake, I really do appreciate it. :)

Share this post


Link to post
Share on other sites

Wow, I feel foolish now. I just realized that the error was not due to reference issues but something else entirely.
I just assumed that the object wasn't being passed as it should and found several websites saying that java was pass-by-value only which seemed to make sense to me based on the results I was getting.
However I just debugged it and it is definitely doing what it is supposed to do. I'm just handling the result badly.

Anyway, I suppose this thread is now just a waste of space. Thank you all for helping me realize my mistake, I really do appreciate it. :)


Java is pass-by-value. So is C#. As are most programming languages.

However, the usual term is "pass-reference-by-value." Unlike C/C++, when you create a named variable instance using the new operator in Java and C# (if the object type is 'class'), you create what is called a reference. When you pass this reference to a method, you get a copy of the reference. However, the reference acts more like a pointer, in that the reference 'refers' to an object in memory. So when you pass it (by value), the method gets a copy of the reference, that points to the same object. Since it is a copy, if you 'reseat' the reference (reassign the reference to a new object using 'new'), the original passed reference still refers to the original object, not the new one. Simple example:


class Foo
{
public int Bar = 0;
}

static void Main(string[] args)
{
var test = new Foo();
test.Bar = 3;
Debug.WriteLine(test.Bar);
Reassign(test);
Debug.WriteLine("After Reassign: " + test.Bar);
Reseat(test);
Debug.WriteLine("After Reseat: " + test.Bar);
ReseatReference(ref test);
Debug.WriteLine("After ReseatReference: " + test.Bar);
}

static void Reassign(Foo foo)
{
foo.Bar = 6;
Debug.WriteLine("In Reassign: " + foo.Bar);
}

static void Reseat(Foo foo)
{
foo = new Foo();
foo.Bar = 12;
Debug.WriteLine("In Reseat: " + foo.Bar);
}

static void ReseatReference(ref Foo foo)
{
foo = new Foo();
foo.Bar = 24;
Debug.WriteLine("In Reseat Reference: " + foo.Bar);
}


The output is as follows:

3
In Reassign: 6
After Reassign: 6
In Reseat: 12
After Reseat: 6
In Reseat Reference: 24
After ReseatReference: 24


People use "pass-by-reference" incorrectly when describing most managed languages. As the C# example shows, actually passing by reference is very different than passing a reference by value.

Share this post


Link to post
Share on other sites
I have heard about "pass-reference-by-value" before but I can't understand what the difference is between that and pass-by-reference. Isn't it always the case that things are being copied and in that case it means pass-by-reference is not possible at all.

Share this post


Link to post
Share on other sites

I have heard about "pass-reference-by-value" before but I can't understand what the difference is between that and pass-by-reference. Isn't it always the case that things are being copied and in that case it means pass-by-reference is not possible at all.


Read my code sample above, which shows how you can pass-by-reference in C#. You can also do this in many languages, but Java is not one of them. But, it is not a necessary feature as design can eliminate or mitigate the need or use of reference passing semantics.

Share this post


Link to post
Share on other sites
ok, but you can still say you pass the object by reference in Java but you can't pass the reference by reference. That makes sense to me. It all comes down to what you are referring to.

Share this post


Link to post
Share on other sites

ok, but you can still say you pass the object by reference in Java but you can't pass the reference by reference. That makes sense to me. It all comes down to what you are referring to.


It is more correct to say that you are passing an object reference, not "by reference" as that would imply pass-by-reference semantics, which Java does not have. I know it is a nitpick, but it is a source of major confusion because people play fast and loose with what should be precise computer science terminology. Argument passing semantics is a computer science wide topic, not an individual language topic.

Share this post


Link to post
Share on other sites
C# and Java are identical, down to the dot.

Java however lacks two things:
- method parameters: ref/out/params
- value types (struct vs. class in C#)

There is no way to achieve such functionality in Java or in raw JVM itself.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!