How does Java deal with passing reference data type arguments?? Can somebody give a clear picture?
Java passes a copy of the reference to the method. The reference still points to the same instance.
Imagine if I had a slip of paper with a restaurant's address on it. You also want to go to the same restaurant so I get a new slip of paper and copy the address of the restaurant on to that paper and give it to you. Both slips of paper point to the same restaurant but they are separate references to the instance.
The restaurant itself is not duplicated, only the reference to it is duplicated.
Jon Skeet provides a similar analogy:
The balloon analogy
I imagine every
object as a helium balloon, every
reference as a piece of string, and
every variable as something which can
hold onto a piece of string. If the
reference is a null reference, that's
like having a piece of string without
anything attached to the end. If it's
a reference to a genuine object, it's
a piece of string tied onto the
balloon representing that object. When
a reference is copied (either for
variable assignment or as part of a
method call) it's as if another piece
of string is created attached to
whatever the first piece of string is
attached to. The actual piece of
string the variable (if any) is
holding onto doesn't go anywhere -
it's only copied.
Here is an example:
// Here I have one instance and one reference pointing to it
Object o = new Object();
// At this moment a copy of "o" is made and passed to "foo"
foo(o);
void foo(Object obj) {
// In here I have obj which is a copy of whatever
// reference was passed to me
}
All Java objects (everything except primitives such as int, float, boolean, etc...) are references to the pointed-to-object.
So for example:
Foo f = new Foo();
Above, f is a reference to an object of type Foo. If you then have a function:
void doSomething(Foo myFoo) { ... }
doSomething(f);
The doSomething() function receives the same object that f refers to. So if doSomething() mutates f, it is mutating that object.
Unlike C++, there is no choice between passing by value, reference or using pointers: All class-type variables are references (or pointer depending on your exact terminology).
One problem here is that people often try to apply their C++ knowledge and terminology to Java, which won't work.
Related
After searching a lot, at least this question helped me to understand the difference of using copy constructor and assignment operatorMy question is about this line instance has to be destroyed and re-initialized if it has internal dynamic memory If I initialize an instance like
Object copyObj = null; and then then assign copyObj = realObj then still this overhead (destruction and re-initialization) remains?If not, then Now in this scenario, why should I use Copy Constructor instead of direct assigning the object
The concept of using a copy constructor by overriding the = simply does not exist in Java. You can't override operators. The concept of a copy constructor in Java works like this:
public class MyType {
private String myField;
public MyType(MyType source) {
this.myField = source.myField;
}
}
A copy constructor is a constructor that takes a parameter of the same type and copies all it's values. It is used to get a new object with the same state.
MyType original = new MyType();
MyType copy = new MyType(original);
// After here orginal == copy will be false and original.equals(copy) should be true
MyType referenceCopy = original
// After here orginal == referenceCopy will be true and original.equals(referenceCopy) will also be true
The = operator does the same: Assigning an object to a variable. It produces no overhead. The thing that can differ in runtime is the constructor call.
A Copy constructor allows you to keep two references; one to the "old" object, one to the "new". These objects are independent ( or should be depending upon how deep you allow the copy to be )
If you do a reassignment, you only have a reference to the "new" object. The "old" object will no longer be accessible ( assuming there are no other references to it ) and will be eligible for garbage collection.
It comes down to what it is your trying to achieve. If you want an exact copy of the object, and you want this object to have an independent life of its own, use a copy constructor. If you just want a new object and don't care about the old one, reassign the variable.
PS - I have to admit, I didn't read the question you linked to ..
First some basics about copy construction and copy assignment in C++ and Java
C++ and Java are two very different beasts due to object semantics in C++ and Reference semantics in Java. What I mean by this is:
SomeClass obj = expr;
In C++ this line denotes a new object that gets initialized with expr. In Java, this line creates not a new object but a new reference to an object, and that reference refers to what ever the expression gives. Java references can be null, meaning "no object". C++ objects are, so there is no "no object"-object ;-) Java references are very much like C++ pointers. The only thing that can make the distinction difficult is that while C++ has pointers and objects and dereferences pointers with ->, in Java everything is a reference (except int and a few other basic types), and accessing objects through references uses ., wich easily can be confused with access to "direct" objects in C++. "Everything is a reference" means, that any object (except int & Co.) is conceptually created on the heap.
Having said that, let's have a look at assignments and copies in both languages.
Copy construction means the same in both languages, you essentially create a new object that is a copy of another. Copy constructor definition is similar:
SomeClass(SomeClass obj) { /* ... */ } //Java
SomeClass(SomeClass const& obj) { /* ... */ } //C++
The difference is only that C++ explicitly has to declare the parameter as a reference, while in Java everything is a reference anyways. Writing the first line in C++ would define a constructor that takes it's argument by copy, i.e. the compiler would have to create a copy already, using the copy constructor, for which it has to create a copy,... - not a good idea.
Using copy construction in the two languages will look like this:
SomeClass newObj = new SomeClass(oldObj); //Java
SomeClass newObj = oldObj; //C++ object
SomeClass* ptrNewObj = new SomeClass(oldObj); //C++ pointer
When you look at the first and third line, they look essentially the same. This is because they are essentially the same, since Java references are essentially like pointers in C++. Both expressions create a new object that can outlive the function scope it is created in. The second line creates a plain C++ object on the stack, wich does not exist in Java. In C++, copies are also created implicitly by the compiler eg. when an object is passed to a function that accepts its parameter by value instead of by reference.
Defining copy assignment: In C++, you can define operator= wich (normally) assigns the values of an object to an already existing object, discarding the old values of the object you assign to. If you don't define it yourself, the compiler will do it's best to generate one for you, doing a plain elementwise copy of the objects' elements. In Java, you cannot overload operators, so you will have to define a method, called e.g. assign:
void assign(SomeObject other) {/* ... */} //Java
SomeObject& operator=(SomeObject const& other) {/* ... */} //C++
Note thet here again we explicitly declare the parameter as reference in C++ but not in Java.
Using copy assignment:
objA = objB; //C++ copy assignment
objA = objB; //Java ref assignment
ptrObjA = ptrObjB; //C++ pointer assignment
objA.assign(objB); //Java
objB.change();
Here the first two lines look exactly the same but could not be more different. Remember that in C++, objA and objB deonte the objects themselves, while in Java they are only references. So in C++ this is copy assignment on objects, meaning you finish with two objects that have the same content. After changing objB you will have objA with the value that objB had before the assignment, while objB has changed.
In Java (line 2) that assignment is an assignment of references, meaning after that the two references objA and objB refer to the very same object, while the object previously referred ba objA is not referred to any more and so it will be garbage collected. Calling objB.change() will change the single object both references point to and accessing it through the reference objA will reveal these changes.
Again it's (nearly) the same with C++ pointers. You see you cannot distinguish the syntax of object and pointer assignment, it's all determined by the types that get assigned. The difference with C++ is that it has no garbace collector and you end up with a memory leak because the object ptrObjA pointed to can not be deleted any more.
About your question:
Consider a C++ class:
class X {
int* pi;
unsigned count;
public:
X(X const&);
X& operator= (X const&);
~X();
};
Suppose each X object allocates it's own dynamic array of ints, the pointer to it gets stored in pi. Since C++ has no garbage collection, the X objects have to care themselves for their allocated memory, i.e. they have to destroy it manually:
X::~X() { delete[] pi; }
A copy constructor will copy the dynamic array of the original, so the two do not conflict while using the same array. This is called deep copy and is used equally in Java and C++:
X::X(X const& other) : pi(NULL), count(0) {
pi = new int[other.count]; //allocates own memory
count = other.count;
std::copy(other.pi, other.pi+count, pi); //copies the contents of the array
}
Now to the qoute in your question:
Consider two objects x1 and x2 and the assignment x1 = x2. If you leave everythign to the compiler, it will generate an assignment operator like this:
X& X::operator=(X const& other) {
pi = other.pi;
count = other.count;
}
In the first line x1.pi gets the pointer value of x2.pi. Like I explained in the section about copy assignment, this will lead to both pointers pointing to the same array, and the array previously owned by x1 will be lost in space, meaning you have a leak and odd behavior when both objects work on their shared array.
The correct implementation would be:
X& X::operator=(X const& other) {
delete[] pi; //1
pi = new int[other.count]; //allocates own memory
count = other.count;
std::copy(other.pi, other.pi+count, pi); //copies the contents of the array
}
Here you see what the quote says: First, the object is "cleaed up", i.e. the memory is freed, essentially doing what the destructor does ("instance has to be destroyed").
Then, the deep copy is performed, doing what the copy constructor does ("...and re-initialized").
This is called the "Rule of Three": If you have to write your own copy constructor (because the generated one does not what you want it to do), you will mostly have to write your own destructor and assignment operator as well. Since C++11 it has become the "Rule of Five", because you have move assignment and move construction that have to be considered as well.
In Java, if I declare,
MyClass obj;
Is obj called a "reference" or an "object". I am not instantiating class here.
obj is a Reference to an instance of MyClass.
Currently, that Reference is NULL because you haven't assigned it to refer to any instance.
Technically MyClass must be a subclass of Object, so it is possible to say that obj is a Reference to an instance of Object as well.
Reference: A variable that points to some object in memory.
It is stored in stack they can be contained in other objects (then they are not really variables, but fields), which puts them on the heap also.
Object: An instance of class that is created dynamically.
It is stored in heap
Example:
MyClassI aObj,aObj1;
aObj=new MyClass2();
At first line aObj and aObj1 are references
At second line aObj referencing to object of MyClass2(New operator creates an object of Myclass2 and its address is assigned to aObj).
To understand even better consider a class Car which has driverName as a member.
Car c1,c2;
c1.driverName="Andrew"
c2.driverName="Gabriel"
System.out.println(c1.driverName);//gives Andrew
System.out.println(c2.driverName);//gives Gabriel
c1=c2;
c2=null;
// gives gabriel because the address of c2 is copied to reference c1.
// the object is not nullified because c2 is just a reference when
// assigning null the address that is stored on c2 in nullified not
// the object it points..
system.out.println(c1.driverName);
In computer science, a reference is a
value that enables a program to
indirectly access a particular data
item, such as a variable or a record,
in the computer's memory or in some
other storage device. The reference is
said to refer to the data item, and
accessing that data is called
dereferencing the reference.
In computer science, an object is any
entity that can be manipulated by the
commands of a programming language,
such as a value, variable, function,
or data structure. (With the later
introduction of object-oriented
programming the same word, "object",
refers to a particular instance of a
class)
so obj is a reference and new MyClass() can be seen as an object
obj is a Reference of type MyClass. The current reference does not point to anything (ie: null).
Sometimes you'll hear people say "Design an method that takes an object as a parameter and..."
If you're new to programming, and especially with Java, such statements can lead to some confusion. These people are using the word "object" to refer to an instance of a class in very general OOP terms, not necessarily Java specific.
When we're talking specifics about Java and the code you have there, it is a reference to an instance of MyClass, which is NULL.
'obj' is a variable. It holds either a reference or null. If it holds a reference, that refers to an object.
In Java, all objects are accessed by reference, and you never have direct access to the object itself.
reference :- is a variable that has a name and can be used to access the contents of an object, A reference can be assigned to another reference passed to a method, or returned from a method. All references are the same size, no matter what their type is Like "Object object ;".
object:- is an entity that's exists in memory allocated by the Java run time environment, An object sits on the heap and does not have a name Like "Object object=new Object();".
so MyClass obj Here is A reference referred to Null.
We can summarize this principle with the following two rules:
The type of the object determines which properties exist within the object in memory.
The type of the reference to the object determines which methods and variables are accessible to the Java program.
The reference is a variable that has a name and can be used to access the contents of an object. A reference can be assigned to another reference, passed to a method, or returned from a method.
All references are the same size, no matter what their type is.
An object sits on the heap and does not have a name. Therefore, you have no way to access an object except through a reference. Objects come in all different shapes and sizes and consume varying amounts of memory. An object cannot be assigned to another object, nor can an object be passed to a method or returned from a method. It is the object that gets garbage collected, not its reference.
I have a function that returns a user-defined object. First I want to know if that object is returned by reference and what if it was private?
Also, how do I return it as Constant (final) reference because I don't want someone to mess with it? I'm so confused between returning an object and returning object.copy(); or object.clone();
In Java, You always return a reference (unless returned value is a primitive type such as int, float, char, ...).
So, if you don't want the returned object to be modified, you must return a full copy of it (you could use Clonable interface and clone method if your class defines it).
So, to answer your questions you have to at first know how Java passes Variables.
a Variable has a value:
int i = 1234;
Person p = new Person("Peter");
Now, the Variable i contains exactly 1234, while the Variable p contains the Memory Adress of the created Person.
so i contains 1234 and p contains the adress (let's say a4dfi3).
anyMethodYouLike(p);
System.out.println(p.getName());
public void anyMethodYouLike(Person somePerson) {
somePerson.rename("Homer");
}
so in this example, we give the Method anyMethodYouLike the Variable p... wait! we give the Method the value of the Variable (a4dfi3). The Method then calls rename on this Variable (which still has the same adress as p has, hence it modifies the same Person that p points to).
So, after the Method, the Name of the Person p points to, gets printed, which results in "Homer".
someOtherMethod(p);
System.out.println(p.getName());
public void someOtherMethod(Person somePerson) {
somePerson = new Person("Walter");
}
In THIS example we still give the adress of our Person called "Peter" to the Method. But this time, the Method creates a new Person in somePerson (therefore overriding the adress in somePerson to.. let's say 13n37s.
BUT! the Person at a4dfi3 wasn't changed! The print call still outputs "Peter" and not "Walter".
Now, let's see how this behaves with primitives:
someMethod(i);
System.out.println(i);
public void someMethod(int someInt) {
someInt++;
}
So, the Value of i (1234) gets passed to someInteger. Then someInteger gets incremented to 1235. But i is still 1234.
This is the big difference between Objects and primitives in Java.
Now to your questions:
1. As you can read here, yes Java always passes the Reference Adress of the Object.
2. If you don't want someone to mess with the values of your Objects, you HAVE to first create a new Object with that information (e.g with Cloneable and clone()), but it's a real mess because you have to make sure, that everything in your Object that is not primitive gets re-created, which is just awful when you have huge Tree-structures of Objects.
I hope I could help,
Ferdi265
What you should really realize is that there is nothing special about "passing" or "returning". Whenever you "pass" or "return" something, it just passes the value of the thing. Period. For any type. Whenever you "pass" or "return" something, it's exactly the same as simply assigning it to a variable.
However, what is the value of the thing you are passing or returning? That is where your confusion seems to lie. Your question asks about "returning an object"; however, such a thing does not make sense in Java. Objects are not values in Java. It is impossible to have a variable whose value is an object.
The only types in Java are primitive types and reference types. Hence the only values are primitives and references. (References are pointers to objects.) In Java, we only manipulate objects through references (pointers to objects). We cannot store an object in a variable; but we can store a reference (pointer to an object) in a variable. So when you talk about passing or returning objects, you are almost certainly instead talking about passing or returning references. And, as said before, there is nothing special about passing or returning references -- the value of the reference (a pointer) is passed or returned.
It returns the object's reference.
say suppose you have a method call like.
Object obj = makeObject();
which creates an Object and returns(which is the reference of the object created in the makeObject method).
1) Yes, it returns a reference to the object.
2) If the method is private, then it can only be called from within the class itself.
3) Making an object final does not stop others from calling methods on it. There are ways to make an object immutable by using packages and method visibility. (Look up how public, protected, and private work)
4) There is no Object.copy()
5) Object.clone() is a messy beast.
Say I set int A = int B. When I change A after, it will not change the value of B. But when I set a SomeClass A = SomeClass B, and I change A's contents (like a.cost), it changes B.cost as well. Can someone explain this to me?
I thought Java is assigned by value, not reference?
Yes, it does - but the value of A is a reference, not a copy of the object itself.
I like to give the following analogy...
Suppose two people both have my address: that's like two variables of type House in Java. Now one of them comes and paints my door red. The second person will still see the red door if they visit:
House jonsHouse = new House(); // Even the variable jonsHouse is only a reference
House firstAddressCopy = jonsHouse; // Just a copy of the reference
House secondAddressCopy = jonsHouse; // Just a copy of the reference
firstAddressCopy.paintDoor(Color.Red);
Color color = secondAddressCopy.getDoorColor(); // Now color will be red
Basically, remember a few rules and things will become clear:
The value of an expression in Java is never an object - only ever a reference or a primitive value
(Corollary of first point) A variable never holds an object - only ever a reference or a primitive value
Assignment (and argument passing) always copies the value, whether that value is a reference or a primitive value
I thought Java is assigned by value,
not reference?
What does "assigned by value" mean? Are you maybe confusing it with "pass by value/reference"?
At any rate, if you handle a class instance in Java, you are actually handling a reference to that class (much like a pointer in C/C++). Your assignment only copies the reference, so both A and B refer to the same instance, i.e. the data is shared, hence the result.
A is a reference to the object. So if you change the object internal state, it will be reflected to every other variable pointing to it.
If you re-assign A, then B will not change:
Foo a = new Foo();
Foo b = a;
a.bar = "bar"; // this is reflected in b
a = new Foo(); // b stays pointing to the previous Foo
a.bar = "baaar"; // b stays with a value of bar="bar"
(Java is pass by value. Check this article about it.)
In Java, your variables can be split into two categories: Objects, and everything else (int, long, byte, etc).
A primitive type (int, long, etc), holds whatever value you assign it. An object variable, by contrast, holds a reference to an object somewhere. So if you assign one object variable to another, you have copied the reference, both A and B point to the same object.
NOTE: Strings in Java are actually objects, not primitives, which beginners often assume.
Hope this helps
In java when you assign Object to Object its assign by reference.
Int is non an Object in java so when you assign int to int its assign by value.
In java, when you pass an object to a method as a parameter, it is actually passing a reference, or a pointer, to that object because objects in Java are references.
Inside the function, it has a pointer to that object which is a location in memory. I am wondering where this pointer lives in memory? Is a new memory location created once inside the function to hold this reference?
Within a function, a parameter reference is stored on the stack. The thing-referenced can live anywhere.
When some code calls a method, what normally happens is that space is made on the executing thread's stack, and this space is used to hold the parameters that are passed to the function. If one of the parameters "is an object", what's really in play is a reference to an object; that reference is copied onto the stack so that the called code can find it. It's important to recognize that the object itself is not copied, just the reference.
The prologue section of the called code will then typically allocate more space on the stack, for the method's own local variables, but underneath, the JVM has a pointer to the stack frame with all the parameters, so the called code can locate the object named by the parameter. Items created with 'new' will be allocated from the heap, and can persist even after the method exits, but all items allocated on the stack are dumped simply by moving the stack pointer back to where it was before the call.
Objects are not references, but you use references everywhere. e.g.
String a = "abc";
the a is a reference to a String. So references get passed around everywhere. Are they pointers ? No. A reference is more like a handle to an object. The JVM is at liberty to move around objects within memory. A pointer would have to change to reflect this. A reference doesn't. A reference could be modelled as a pointer to a pointer.
Every parameter of the function is passed by value - however, the parameter is not an object, but instead is a reference.
So the same object exists with two references to it.
String s = "my string"; // reference to this object created
doSomething(s); // in the doSomething function, a new reference to the same point of memory is passed by value
This means when I have my function void doSomething(String str) I work the same way as I do outside the function, except I have a different reference. Same object being referenced, but different reference. So if inside my function I do str = "different string"; that won't change s - s still points to the same point of memory it did the whole time - but now str instead of pointing to what s points to, now points to where the "different string" is stored.
for example in JFrame you can start like this:
public myFrame mF;
public void Panel1(myFrame mF) { your code ... }