#edit IT works, thanks for the answers:) I guess my bad was when I thought that
WORLD[i]=global.Values.CHUNKPATTERN();
simply takes the object on the right, clones its value('s), and assigns them to part on the left, while it turns out that it establishes a reference between two. Thanks again:)
I have simple begginer/newbie array problem:
for(int i=0; i<global.Values.WORLDVOLUME(); i++)
// global.Values.WORLDVOLUME() --> const, int. always the same.
{
WORLD[i]=global.Values.CHUNKPATTERN(); //to pre-define as 'zero only' object. Always the same. Const.
WORLD[i].chunknr=i+1;
}
System.out.println(WORLD[4].chunknr);
Of course I want WORLD[0] to have chunknr 1, WORLD[4] to have chunknr of 5 and so on.
Instead WORLD[i].chunknr=i+1; seems to update chunknr of ALL elements(not only WORLD[i]).
So that it looks like WORLD[0].chunknr = WORLD[1].chunknr=global.Values.WORLDVOLUME() here.
Anyone knows how to bypass that? I belive there's a simply solution...
Do I understand the array of objects correctly?
You can Have like(providing you have the class and constructor)
Point POINTARRAY[]= new Point[10];
POINTARRAY[1].x=5
POINTARRAY[1].y=6
POINTARRAY[3].x=17
POINTARRAY[3].y=1
Right?
How to assign that via loop?
Instead WORLD[i].chunknr=i+1; seems to update chunknr of ALL elements.
Are WORLD[0] and WORLD[1] different objects? They are not different if `WORLD[0] == WORLD[1] evaluates to true.
You have:
WORLD[i]=global.Values.CHUNKPATTERN();
Does CHUNKPATTERN create a new object every time it is called?
I bet this method
WORLD[i]=global.Values.CHUNKPATTERN();
always returns the same instance of an object so you have a reference to the same object in every slot of your array.
Subsequently
WORLD[i].chunknr=i+1;
you change the attribute chunknr of the same object in every iteration. You say
...seems to update chunknr of ALL elements
kind of true, because all elements reference the same instance.
You need to find a way to have global.Values.CHUNKPATTERN(); return a new object every time.
This line is your problem:
WORLD[i]=global.Values.CHUNKPATTERN();
This is assigning WORLD[i] a reference to global.Values.CHUNKPATTERN(), meaning that they both point to the same object! And for each iteration of your loop you are just creating more and more references to the same global object.
Sometimes this isn't what you want. In this case you need to copy the value, which can be done in a number of ways, but in most cases you can simple clone it. All Java objects support a clone() method, although sometimes you need to override it to do the correct thing for your class.
All this means is that you should replace the above line with:
WORLD[i]=(YourType)global.Values.CHUNKPATTERN().clone();
where YourType is the actual type of the class, since you omitted that from the code snippet you posted.
Hope that helps!
I guess the following line returns always the same reference:
global.Values.CHUNKPATTERN();
so the different array indices are actually point to the same referece. It's only a guess because you didn't tell us how the above function works.
Here's an example of what different array element could point to the same instace:
public class AClass{
public int val = 0;
}
AClass[] array = new AClass[2];
AClass classInstance = new AClass();
array[0] = classInstance;
array[1] = classInstance;
The code above instatiated a single AClass object (classInstance), but use 2 different array elements to reference the same instance:
System.out.println("array 1 value " + array[1].val ); // both element initialized to 0 so it prints 0
array[0].val = 15; // actually is classInstance.val to be modified, through the reference to it stored inside the first element of the array.
System.out.println("array 1 value " + array[1].val ); // print 15
For what concern the POINT example, you can use for loop this way:
Point POINTARRAY[]= new Point[10];
for(int i = 0 ; i < POINTARRAY.length; ++i)
{
POINTARRAY[1].x=...;
POINTARRAY[1].y=...;
}
Related
So here it goes. I've been building a piece of software for a bigger project, and right now, I am simply baffled by the way Java treats my code. I have absolutely no idea as to why Java behaves the way it does right here.
It seems to skip part of my code, and assigns values to a different array than I expected when no according method is called.
I have walked over this for a few hours now with the IntelliJ Debugger, inspecting everything ever so closely, but I have not found a single reason as to why things happen the way they do.
package com.whatareyoudoing.java;
import java.util.Arrays;
/**
* WHAT THE ACTUAL DUCK
*/
public class WTF {
private int[] number;
private int[] oldNumber;
public WTF() {
number = new int[1];
oldNumber = new int[1];
}
public void putNumber(int c) {
number[0] = c;
}
public void putOld() {
if(Arrays.equals(oldNumber, number)) {
System.out.println("Nothing to do!");
return; //How on earth can they literally be the same?!
}
oldNumber = number;
}
public void doWTF() {
putNumber(1);
putOld(); // Works.
putNumber(2); // Expected Result: number = 2; oldNumber = 1 [NOPE] number = 2; oldNumber = 2
putOld(); // [NOPE] Simply Skips with "Nothing to do"
putNumber(3); // Same odd behaviour
putOld(); // Aaaand skips again.
}
}
After calling putNumber the first time, using putNumber again simultaneously puts the value in both variables (oldNumber and Number) instead of only in number[0].
I continued to simplify my code as far as possible so this example is more hands-on. Obviously, the real example where I found this had arrays longer than a single element.
I also tested it with multidimensional arrays, as well as object arrays. No change in the behavior.
I am completely puzzled now and have absolutely no idea how to go on. If you can shed any light on this topic, please do so. I am more than confused.
The following assignment statement:
oldNumber = number;
makes oldNumber and number point to the same underlying array. Perhaps what you want is to make a copy:
System.arraycopy(number, 0, oldNumber, 0, number.length);
See the documentation for System.arraycopy for full details.
This line isn't doing what you think it's doing.
oldNumber = number;
It isn't copying the contents of one array to another. It is making the reference variable oldNumber refer to the same array object as number refers to.
oldNumber ----> [1]
number -------^
So, any change through either variable writes through to the same array, and the change is visible through both references, which refer to the same array.
Then later you call Arrays.equals with references to the same array, so they are "equal".
You want to copy the number with this line instead:
oldNumber[0] = number[0];
When you assign
oldNumber = number
you don't make a copy of the values in the array. oldNumber will point to the exact same array (and future changes in either variable reflect in the other).
You can make a copy with
oldNumber = Arrays.copyOf(number, number.length);
In the putOld function you assigned the reference of the first array to the other. After the first call oldNumber is a pointer to number and if you change a value in one, the other one is affected too.
If you want to copy the values System.arraycopy().
Can some one tell me how i would achieve the following. Java is not my strong point and after trying to search i keep getting pages on javas always pass by reference.
void edit(int[] a){
a = new String[]{"q","r","s","t","u"};
}
int[] x = new int[]{"a","b","c"};
edit(x);
System.out.println(x); // ["q","r","s","t","u"]
Im trying to achieve the above so that i can change the pointer of x after i've passed it into a function.
Thanks all for your help
Java is purely pass-by-value. You cannot do anything inside a method that changes the value of a variable used as an argument to the method. It simply isn't possible in Java.
In your example, you can change the content of the array, you just can't change what array x is referring to. You'd do that like this:
void edit(int[] a) {
a[0] = 1;
a[1] = 2;
a[2] = 3;
}
Note the distinction here: You can change the content of the array x refers to, but you can't change x from within edit. So for example, you can't change the length of the array, because the only way to do that is to create a new array and point x at it, and you can't do that within edit.
Other options:
Have edit return a new array, then assign that to x.
Use List, so you can change how many elements there are.
Create a class with mutable properties and pass an instance of that class in.
class A
{
static int i;
A()
{
System.out.println(++i);
}
public static void main(String h[])
{
A obj[] = new A[30];
}
}
A obj[30] = new A[30]; :- this line should invoke the default
constructor 30 times ?
The line
A obj[30] = new A[30];
does not call the constructor for A. It creates 30 uninstantiated references to A;
To instantiate the 30 object references, you can use:
A obj[] = { new A(), new A(), ..28 more ->
};
or better in this case given the number of elements:
for (int i=0; i < obj.length; i++) {
obj[i] = new A();
}
Note, the first use of 30 in the array size declaration is illegal.
A obj[30] = new A[30];
^
No, this line does not invoke constructor at all. It just creates 30 elements long array of type A. Each element of array is null.
There is no way to do exactly what you want to do, but here are two things that come very close, both calling the default constructor 30 times:
A *obj = new A[30];
or
A obj[30];
The first answer will create an array of 30 A objects on the heap, calling the default constructor for each one of them. obj can be passed back to callers of this function since it is not on the stack. The problem is, obj no longer has a type of A[30], so sizeof(obj) will be different from the code in the original question. (Note that "delete []" must be used for obj, not just "delete".)
The second answer will create an array of 30 A objects on the stack. Now the compiler will understand the obj has 30 elements, and sizeof(obj) will be the same as in your question. However, obj can only be used within this function (or functions that it calls) because once the function returns, it will be eliminated from the stack, calling 30 destructors in the process. (It is a local variable only.)
With C++ (or any good object oriented language), creating an object always means both allocating the space and calling the constructor. Otherwise, you really don't have a useful object. So, when an object is created in any supported way (local variable or "new" for C++), it always calls the default constructor for every object you created and now have access to. (Note that if there were no default constructor, then neither answers would even compile!)
I'm working with two-dimensional array-values that should be inserted into a ArrayList. But this is done in a for-loop and the value of the two-dimensional array-value gets changed as the loop runs since it is just used as an temp-variable (which makes all of the variables stored in the ArrayList gets changed as this variable changes).
So if I try to print out the content of the ArrayList when the loop is done all the values are the same.
for(int i = 0; i <= Counter; i++)
{
if(Xhavetomove >= i)
arrayvalue[0][0] = this.Xspeed;
else
arrayvalue[0][0] = 0;
if(Yhavetomove >= i)
arrayvalue[0][1] = this.Xspeed;
else
arrayvalue[0][1] = 1;
System.out.println(arrayvalue[0][1]);
Object.movement.add(arrayvalue);
}
Are there anyway I can make it store the value itself?
For example: The first time the loop runs the value is "5,5" but if I print out the ArrayList when the loop is done all the values has turned into "5,1".
The problem is the way Array is added to the Object here. You are not adding the Array to the Object. What is happening is you are adding the address to the location in memory where the Array resides. So every time you add the Array to the Object, you are adding the same address every time. So every Array in the Object is actually the same Array over and over since they all point to a single location in memory. So when you change the Array, it will appear to change all of them inside the Object.
The best thing to do is either create a new Array every time through the loop, essentially creating a new location in memory for the Array to reside, or clone() the Array which will create a new reference.
Example:
String[] houseOfStark = {"Eddard", "Catelyn",
"Robb", "Sansa", "Arya", "Bran", "Rickon"}; // Sorry Jon
String[] copyOfStark = houseOfStark;
String[] cloneOfStark = houseOfStark.clone();
houseOfStark[1] = "Lady Catelyn";
System.out.println(houseOfStark[1]);
System.out.println(copyOfStark[1]);
System.out.println(cloneOfStark[1]);
Will produce:
Lady Catelyn
Lady Catelyn
Catelyn
Good blog post explaining the difference
At the end each add needs to create an own object.
To use clone is one way.
Or to add always the values in pairs, in an other.
A totally different way is to use serialization. This make sense when you do not want to calculate this values but to log it. In this case you need an outputStream
What is best is defined by what you want to do with Object.movement
You need to use array's clone() method to make its copy:
//for example
int[][] copy = (int[][])arraySource.clone();
I have come across two scenarios.
One in which an array is passed as argument to a method and if it is updated in the called method, it is reflecting in the calling method as well.
But in the second scenario, a String Object is passed as argument. The object is updated in the called method, but it doesn't reflect in the calling method.
I want to understand what is the difference between two, even though in both cases, value (of reference) is passed as argument. Please see below snippets.
Scenario 1:
class Test {
public static void main(String[] args){
int a[] = {3,4,5};
changeValue(a);
System.out.println("Value at Index 1 is "+a[1]);
}
public static void changeValue(int b[]){
b[1] = 9;
}
}
Output:
Value at Index 1 is 9
Here, reference (Memory Address) related to array a is passed to changeValue. Hence, b is just pointing to same address as a does.
Hence, whether I say b[1] or a[1], it is referring to same memory address.
Scenario 2:
public class Test {
public static void main(String[] args){
String value = "abc";
changeValue(value);
System.out.println(value);
}
public static void changeValue(String a){
a = "xyz";
}
}
Output:
abc
If I apply the same logic here, String Object VALUE's reference (Memory Address) is being passed to changeValue, which is recieved by a.
Hence, now a should be referring to the same memory location as VALUE does. Therefore, when a="xyz" is executed, it should replace "abc" with "xyz".
Can someone please point out where my understanding goes wrong? Thanks in advance!!
Java passes all its arguments by value. This means that a copy of the pointer to the String is made, and then passed to the method. The method then makes the pointer point at another object, but the original pointer still points to the same String.
This is not the same thing:
in the first example, you pass an array reference as an argument, therefore you correctly expect it to be changed by manipulating the reference directly;
in the second example however, you pass an object reference, sure -- but you change the reference itself in the method. Changes to a are not reflected when the method returns.
Consider any object:
public void changeObj(Object o)
{
o = new Whatever();
}
a new object is created, but it won't change o in the caller. The same happens here.
You're doing different things; with the string you set the parameter value, with the array you set something belonging to the reference.
For an equivalent array example you'd need to try setting the array reference to a new array:
public static void changeValue(int[] b) {
b = new int[] { 42, 60 };
}
The original array won't be changed.
The difference here is simple, and it is not actually about immutability of strings, as some other answers (now edited or deleted) might have originally implied. In one version (with the string), you have reassigned the reference, and in other version (with the array), you haven't.
array[0] = foo; // sets an element, no reassignment to variable
array = new int[] { 1,2,3 }; // assigns new array
obj = "hey"; // assigns new value
When you reassign the variable, you are not going to observe that change outside of the method. When you change elements of an array without reassigning the array variable, you will observe those changes. When you call a setter on an object without reassigning the actual variable of the object, you will observe those changes. When you overwrite the variable (new array, assigning new value, creating new object, etc.) those changes will go unobserved.
Arguments are passed (or copied) by value. The variable inside the method has the same value as the variable on the outside at the beginning. The variables are not linked, and they are not aliases for one another. They just happen to contain the same value. Once you reassign the value to one of them, that is no longer true! The variable on the outside is not affected by the variable on the inside, or even another local variable. Consider
Foo foo = new Foo();
Foo other = foo;
foo.setBar(1);
int bar = other.getBar(); // gets 1
foo = new Foo();
foo.setBar(42);
int bar2 = other.getBar(); // still gets 1
foo and other only referenced the same object for a time. Once foo was assigned a new object, the variables no longer had anything in common. The same is true for your reassignments to the parameter variable inside your method.
Thank you all for answers and updates..
I understood the difference between scenario 1 and 2 as below..
In scenario 1, the array reference is passed. The called method just updates one of the elements pointed by the reference.
While in scenario 2, the reference is passed, but when the called method assigns "xyz" to the reference variable (pointer), it actually creates a new String Object and its reference is assgined to a local reference variable 'a' (Pointer now points a different objct).
The code in called method is as good as
a = new String("xyz");
Hence, the object in called method and calling method are absolutely different and indepenedent and have no relation with each other.
The same could have happened with scenario 1, if instead of doing
b[1] = 9;
I would have used
b = new int[] {8,9,10};
I understood, Mutability fundamentals would have come in action, if I might have done like below..
String a="abc";
a="xyz";
In this case, object "abc" was being pointed by 'a'. When 'a' is assigned the duty to point to a new object "xyz", a new object "xyz" is created, which is not replacing the existing object "abc". i.e. "abc" is still existing but has no reference variable to keep itself accessible anymore. This non-replacement property is because of Immutability of String.