This may be fundamental and be voted as off-topic.
However, as a student I have to know some of the fundamentals (which may be also considered non-fundamental).
If I create a new object someObject,
public class foo {
someObject bar;
private class someObject {
int data;
public someObject (int value) {
data = value;
}
}
}
without assigning any values to its field,
the memory address of the object foo seems to be null.
Within my knowledge, this does not make sense.
Isn't every object created regardless of it having data still be assigned to a memory address?
If I'm wrong (most surely), could someone elaborate more on this please?
Pretty simple:
You never create any Object. All you do is declare a variable. There isn't any Object created in the provided line - neither empty nor in any other state - , no memory allocated, except for the reference, which logically points to null.
Related
This question already has answers here:
Is Java "pass-by-reference" or "pass-by-value"?
(93 answers)
Closed 4 years ago.
I am confused about how Java deals with aggregation within objects, and in particular referencing of objects. It seems like objects will keep a reference to an aggregated object when it is passed as a parameter, rather than copying it like I've been lead to believe.
Say I have a basic class called Foo which contains a string attribute, print function, and setter for the text attribute.
public class Foo {
private String text;
public Foo(String text) {
this.text = text;
}
public void print() {
System.out.println(text);
}
public void setText(String text) {
this.text = text;
}
}
And a class called Bar which contains an attribute of type Foo, and a method called print which calls foos print method.
public class Bar {
private Foo foo;
public Bar(Foo foo) {
this.foo = foo;
}
public void print() {
this.foo.print();
}
}
If I define an instance of Foo, pass it into a new instance of Bar, and then call bars print method it will print "hello" as I expected. However if I then set the text of the original instance of foo to "Edited" using its setter method, bars print method will also print "Edited".
public static void main(String[] args){
Foo foo = new Foo("Hello");
Bar bar = new Bar(foo);
bar.print();
foo.setText("Edited");
bar.print();
}
Console Output
The Bar object appears to be keeping a reference to the Foo object even though I passed it as a parameter. I'm sure I am missing something trivial here, and I just wanted someone to explain this clearly.
"I'm sure I am missing something trivial here"
Not really. What you see is not a bug, it is a feature. Passing objects around in java means passing around references to them. Objects aren't "cloned" unless the code explicitly requests this through .clone(). Searching on this site for "is java pass-by-value or pass-by-reference" should help you find all the detailed explanation you need.
Reference copied, not object
It seems like objects will keep a reference to an aggregated object when it is passed as a parameter, rather than copying it like I've been lead to believe.
No, the object is not copied.
The reference (pointer) is copied when passed as an argument to a method. The object (the referent, the thing to which the pointer points) is not copied.
The pointer is really an address in memory someplace (though not seen as such by us Java programmers). That address, basically a number, is being copied when passed into the other method. But the object is left untouched, unaware of any references.
Here's a diagram of several Cat objects in memory. Three of the five are candidates for garbage-collection because they have no references remaining, no pointers pointing to them. At first Lilly Mae cat has one pointer pointing to it.
Cat c = new Cat( "Lilly Mae" ) ;
The c variable is not holding a Cat, it holds the address elsewhere in memory where you can find the Cat object. Think of that line as saying:
variable-holding-pointer-that-can-only-point-to-objects-of-class-Cat c = instantiate-new-object-of-type-Cat-and-return-a-pointer-to-its-location-in-memory( "Lilly Mae" ) ;
Then we pass that pointer as a argument to another method.
Human h = SubservientHumanLocator.findFirstAvailable() ;
h.feedCat( c ) ; // Passing a copy of the address of Lilly Mae to this other object’s method.
After the reference to the Cat is passed to the Human, we still have only one hungry cat. We did not clone the cat. We now have two references, both pointing to same original Cat object.
Here is a diagram of state before and after the Human::feedCat call.
After calling on the human to feed the cat, the variable c may fall out of scope. After feeding the cat, the Human object h will likely let its copied reference also fall out of scope. Then, if no other references had been made, and with no existing references remaining, our well-fed Cat object will become a candidate for garbage-collection.
One source I am studying defines an array as "a collection of variables under one name, where the variables are accessed by index numbers."
But then I realized that you can have an array of objects (or an array of pointers to objects, at least).
This got me to wonder what a variable is defined as in java, as I did not consider an object to be a variable. Jenkov Tutorials cites a variable as being "a piece of memory that can contain a data value."
And since I believe an object fits this definition, is an object considered a variable?
Calling an array a "collection of variables" is arguably stretching the definition already. But an array is certainly a collection of references that can be made to point to different objects in memory, and each such reference can reasonably be called a variable.
Asking "is an object a variable" is a little weird in the first place. In Object o = new Object(), o is clearly a variable, though remember it's a reference to an object in the heap, not the object itself.
Honestly, "variable" is a pretty flexible, ill-defined term -- is a field a variable? The return result of a method? It depends on who's talking and what fuzzy definition they're using today.
is an object considered a variable?
No, these are two distinct things.
The first one (the object) is the value and the second one (the variable) is a way to reference an object, generally to use it (invoking a series of method on it for example).
For example when you write :
new Dog()
You instantiate a Dog. Nice. But suppose you want feed it if it is hungry.
You cannot if you have not a way to chain a series of method on this object.
By storing the reference of the Dog in a dog variable you can do it :
Dog dog = new Dog();
if (dog.isHungry()){
dog.feed();
}
Jenkov Tutorials cites a variable as being "a piece of memory that
can contain a data value."
It says the same thing.
But this :
One source I am studying defines an array as "a collection of
variables under one name, where the variables are accessed by index
numbers."
is rather misleading.
An array is an object that has a state that contains, among other things, elements of the array.
The way which the elements are referenced in is a implementation detail of the Array class and I would not affirm that each element is stored in a specific variable.
An object is created when you call the constructor with the reserved word new.
For example:
Object a = new Object();
a will be the variable of that new object created and will go to reserved memory for that object. You are instantiating that new variable and that variable is associated with that object.
Hope might this will help you to understand it better...
class Bulb
{
private int w;
public void setWattage(int e)
{
w=e;
}
public int getWattage()
{
return w;
}
}
class Test
{
public static void main(String args[])
{
Bulb b[];
b=new Bulb[2];
b[0]=new Bulb();
b[1]=new Bulb();
b[0].setWattage(60);
b[1].setWattage(100);
System.out.println(b[0].getWattage());
}
}
here b[0] and b[1] are reference variables who have the address of two Bulb objects
In a class, I have:
private Foo bar;
public Constructor(Foo bar)
{
this.bar = bar;
}
Instead of creating a copy of bar from the object provided in the parameter, is it possible to include a pointer to bar in the constructor such that changing the original bar changes the field in this object?
Another way of putting it:
int x = 7;
int y = x;
x = 9;
System.out.print(y); //Prints 7.
It is possible to set it up so that printing y prints 9 instead of 7?
When a variable is used as argument to a method, it's content is always copied. (Java has only call-by-value.) What's important to understand here, is that you can only refer to objects through references. So what actually happens when you pass a variable referring to an object, is that you pass the reference to the object (by value!).
Someone may tell you "primitives are passed by value" and "non primitives are passed by reference", but that is merely because a variable can never contain an object to begin with, only a reference to an object. When this someone understands this, he will agree that even variables referring to objects are passed by value.
From Is Java "pass-by-reference" or "pass-by-value"?
Java is always pass-by-value. The difficult thing can be to understand that Java passes objects as references passed by value.
From http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
Java does manipulate objects by reference, and all object variables are references. However, Java doesn't pass method arguments by reference; it passes them by value.
In Java, there is no counter part to the C++ "reference type" for primitives.
Your last example works that way because int is a primitive, it is copied by value. In the first example, "this.bar" would hold a copy of the reference (sort of pointer) to bar. So if you change the original bar (internally), the change will be reflected in your class. Try it.
To get that behavior you could modify a member of an object:
public class Number{
int value;
Number(int value){
this.value = value;
}
public String toString() {
return "" + value;
}
}
You could then do:
Number x = new Number(7);
Number y = x;
x.value = 9;
System.out.println(y);//prints 9
Java never copies objects. It's easiest to think of in terms of for each "new" you will have one object instance--never more.
People get REALLY CONFUSING when they discuss this in terms of pass by reference/pass by value, if you aren't amazingly familiar with what these terms mean, I suggest you ignore them and just remember that Java never copies objects.
So java works exactly the way you wanted your first example to work, and this is a core part of OO Design--the fact that once you've instantiated an object, it's the same object for everyone using it.
Dealing with primitives and references is a little different--since they aren't objects they are always copied--but the net effect is that java is just about always doing what you want it to do without extra syntax or confusing options.
In order to keep the original value of member bar, you will need to implement Cloneable interface. Then before assigning a new value to the object, you will need to make a clone of it and pass the cloned value and assign new values to the cloned object. Here is a tutorial on how to do it http://www.java-tips.org/java-se-tips/java.lang/how-to-implement-cloneable-interface.html .
I've been reading many posts about this, all are full of answers that tend to counter the answer before it and they all seem to be by high ranked people so im very confused and would just like to know if this works:
public class Object{
private int someNumber = 5;
public void setSomeNumber(int newNumber){someNumber = newNumber;}
}
public class Main {
Object myObject = new Object();
public static void main(String[] args){
changeNumber(myObject);
}
void changeNumber(Object obj)
{
obj.setSomeNumber(10);
}
}
Would this change myObject.someNumber to 10?
My understanding is that obj is pointing to the same place in memory as myObject so calling its method useing obj is the same as calling it with myObject because obj is not just a copy of myObject?
I thought it was clear to me till i started reading threads on here about it lol
Edit: Thanks for correcting code, i just wrote it out in here as a example, didnt see the mistakes
Thanks guys. Also i was confused by people saying pass by value so i wasnt sure if it was passing the address in memory or not because to me thats passing a refrence so it became unclear to me.
You are correct. changeNumber() would change the someNumber variable of the object passed to it. You are passing a reference to the object itself, not a copy.
Although this code won't compile (you can't use Object, and can't access from static method non static data field), but I've got your question.
Basically you're right, and this is why:
In Java when you pass parameters into the method, they're passed by reference, but the reference itself is passed by value.
This is done for optimization reasons I believe.
So in fact, another reference is produces that points to the same Object in memory.
If you take a look on these references by themselves they're different, but they both point on the same object. So when you change the internal state of the object from within 'changeNumber' method, its goes to the object that reference 'obj' refers to and changes it.
The only exception is primitives - they aren't passed by reference, instead they're passed by value as you probably have learnt in other languages.
Once you get aware of what exactly goes on when you call methods and pass parameters to it this will stop confusing you :)
Hope this helps
You are right, java does manipulate objects by reference, and all object variables are references, and doesn't pass method arguments by reference but by value.
Take a look at this article and see the difference in behaviour between objects and method arguments in the examples provided.
I have a class (Literal). I need to be able to keep an intact Literal instance in memory throughout my application, and have a copy of it which I can alter. I have used two ways to do this:
class Literal implements Cloneable and override Object.clone() method.
Factory constructor:
public Literal(Literal lit){
this = lit;
}
In both cases copying doesn't work. Every change I make to the copy, changes the original. Does anybody have any idea what I'm doing wrong?
since Literal is not a integral type, variables of type Literal holds a reference to the actual value, so this = lit just copies the reference, so your behavior.
You must copy all the member fields recursively to do a "real" copy.
This article has been linked in the accepted answer to the question linked by Umesh in his comment, and I think it clears the conceptual problems you're hitting with your problem.
If you are going to use copy-constructor, then you will need to make a deep copy of every mutable member variable.
Say your Literal has member variables like this:
private String[] args;
private String s;
Then your copy-constructor would need to do something like this
public Literal(Literal l) {
// have to deep copy the array, otherwise both instances are sharing the reference
this.args = Arrays.copyOf(l.args, l.args.length);
// safe to just copy the reference, String is immutable
this.s = l.s;
}