I know the question of Java being pass-by-reference or pass-by-value is beating a dead horse but I do have a question regarding memory usage.
The way I understand Java now is that:
public class MyInt{
int value;
}
MyInt x;
MyInt y;
x = new MyInt(3); // value of x is now 3
y = x; // y now points to same object that x points to
y.setValue(1); // value of said object is now 1
x.getValue(); // should return 1 instead of 3
But my question is how memory intensive is it to set this new y? Ex: if the value of MyInt were some very very large image instead of an integer,
x = new MyImage("very large image"); // eats memory depending on size of image
Would naturally take a lot of memory to have that image loaded if it were very large. I just want to make sure that when I call
y = x; // y now points to same image that x does
y is just a reference to the object that x is already pointing at right? So when I call y = x; it would not be memory intensive no matter how large the image as long as that image had already been loaded via initializing x.
Is this correct? What pitfalls should I avoid to keep the same very large image from being loaded into memory multiple times?
Yes you're right, any non primitive instance assignment to a non primitive reference variable is just reference assignment.
So if there's a memory location for x say mem1 then y=x will make y to point to mem1. Now even if x were to point to a new memory location mem2, y will still be pointing to mem1. So that's a pitfall to be avoided.
You almost will never be able to load a very large object multiple times without noticing it first, as you would either be creating new object calling the constructor or using some form of clone() method.
One pitfall unrelated to large objects but related to pass by reference in Java is that a reference variable passed to a method can not be dereferenced.
So suppose there's a method dereferenceMe(MyInt x) {x = new MyInt();} it won't change the actual reference of x in the caller method. As Java will pass the reference by value, meaning it creates a copy of reference variable and that copy is passed to the methods.
You are right, when you call y=x it would simply set y to refer the location of "very large image". There still would be only 1 object in memory which would be referenced by both x and y.
To avoid the very large image from loading again and again in memory, just don't create a new object with that image again. Avoid deep copy of the object as well.
Related
I know that local variables are stored on stack in java. But what happens with respect to memory allocation on stack when two int variables are given same value in java(How are they related)? Is there any kind of copy on write semantic? How does it works then?
The obvious answer is that int x=5; int y=5; does the same as int x=5; int y=6; with the only exception being that, in your case, the memory that's been associated with y will look the same as as it does for x.
It's difficult to envisage a JVM where some kind of copy on write semantic is used - i.e. x and y are allocated the same piece of memory until one of them changes the value. As far as I know, that is theroetically permissible by the Java Language Specification, but it's unlikely to be used by anything so trivial as an int: the overhead in setting up the copy on write would far outweigh them having different memory from the outset.
(Out of interest, it was possible to write copy-on-write semantics for the C++ std::string class, but since C++11 it's been disallowed).
It will definitely create to variable in stack. which hold value 5.
There's no other way.
Any variable local/global,primitive/non-primitive stores some value
For primitive value is some whatever you assign according to type.
For non primitive value is memory address of the object in heap but in the end both holds value and does not lookup if some other var has the same either way.
I'm trying to make a 2d game in Java.
In the process I soon noticed that many objects needed bounds (x1, x2, y1, y2) and as a consequence many methods thus had parameters (int x1, int x2, int y1, int y2).
So I thought what the heck, why not make an object IntRectangle with attributes x1, x2, y1, y2 (which I set as public for a performance boost), along with a few helpful methods like getWidth(), getHeight(), etc.
At this point my code is much cleaner and I haven't lost much performance since the variables are public.
I soon noticed, unlike passing primitive values into a method, the values of the passed object changed when I changed them in the method.
For instance, with a primitive value
int x = 10;
subtract5(x);
print(x);
void subtract5(int i) {
i -= 5;
}
this line of code would print 10.
But with an object...
class XY {
public int X;
public int Y;
}
main {
XY xy = new XY();
xy.X = 5;
xy.Y = 10;
changeX(xy);
print xy.X;
}
changeX(XY xy2) {
xy2.X = 7;
}
It prints 7;
The theory I've developed is that an int is not a pointer to an int, it's an int stored in the register. It is pushed when a method is called and then popped back when returned, unchanged. An object is a reference to an object. The object itself isn't pushed onto the stack, just the pointer.
But I've tired this with strings (that I know are objects) and they behave just like ints in this matter, which confuses me. Perhaps they make a copy out of themselves somehow?
Well, I hope someone can shed some light on this matter and tell me where my reasoning is taking a wrong turn and hopefully give me some advice on how to clean up my code, keep performance, but without making it venerable.
A object in java is a block of memory in the heap space. All you pass around are references to this object/memory area. (The references itself are passed by value) So if you have an Object Rectangle with four ints your methos will change the memory of the heap ara which is references by the passed object reference.
Strings are immutable - so the object cannot change and every modifier method returns a new instance.
See http://javadude.com/articles/passbyvalue.htm for more information.
The fact is that Java is always pass-by-value.
In particular Java passes objects as references and those references are passed by value.
In case of primitive type, it is passed directly by value.
Further details in the following question:
Is Java "pass-by-reference" or "pass-by-value"?
Strings are constant; their values cannot be changed after they are created.If you change the value of a String it will create a new String object and return a reference to the new String object i.e a new instance is created .E.g
String str="abc";
str=str+"d";
In this case a new String object is created in the String pool and it is now referred by str.The old string is garbage collected.
Ok, I might have been a bit vague, but the question was not how java passes variables. I just came from that thread. I've figured that out, it was just the String class that was confusing me. And the eventual performance gain of having public attributes. I'll make another attempt, thanks for all your answers!
In Java, when you assign one object to another, the original object isn't copied, it merely clones the reference. So, for example, I'd like it to behave like this Java code:
SomeClass x = new SomeClass();
SomeClass y;
y = x; // x is not copied, y is simply a (Java) reference to x
What I'd like to do is create a C++ class that behaves the same way. The obvious choice is to overload the assignment operator, like so:
SomeClass& operator=(const SomeClass& rhs)
{
this = &rhs;
return *this;
}
Unfortunately, assigning a new location to this is not allowed; the above code won't even compile.
Does anyone know of any other way to do this?
Also, before you say anything: yes, I know this is absolutely the wrong way to implement an assignment operator. Please, indulge me anyway.
EDIT 2: To clarify, here is the C++ code that should behave as in Java:
SomeClass x = SomeClass(); // Created on stack
SomeClass y; // In C++, same as above; NOT reference or pointer
y = x; // x is not copied, y becomes a (C++) reference to x;
// original y is destroyed when stack unwinds
I DO NOT want to use pointers at all.
EDIT: I'm doing this to see if I can change the base address of a C++ object that was passed by reference to a function. If I simply assign another object to the reference variable, it automatically makes a shallow copy, and I don't want that. I want the reference parameter to reference a completely different object.
I'm doing this to see how references are implemented by the compiler. If references are syntactic sugar for dereferenced pointers, then outside the function, the base address of the argument object would NOT change. If they are aliases in the symbol table (as in PHP), then it WILL change. (So any solution using pointers is out, since that's my "control" for the test.)
Hope that makes sense.
This isn't possible. The languages just work fundamentally differently.
SomeClass x in Java is some kind of pointer or reference to a SomeClass object. It's an indirection, so that why you can have multiple ones refering to the same object.
SomeClass x in C++ literally is the object. Thus SomeClass y is literally an entirely different object. There's no indirection. And so there's no way to make one reference the other.
C++ provides pointers (SomeClass* x) and references (SomeClass& x) to take care of the times when indirection is needed. Perhaps those are what you actually want to use, although it depends on why you asked this question in the first place.
Responding to the edit:
No, you can't change the address of an object. An instance of an object will live in exactly one place for the duration of its lifetime, until it is destroyed/deallocated.
I don't think this is okay, because even you assign this to another pointer, then the current object pointed by this will be memory leaked. Java has memory collection, but C++ not.
This is a good question, through. And this is possible.
A& operator=(const A& rhs)
{
A * cthis = const_cast<A*>(this);
cthis = const_cast<A*>(&rhs);
return *cthis;
}
Edit: It is possible to change "this pointer" inside a member function. But changing "this pointer" doesn't accomplish much.
It can be done. but, with pointer indirection.
Lets say you have a class someClass
class someClass
{
someClass *someClsPtr;
public:
someClass(someClass *someClsPtrTemp):someClsPtr(someClsPtrTemp)
{
}
someClass* operator=(someClass *someClsPtrTemp)
{
this->someClsPtr = someClsPtrTemp->someClsPtr;
return this;
}
//now over load operator -> and operator *. Thats it.
};
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is it possible to write swap method in Java?
Given two values x and y, I want to pass them into another function, swap their value and view the result. Is this possible in Java?
Not with primitive types (int, long, char, etc). Java passes stuff by value, which means the variable your function gets passed is a copy of the original, and any changes you make to the copy won't affect the original.
void swap(int a, int b)
{
int temp = a;
a = b;
b = temp;
// a and b are copies of the original values.
// The changes we made here won't be visible to the caller.
}
Now, objects are a bit different, in that the "value" of an object variable is actually a reference to an object -- and copying the reference makes it point at the exact same object.
class IntHolder { public int value = 0; }
void swap(IntHolder a, IntHolder b)
{
// Although a and b are copies, they are copies *of a reference*.
// That means they point at the same object as in the caller,
// and changes made to the object will be visible in both places.
int temp = a.value;
a.value = b.value;
b.value = temp;
}
Limitation being, you still can't modify the values of a or b themselves (that is, you can't point them at different objects) in any way that the caller can see. But you can swap the contents of the objects they refer to.
BTW, the above is rather hideous from an OOP perspective. It's just an example. Don't do it.
I'm going to be reallllyyyy annoying and pedantic here because the word "value" has a very specific meaning in Java, which people often don't often understand, especially when the variables hold references to objects.
I am going to assume the question asks for this behavior:
x = initialValueForX;
y = initialValueForY;
swap(x, y);
// x now holds initialValueForY;
// y now holds initialValueForX;
This is not possible because Java passes all arguments to methods by value. You can never change the actual value stored inside of x and y this way.
You can, however, if x and y hold references to objects, change the properties of the two objects in such a way as to make the printed values look like each other's initial values:
x = initialValueForX;
y = initialValueForY;
swap(x, y);
System.out.println(x); prints what looks like initialValueForY
System.out.println(y); prints what looks like initialValueForX
This works if your understanding of value is what the object looks like, rather than what the identity of an object is. Usually, that is acceptable.
(Was going to give a good example here, but cHao already did. Plus others pointed out that this was a duplicate question anyway.)
In my Java test was the next question:
there is the next method:
public void changer(int[] x, int y) {
x[y] = x[y] +3;
y = y * 2;
}
We have array named a, with the values:
2,4,0,1,-6,3,8,7,5
if b = 3
what will be a and b values after the next call:
changer(a,b);
My answer was:
b = 6
a = 2,4,0,4,-6,3,8,7,5
I've tested it on BlueJ and got the same answer, but the tester wrote: wrong !
what do you say?
You are right about array values, but wrong about b value.
When you call a method, java passes everything by value, that mean that changing y only changes the value locally, and the change is not reflected on b.
However, when passing arrays and objects, a value representing a pointer to the array is passed. That means that x = new int[8] does not alter a at all, since as it happens for y the change is not reflected to a. However, changing array members or object properties works as you expected, cause a and x both point to the same array in memory.
from the scope where changer is called b doesn't change, because Java is pass by value and b is a primitive. So b would still be 3 after the method call. The statement in changer:
y = y * 2
after changing the value in the array effectively does nothing.
Your answer for a is correct.
b should still be 3. Passing an integer passes it "by value", so it is essentially a copy of b that goes into the changer method.
B won't be changed because it is a primitive passed as a method parameter. In that case a local copy is made, which is in this case multiplied by two. The original b will not be affected by this though. The array is changed because arrays (even arrays of primitives) are Objects in Java, so the reference to the array is passed into the method and changes to the array (via the reference) are reflected in the one and only array - no copy is made in this case.
You're confusing values and references, and thinking of the y value as if it's a reference.
The first line
x[y] = x[y] +3;
sets the value of the yth element of the array. The following line y = y * 2;
changes the value of the parameter but doesn't alter the array setting.