Change the value of instance without changing the other instance - java

For those who had read my first question, I think I found where the problem is. The problem is in the mutate method and especially in this instruction:
Chromosom ch=new Chromosom(); // Chromosom is a class who use hash table
Chromosom k= new Chromosom(); // Class chromosom extends hashmap <integer,parc>
k.initialise();
for(int i=0;i<l.size();i++) ch.put(i,k.get(i)); // in this instruction i think
And this is the constructor of Chromosom:
public Chromosom(){ // construct a blank chromosom
super();
this.identifiant = 0;
NbEquipeExterne = 0;
NbEquipeInterne = 0;
CoutMinimal = 0;
CoutMensuel = 0;
}
When I change the values of ch, the values of k change too?
How can I pass the k's values to ch by copy and not by reference?

First of all Java is always pass-by-value. or rather pass-by-copy-of-the-variable-value not pass by reference. You might be changing objects of Chromosom with k in the constructor.

No danger, both ch and k are separate objects.
Furthermore you can do
ch.putAll(k);
which is a nice short-cut to remember.
Caveat
If the values of the maps are stateful objects (having mutable fields to contain some changing info), then changing that field would change the field of the simgle value object in both tables.
BitSet bits = k.get(i);
bits.set(3);
// Now ch.get(i) being the same object, also has bit 3 set.
If a class has a static field, then that field is once per class, a single instance. So you could have in say Chromosome:
static String copyright;
Chromosome.copyright = "All rights reserved"; // Clearest style
k.copyright = "All rights given to the community";
ch.copyright = "MIT license";
And you would have dealt with the same single variable, with vaklue "MIT license".
About Java
A nice design decision was made in java:
If you pass a variable to a function/method, the object/value will be passed. It may never happen that the variable itself gets an other object/value. (Not the address of the variable is passed.) Java has pass-by-value, no pass-by-reference.

Related

Helper Methods within static method are overidding multiple variables? [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 5 years ago.
public class SeamCarving {
public static Seam carve_seam(int[][] disruption_matrix) {
int[][] original = disruption_matrix;
int[][] weighted_matrix = disruption_matrix;
SeamCarving s1 = new SeamCarving();
weighted_matrix = s1.buildMatrix(disruption_matrix);
....
}
In the above code I have a static method carve_seam. The method takes a matrix. That input is saved in a matrix variable called original. A calculation is performed on the matrix and that is also saved as a variable called weighted_matrix. Both are needed.
Since its in a static method, a new object of the class is made and it is called from that "s1.buildMatrix"
However, that line is doing something that is over my head. This is because afterwards, not only is weight_matrix changed (correctly from the buildMatrix method) but original is also changed to the same exact thing! How does this happen???
First thing you need to understand here is that all the three reference matrix, are referring to the same object you have passed as the input (disruption_matrix object). This is the reason why also the original and weighted_matrix are being changed.
In the first line,
int[][] original=disruption_matrix;
refers to the same object in disruption_matrix.
Then on the next line,
int[][] weighted_matrix=disruption_matrix;
refers to the same old object as well. So, you do not need to reach the line,
weighted_matrix = s1.buildMatrix(disruption_matrix);
to see that both original and weighted matrix have been changed. Actually the they have been changed when you have done the calculation to the disruption_matrix itself.
This situation is quite similar to a something like, where,
int a=10;
int b=a;
int c=a;
So, not only 'a' but also 'b' and 'c' will have their value assigned to 10.
In a OOP manner, where such same object is being assigned to different references, once a change has been made to the object through a single reference no matter that you're accessing the object through a different reference, the object has been changed.
For an example let's take this simple class,
Class A{
int val=10;
}
now, in some method we create an object and assign it to references,
A a=new A();
a.val=20;
A b=a;
b.val=30;
A c=a;
c.val=40;
As for the above code, an object is created under the reference called 'a'. In the next line, the value 'val' is accessed through that reference and has been changed from 10 to 20.
Then, the reference 'b' has been declared and it is initialized and pointed to the same object which 'a' is holding. Then in the next line, the value of that object (val) is changed again 20 to 30, but this time through 'b' instead of the reference 'a'.
Same goes to the next three lines where the value of the object is being changed from 30 to 40 through the reference 'c'.
So finally what will be the output?
System.out.println(a.val);
System.out.println(b.val);
System.out.println(c.val);
It is obviously going to give you the output,
40
40
40
This is the concept you are missing here (Pass by value and pass by reference).
In Java, Arrays are technically objects and not primitives, even for arrays of primitive types. Whenever you pass an argument to a method as an object, Java passes it as a reference; the values of the original argument change because all variables you have created are "referring" to the same object. This, however, is not the case with primitives, which are passed by value.
I suggest that whenever you need to make a matrix off of another you use the following utility method:
public static int[][] copyMatrix(int[][] original) {
int[][] copy = new int[original.length][];
for(int x = 0; x < copy.length; x++) {
copy[x] = new int[original[x].length];
for(int y = 0; y < copy[x].length; y++) {
copy[x][y] = original[x][y];
}
}
return copy;
}
At the end, your code would look like this:
public class SeamCarving {
public static Seam carve_seam(int[][] disruption_matrix) {
// no need to make an "original" variable anymore,
// since disruption_matrix already stands for it
int[][] weighted_matrix = copyMatrix(disruption_matrix);
SeamCarving s1 = new SeamCarving();
weighted_matrix = s1.buildMatrix(disruption_matrix);
....
}
}
Keep in mind that this implementation copies the arrays but not the objects. This will solve your problem when working with primitives like int but not with mutable objects.

Memory usage/ reference in java

I am going to ask a basic question about Java memory usage.
Imagine we have an array List and it is large enough and we don't like to use more memory. Now if I want to pass this array to another methods in this class, or other classes through their constructor or method, do I need additional memory/is there additional memory usage for this array?
If yes, could I just make this array package level, and therefore the other classes in this package could access it directly, without any memory need.
Thank you in advance.
No, no additional memory is necessary. The parameter of a function is passed by copy of the reference. It means that for any kind of object only 4 additional bytes are used.
If you pass an array as parameter and you modify it in the body of the method the changes will be exported outside of method.
Instead if you reassign the array variable, the difference is not visible externally.
This happens because the parameters are passed as copy of the reference and not by reference.
public void vsibleModification(int[] a) {
for (int i = 0; i < a.length; i++) {
// This change is visible outside of method because I change
// the content of a, not the reference
a[i] = a[i] + 1;
}
}
public void nonVisibleModification(int[] a) {
// Non visible modification because a is reassigned to a new value (reference modification)
a = new int[2];
a[0] = 1;
a[1] = 2;
}

Java pass by value clarified [duplicate]

This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 7 years ago.
I have a list of Cell object that represent a board game inside the board class.
Cell boardGame[][] = new Cell[8][8];
I needed a temporary cell to try the player move on him and compare it to the other cells, so I though that I could use a java pass-by-value to do it.
test(board.boardGame);
board.printBoard();
private static void test(Cell[][] boardGame) {
Cell c = new Cell((new Soldier(ChessPiece.QUEEN, Color.WHITE)), 7, 4);
boardGame[7][7] = c;
}
I read some post about java here, but apparently I still didn't catch it 100%.
I expected to see only one white queen on the board, but I saw two.
I know that if you pass a reference you can change its values, but I though that if I would pass the array itself its members won't be modified unless I would execute a return.
Please help me to understand this subject better.
Thanks
Edit:
I think I don't understand when it called attributes and where it doesn't.
I though the different it if you are call "new" or not.
When its part of another object it called attribute right? but every object can be created as part of another object. I can create a new string in dog class and then create the dog class in the animal class and then create it in another class. So only the top class is in the stack?
For exemple:
public class Board { //fake class
int num= 0;
public void test(int i){
i = 1;
}
}
and on another class:
public class Main {
static void outsideTest(Board board){
board.num = 1;
}
public static void main(String[] args) {
Board board = new Board();
System.out.println(board.num);
board.test(board.num);
System.out.println(board.num);
outsideTest(board);
System.out.println(board.num);
}
}
Now I didn't understand why on test() method the num didn't change and on outsideTest() the num change, num as been created in the heap because its part of the board object, so its need to be changed on both cases no?
The best and least confusing way to remember it is as follows: Java passes everything by value, that includes the references. :)
When you have a variable:
Object a = new Object();
you don't actually have an object stored in a. What you have is a reference to an object somewhere in memory.
Likewise when you call a method on an object:
String b = a.toString();
you don't do that. What you call is a method that uses the data of the referenced object as its context.
So when you pass an object as an argument
System.out.println(b);
You don't pass the whole object. You pass the reference and that reference is passed by value.
edit:
If the reference were not passed by value, but by reference, you could do something like this, which fortunately you can't.
public void swap(Object a, Object b){
Object swap = a; a = b ; b = swap;
}
String a = "a";
String b = "b";
swap(a,b);
// would print "b a" if references were
// passed by reference but instead prints
// "a b" as they're passed by value.
System.out.println(a + " " b);
The reference to the object is passed by value, which means that
boardGame = new Cell[8][8];
does not do any harm, but changing anything you get from boardGame does.
Java is essentially always "pass-by-value".
Caveat: It passes the value stored in the memory for the variable.
For primitive data types, the memory is allocated in stack space, whereas for objects reference memory is allocated in stack space but the object itself is created in heap. Similar can be stated for arrays too though they are not exactly objects in a strong sense.
Diagrams below would make it clearer.
Your Cell object 2D array should seem something like anObjectArrayVar (not exactly as the ref in the diagram pointing to the objects should now be pointing to the rows and we would need another level of allocation in heap in between ref and objects for each row (a set of cells refering to the objects).
So, when you pass boardGame, the value stored in the stack is passed that stores the reference to the array of objects (just like the value stored in the anObjectArrayVar). If say the list of refs is stored in location numbered 50 then anObjectArrayVar would have stored that and it passes that value to the test method when we call it. In such a scenario the test method wont be able to goto memory location anObjectArrayVar and change its value (to say 100) as it has only a copy of the value but it could easily change what it refers to(directly or indirectly) like the values in ref or the next level (and add new objects as in your case adding a new cell with queen) or the objects pointed to by them and those changes would reflect through out the program!
I would also like to draw your attention to the fact that the code
boardGame[7][7] = c;
would replace the current cell (as well as the soldier currently in it) which would create major issues if there was originally a soldier in that place at that point in the game. The game state would actually change.
As a suggestion (given the limited knowledge about your design) I would say at least save the cell in some other value in test method before replacing it.
Cell old = boardGame[7][7];
//now do all your operations
boardGame[7][7] = old;//just before returning from the function

Using variables as names for other variables in Java

Alright, I am not completely sure that I worded the title right, but I want to use an int variable to define another int to go through a method. In other words, I want to be able to have the int/name/thingy variable go through a ++ statement, and then the next variable would go through the method. Is this possible?
An int array might solve your problem. The array stores your ints ("variables"), another one runs throught the index (your ++ operation):
int[] values = loadValuesInArray(); // some magic to get the populated array
for (int i = 0; i < values.length; i++) {
myMagicMethod(values[i]); // calling the method with int values
}
If you need named variables, then you can use a map:
Map<String, Integer> variables = new HashMap<String, Integer>();
variables.put("a", 1);
variables.put("b", -10);
variables.put("c", 25);
myMagicMethod(variables.get("b")); // calls method with value from "variable" b
You can use reflection.
http://java.sun.com/developer/technicalArticles/ALT/Reflection/
http://www.java2s.com/Tutorial/Java/0125__Reflection/Catalog0125__Reflection.htm
or see to have an idea.
Setting variables by name in Java
You almost certainly want to be using something like a Map or List (essentially a dense map with a small positive int key).
If you don't need to create a new variable with a name, stored in another variable, then reflection is a way to go.
String varName = "x";
Point2D point = new Point(15, 2);
Integer val = (Integer)Point.class.getDeclaredField(varName).get(point);
assert val == 15;
You say "I want to use an int variable to define another int" do you mean something like
int a = 0; //declare a new variable a of type int and assign it to zero
a b = 0; //declare a new variable b of type a which is an int and assign it to zero
From what you said, that is what it appears you are saying. If that is the case, I do not think you can do that. My memory says that there is a method that allows you to determine the type of an object, but to use that as a declaration of another variable... I don't know if you can do that.

Why when I pass an array, it changes value in the method? Amazing [duplicate]

This question already has answers here:
Changing array in method changes array outside [duplicate]
(2 answers)
Closed 3 years ago.
public class Test {
public static void main(String[] args) {
int[] arr = new int[5];
arr[0] = 1;
method(arr);
System.out.println(arr[0]);
}
private static void method(int[] array)
{
array[0] = 2;
}
}
After invoking method, arr[0] becomes 2. Why is that!?
You can call set methods on objects passed to a method. Java is pass by value, which means that you can't replace an object in a method, though you can call set methods on an object.
If Java were pass by reference, this would pass:
public class Test {
public static void main(String[] args) {
Test test = new Test();
int j = 0;
test.setToOne(j);
assert j == 1;
}
public void setToOne(int i) {
i = 1;
}
}
Java is Pass-by-Value, Dammit! http://javadude.com/articles/passbyvalue.htm
This is because Java uses Call by Object-Sharing* (for non-primitive types) when passing arguments to method.
When you pass an object -- including arrays -- you pass the object itself. A copy is not created.
If you mutate the object in one place, such as in the called method, you mutate the object everywhere! (Because an object is itself :-)
Here is the code above, annotated:
public static void main(String[] args)
{
int[] arr = new int[5]; // create an array object. let's call it JIM.
// arr evaluates to the object JIM, so sets JIM[0] = 1
arr[0] = 1;
System.out.println(arr[0]); // 1
method(arr); // fixed typo :-)
// arr still evalutes to JIM
// so this will print 2, as we "mutated" JIM in method called above
System.out.println(arr[0]); // 2
}
private static void method(int[] array)
{
// array evaluates to the object JIM, so sets JIM[0] = 2
// it is the same JIM object
array[0] = 2;
}
Happy coding.
*Primitive values always have call-by-value semantics -- that is, a copy is effectively created. Since all primitive values are immutable this does not create a conflict.
Also, as Brian Roach points out, the JVM only implements call-by-value internally: the call-by-object-sharing semantics discussed above are implemented by passing the value of the reference for a given object. As noted in the linked wikipedia article, the specific terms used to describe this behavior differ by programming community.
Additional:
Pass by value or Pass by reference in Java? -- see aioobes answer and how it relates with Brian Roachs comments. And aioobe again: Does array changes in method?
Make copy of array Java -- note this only creates a "shallow" copy.
Because that's exactly what you're telling it to do. Java passes first by value, then by reference. You're passing in the array, but any modifications you make to that array will be reflected on any other accesses to that array.
A quick example for thought:
If within method you did array = null, no change would be visible from main - as you would be changing the local value of array without modifying anything on the reference.
Because when you are passing argument like int/double/char etc. they are the primitive data types and they are call by value - meaning their values are copied to a local variable in this method (that has the same name as the names in your argument) and changes made to them are only changes made to these local var -> does not affect your primitive type variables outside the method
however an array or any object data type is called by reference -> the argument pass their address(reference) to method. that way, you still have a local variable named by them which has the reference. You can change it to reference another array or anything. but when it is referencing an array, you can use it to set the value of the array. what it does is accessing the address it is referencing and change the content of the referenced place
method(arr[0]);
I think that's supposed to be
method(arr);
But anyway the value passed as argument to the method is the reference to the array and the local variable arr in the method is referencing the same array. So, within the method you are making changes to the same array.
Java is pass by value. What confuses people is that the 'value' of a variable that refers to an object allocated on the heap is a reference, so when you pass that, you pass the reference 'by value' and therefore it refers to the same object on the heap. Which means it doesn't matter from where you modify the referent; you're modifying the same thing.

Categories

Resources