wood burning stoves 2.0*
The moose likes Beginning Java and the fly likes functions permanently rewriting data Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "functions permanently rewriting data" Watch "functions permanently rewriting data" New topic
Author

functions permanently rewriting data

T Shaw
Greenhorn

Joined: Jul 29, 2012
Posts: 27
I am still fuzzy on the details, but something I thought I understood about Java was that if one created a variable outside a method, assigned it a value, passed it as a parameter to a method, and changed the value inside the method, the value outside the method is not changed. I am not experiencing that in my present program.

I'm working on a pathfinding method. It basically checks the specs on a specific x,y position on an array of tile objects passed to it, records that data to that object, and then in a for loop it calls itself upon the four squares x+/-1 and y+/-1 until a certain number of movement points are exhausted. To save time, to prevent it from trying to explore paths which take it through tiles which an earlier iteration of the function could have taken, I keep an array of tiles I consider "dead" and want the method to ignore.


This is in main and gets passed to my pathfinding method.

I keep another array of all the x and y coords which the process took to get to whatever point the function is presently at. Since I don't want any tiles to be dead coming in, I require that the pathhistoryarray be at least 2 items long. If it is, I take the coordinates of the square the function was analyzing in the last iteration, and kill the four adjacent tiles.


the killing method looks like this


because the function only recurses on itself if certain situations are met, such as the adjacent tile not having too high of an elevation to make the climb, I called another method in there, toohigh(), which makes sure the last branching point actually could have taken or will be able to take that move before it kills the tile, but that's not part of my problem; I'm just documenting that for you because I don't have it in my code's documentation yet.

Now I call the method within the method, passing deadtiles:


What I thought would happen is that at each branch there would be an individual instance of deadtiles keeping the exact list of discarded tiles from all the iterations up until the one before present, and when the end of one branch is reached and the program goes back to a previous fork, it picks up the previous list of discarded tiles from the iteration before that fork. However, it seems my coding is permanently rewriting the array such that when I type System.out.println(deadtiles[3][7]) in main, targeting a point in the array that should only be marked as dead (technically, true) in the sixth iteration, it reads as true after the method has been completed.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:I am still fuzzy on the details, but something I thought I understood about Java was that if one created a variable outside a method, assigned it a value, passed it as a parameter to a method, and changed the value inside the method, the value outside the method is not changed.

This is true of primitives and immutable objects; unfortunately NOT of mutable ones (which includes arrays).

When you pass reference types (ie, objects - and again, an array is an object), you pass a copy of its reference, and that is what won't be changed in the caller. Unfortunately, if the object itself is mutable, there's nothing to stop the method changing things inside the object.

The easiest way to pass a copy of an array A to a method is to pass A.clone() (a very useful change since 1.5).

Winston


Isn't it funny how there's always time and money enough to do it WRONG?
Articles by Winston can be found here
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 37970
    
  22
Actually the bit about not changing the data is true for reference types as well as primitives.
It all depends what you mean by data.
You cannot change the data passed to a method as an argument. But if that argument happens to point to a mutable reference type, then you may be able to manipulate the contents of that object. The reference to the object cannot be changed, but manipulating that object can alter its state.
Winston is right about passing defensive copies.
fred rosenberger
lowercase baba
Bartender

Joined: Oct 02, 2003
Posts: 11154
    
  16

I personally think of it this way (and I am ignoring immutable objects for now)...

I have an address to a house written down - that is the variable created outside a method, and the actual house is the actual object. I need to give the address to you, so I photocopy it and pass it to you (you are the method, and i have now given you the address of the house, which is the parameter in your method).

Now, you can erase that data off your piece of paper. You can write a new address on your piece of paper. you can do whatever you want with your piece of paper - even throw it away.

However, nothing you do to your piece of paper will changed what is on MY piece of paper.

BUT...

If you read that address, and go to the house, and paint the bedroom purple...then when I go to my house, the bedroom is purple. The bedroom will be purple for anyone who goes to that address and does a getColorOfBedroom().


There are only two hard things in computer science: cache invalidation, naming things, and off-by-one errors
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 37970
    
  22
fred rosenberger wrote:. . . and paint the bedroom purple... . . .
Purple? Ugh!

The people who had the house before us painted the bedroom purple.
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4343
    
    8

Campbell Ritchie wrote:The people who had the house before us painted the bedroom purple.

Our lounge is purple. Looks great .
T Shaw
Greenhorn

Joined: Jul 29, 2012
Posts: 27
So I gather I have to take the array which I do not want changed and make a copy of it, and pass that copy to my function instead? That doesn't seem to be working. I already, as a habit, start all my methods by making copies of the parameters passed to my functions, and only manipulate that data. cf.:


even if I change the third to last line to

the changes my method makes to deadtiles[][] within the method are made also to the array I defined in main which is passed to the parameter getdeadtiles. I'm assuming Java is thinking "hey, this is just a copy of an array that already exists, so instead of actually allocating an entirely separate array into memory, I'll just point to the first array instead," but I cannot have that. Or am I mistaken?
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:So I gather...

T Shaw. Please don't put enormously long lines inside code blocks; it screws up the windowing.

I've split up your, but please re-read the UseCodeTags page thoroughly before you post again, because it explains this problem.

Thanks.

Winston
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 37970
    
  22
Matthew Brown wrote: . . . Our lounge is purple. Looks great .
A friend moved into a house at Havant (you are going back about 30 years), and every surface was a different shade of non‑spectral colours. There was purple, puce, magenta, pink, crimson, fuchsia, mauve, you name it, he had it.

Everybody had to dress like this smilie to visit him
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:So I gather I have to take the array which I do not want changed and make a copy of it...

Correct.

even if I change the third to last line tothe changes my method makes to deadtiles[][] within the method are made also to the array I defined in main which is passed to the parameter getdeadtiles. I'm assuming Java is thinking "hey, this is just a copy of an array that already exists, so instead of actually allocating an entirely separate array into memory, I'll just point to the first array instead," but I cannot have that. Or am I mistaken?

You are. Java doesn't "think" anything. It does exactly what you tell it to.

If you look at what I said above, you'll see that I said to pass a clone to the method. All
boolean deadtiles[][] = getdeadtiles.clone();
is create a variable called 'deadtiles' with a clone. If the method changes it, then 'deadtiles' will be changed when the method returns. The idea is to create it and forget it.

Winston
T Shaw
Greenhorn

Joined: Jul 29, 2012
Posts: 27
but if deadtiles is a clone of whatever array is passed through parameter getdeadtiles, how are changes to the former being passed back to the latter?
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:

BTW: 9 parameters, including two 2D arrays? Seems like an awful lot. Are you sure you really need all that?

BTW2: <nitpick>
It should be 'PathFinding', not 'pathfinding' (and I'm not sure I like the idea of a present participle used as a class name either).
</nitpick>

Winston
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:but if deadtiles is a clone of whatever array is passed through parameter getdeadtiles, how are changes to the former being passed back to the latter?

They aren't. What I suspect is that you're than passing 'deadtiles' to the method that changes it. Unfortunately, your code is so tightly coupled and involves such massive parameter lists that I've forgotten what's going on.

The basic idea is this:
You have a method x() that takes an array a. Instead of calling x(a), call x(a.clone()).

It should also be pointed out that I think this only works for one-dimensional arrays (can't remember to be honest). Yours have two, so you may have to look at something like Arrays.deepCopy(), or maybe create your own twoDClone() method.

Winston
T Shaw
Greenhorn

Joined: Jul 29, 2012
Posts: 27
Winston Gutkowski wrote:
T Shaw wrote:

BTW: 9 parameters, including two 2D arrays? Seems like an awful lot. Are you sure you really need all that?


Well, it's part of my AI. I need to pass it an x value and a y value where it starts, a certain amount of move points, the map object which it's moving over (the total x and total y parameters can probably be more efficiently determined from this, but I haven't cleaned that up yet), the path it took to get there, the tiles I want it to ignore, and finally the array of objects to which I'm writing my final data. Of course, I haven't even begun to write the function that analyzes what a good move is, for which I'll have to pass it another array of objects containing the specs on all the pieces on the grid.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:Well, it's part of my AI. I need to pass it an x value and a y value where it starts, a certain amount of move points, the map object which it's moving over (the total x and total y parameters can probably be more efficiently determined from this, but I haven't cleaned that up yet), the path it took to get there, the tiles I want it to ignore, and finally the array of objects to which I'm writing my final data.

OK, well I'd definitely document it (if only for yourself for when you come back after 6 months and several nights on the town and can't remember what you were thinking).

Also, positions are not the same thing as cells. Java has a class called java.awt.Point, which can store an x,y coordinate. As it stands, it's a horrible class, because it violates all sorts of OO practises; but it might give you an idea of how you might (and might NOT ) implement a Position class.

Winston
T Shaw
Greenhorn

Joined: Jul 29, 2012
Posts: 27
With this code, I often can't remember what I was thinking ten minutes ago, so I've taken to writing small books of documentation within it in places.

I changed my boolean[][] deadtiles = getdeadtiles; line into a manual copy with nested for loops and now it runs as desired. Apparently I was only making shallow copies, even with .clone()
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:I changed my boolean[][] deadtiles = getdeadtiles; line into a manual copy with nested for loops and now it runs as desired. Apparently I was only making shallow copies, even with .clone()

Great! Sorry if I misled you with clone(), but all I can say is the idea was right.

Sorry too about Arrays.deepCopy(): there is no such animal (there are a few other 'deep' methods, but not a copy; which quite surprises me if clone() is only one-dimensional).

What I would definitely do is put that code into a utility class somewhere and document it.

Winston
T Shaw
Greenhorn

Joined: Jul 29, 2012
Posts: 27
How to manage various kinds of classes is still way over my head. I vaguely understand that Java has built in libraries of utilities pre-built so that I don't have to build them myself, but I'm not sure what all is involved in interacting with them, nor how to construct and manage one of my own. I'm actually starting on my AI first because I want to get the swing of basic Java commands and flow management and OO programming in general before I have to mess around with these libraries which I'll need in order to write my GUI. I quit C long ago in my youth because I could never figure out why I couldn't get graphics.h to work. Of course I didn't have the internet then.
Winston Gutkowski
Bartender

Joined: Mar 17, 2011
Posts: 7536
    
  18

T Shaw wrote:How to manage various kinds of classes is still way over my head. I vaguely understand that Java has built in libraries of utilities pre-built so that I don't have to build them myself, but I'm not sure what all is involved in interacting with them...

'Fraid there's no silver bullet; you have to read the API documentation.

Off the top of my head, the main ones to know about are:
java.lang.Math
java.util.Random
java.util.Arrays
java.util.Collections
and there's a new java.nio.file.Files in version 7.
(you can click on all the above to get said documentation; and I should warn you that some of them are quite big)

If I've missed any biggies, I'm sure the other chaps here will tell me.

Winston
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: functions permanently rewriting data
 
Similar Threads
Non-static method cannot be referenced from a static context
Complications with sine, cosine, and doubles
an applet compiled but can't run because of the nullPointerException
custom cursor in XOR mode
Making a class instance "current"