This question already has answers here:
What are classes, references, and objects?
(12 answers)
Closed 6 years ago.
Exactly what are the differences between variables, objects, and references?
For example: they all point to some type, and they must all hold values (unless of course you have the temporary null-able type), but precisely how are their functions and implementations different from each other?
Example:
Dog myDog = new Dog(); //variable myDog that holds a reference to object Dog
int x = 12; //variable x that hold a value of 12
They have the same concepts, but how are they different?
(Just to be clear, the explanation I'm giving here is specific to Java and C#. Don't assume it applies to other languages, although bits of it may.)
I like to use an analogy of telling someone where I live. I might write my address on a piece of paper:
A variable is like a piece of paper. It holds a value, but it isn't the value in itself. You can cross out whatever's there and write something else instead.
The address that I write on the piece of paper is like a reference. It isn't my house, but it's a way of navigating to my house.
My house itself is like an object. I can give out multiple references to the same object, but there's only one object.
Does that help?
The difference between a value type and a reference type is what gets written on the piece of paper. For example, here:
int x = 12;
is like having a piece of paper with the number 12 written on it directly. Whereas:
Dog myDog = new Dog();
doesn't write the Dog object contents itself on the piece of paper - it creates a new Dog, and then writes a reference to the dog on that paper.
In non-analogy terms:
A variable represents a storage location in memory. It has a name by which you can refer to it at compile time, and at execution time it has a value, which will always be compatible with its compile-time type. (For example, if you've got a Button variable, the value will always be a reference to an object of type Button or some subclass - or the null reference.)
An object is a sort of separate entity. Importantly, the value of a variable or any expression is never an object, only a reference. An object effectively consists of:
Fields (the state)
A type reference (can never change through the lifetime of the object)
A monitor (for synchronization)
A reference is a value used to access an object - e.g. to call methods on it, access fields etc. You typically navigate the reference with the . operator. For example, if foo is a Person variable, foo.getAddress().getLength() would take the value of foo (a reference) and call getAddress() on the object that that reference refers to. The result might be a String reference... we then call getLength() on the object that that reference refers to.
I often use the following analogy when explaining these concepts.
Imagine that an object is a balloon. A variable is a person. Every person is either in the value type team or in the reference type team. And they all play a little game with the following rules:
Rules for value types:
You hold in your arms a balloon filled with air. (Value type variables store the object.)
You must always be holding exactly one balloon. (Value types are not nullable.)
When someone else wants your balloon, they can blow up their own identical one, and hold that in their arms. (In value types, the object is copied.)
Two people can't hold the same balloon. (Value types are not shared.)
If you want to hold a different balloon, you have to pop the one you're already holding and grab another. (A value type object is destroyed when replaced.)
Rules for reference types:
You may hold a piece of string that leads to a balloon filled with helium. (Reference type variables store a reference to the object.)
You are allowed to hold one piece of string, or no piece of string at all. (Reference type variables are nullable.)
When someone else wants your balloon, they can get their own piece of string and tie it to the same balloon as you have. (In reference types, the reference is copied.)
Multiple people can hold pieces of string that all lead to the same balloon. (Reference type objects can be shared.)
As long as there is at least one person still holding the string to a particular balloon, the balloon is safe. (A reference type object is alive as long as it is reachable.)
For any particular balloon, if everyone eventually lets go of it, then that balloon flies away and nobody can reach it anymore. (A reference type object may become unreachable at some point.)
At some later point before the game ends, a lost balloon may pop by itself due to atmospheric pressure. (Unreachable objects are eligible for garbage collection, which is non-deterministic.)
You can think of it like a answering questions.
An object is a what...
It's like any physical thing in the world, a "thing" which is recognizable by itself and has significant properties that distinguishes from other "thing".
Like you know a dog is a dog because it barks, move its tail and go after a ball if you throw it.
A variable is a which...
Like if you watch your own hands. Each one is a hand itself. They have fingers, nails and bones within the skin but you know one is your left hand and the other the right one.
That is to say, you can have two "things" of the same type/kind but every one could be different in it's own way, can have different values.
A reference is a where...
If you look at two houses in a street, although they're have their own facade, you can get to each one by their one unique address, meaning, if you're far away like three blocks far or in another country, you could tell the address of the house cause they'll still be there where you left them, even if you cannot point them directly.
Now for programming's sake, examples in a C++ way
class Person{...}
Person Ana = new Person(); //An object is an instance of a class(normally)
That is to say, Ana is a person, but she has unique properties that distinguishes her from another person.
&Ana //This is a reference to Ana, that is to say, a "where" does the variable
//"Ana" is stored, wether or not you know it's value(s)
Ana itself is the variable for storing the properties of the person named "Ana"
Jon's answer is great for approaching it from analogy. If a more concrete wording is useful for you, I can pitch in.
Let's start with a variable. A variable is a [named] thing which contains a value. For instance, int x = 3 defines a variable named x, which contains the integer 3. If I then follow it up with an assignment, x=4, x now contains the integer 4. The key thing is that we didn't replace the variable. We don't have a new "variable x whose value is now 4," we merely replaced the value of x with a new value.
Now let's move to objects. Objects are useful because often you need one "thing" to be referenced from many places. For example, if you have a document open in an editor and want to send it to the printer, it'd be nice to only have one document, referenced both by the editor and the printer. That'd save you having to copy it more times than you might want.
However, because you don't want to copy it more than once, we can't just put an object in a variable. Variables hold onto a value, so if two variables held onto an object, they'd have to make two copies, one for each variable. References are the go-between that resolves this. References are small, easily copied values which can be stored in variables.
So, in code, when you type Dog dog = new Dog(), the new operator creates a new Dog Object, and returns a Reference to that object, so that it can be assigned to a variable. The assignment then gives dog the value of a Reference to your newly created Object.
new Dog() will instantiate an object Dog ie) it will create a memory for the object. You need to access the variable to manipulate some operations. For that you need an reference that is Dog myDog. If you try to print the object it will print an non readable value which is nothing but the address.
myDog -------> new Dog().
Related
This question already has answers here:
Modify list has an affect on another list in java
(2 answers)
Closed 1 year ago.
While writing a piece of code, I observed an unusual behaviour.
There is a class object obj1 which has an array list of another class object obj2 called as list1. See the code for reference:
PriorityQueue<Obj2> pq = new PriorityQueue<>(Comparator);
pq.addAll(new ArrayList<>(obj1.getList()));
Obj2 obj2 = pq.poll();
obj2.setField("any value");
System.out.println(obj2);
System.out.println(obj1.getList().get(0));
Both of the sout statement above prints the value.
Why is this happening? I changed the value of obj2 reference in pq and not in Obj1 itself
While adding elements to the pq, if we don't use new ArrayList<>() then it's understandable if the both the references are pointing to same object but I have created a new ArrayList to add in pq, still this happening.
How does java handle object references while dealing with ArrayLists?
It's all references. Everything. All the way down.
Except primitives. The primitive types are int, long, double, float, byte, short, boolean, and char. That's it. The list is hardcoded and you can't make new primitive types.
So, aside from those, it is all pointers. When you write:
MyFoo foo = new MyFoo();
That's just syntax sugar for 2 separate statements:
MyFoo foo;
foo = new MyFoo();
Imagine the heap is a gigantic whiteboard.
So what's happening here is:
MyFoo foo; This makes a little postit for yourself. This postit is named 'foo', it is yours, you can't hand it to anybody else ('local variable' - hence the name 'local'), and it has just enough room to write a coordinate for that gigantic whiteboard, that's all it can hold. It is blank, for now.
new MyFoo() this goes to the whiteboard, finds some blank space on it anywhere, and writes a box, and then in that box, room for all the fields of your MyFoo class. If any fields are non-primitive, it's just enough room to write coordinates. (Each and every object is its own little box on this whiteboard and could be anywhere on it).
The expression new MyFoo() resolves to the coordinates of where you made that box. You then assign this to foo, so, copy down the location of that box on your little postit.
If you then do:
someMethod(foo);
What that does is: Grabs a new postit, copies those coordinates over to the new postit, and then hands the postit off to someMethod. Specifically:
Even if someMethod changes foo directly (foo =), that is: "They scratch out what was on the postit you gave them and write something new on it", which obviously has no effect whatsoever on your postit.
Once that method is done, they burn the postits. You never get them back. Which is fine, you gave them a copy.
If they FOLLOW the coordinates on that postit and take out their pen and edit the whiteboard, and then later on your follow YOUR postit, you will observe what they changed! . and [] are the dereference operators: That's java-ese for: "Take those coordinates, go over to the whiteboard and find the box, and now we do something to the stuff in the box', whereas = is "edit the postit, scratching out what was there and writing something else in".
With all that context:
obj1.getList() gets you the coordinates to the list object. This list object is simply a big sack of coordinates - of postits. NOT a list of Obj1s! A list of Obj1 references - of coordinates.
new ArrayList<>(that) makes a new arraylist (new box on the whiteboard), that constructor will dutifully copy each and every COORDINATE over. It does not copy each object. It can't, java has no idea how to copy arbitrary objects, and Lists can hold anything, so it doesn't know how.
You then 'poll' the top coordinate from this newly created list. Which is the same coordinate as what obj1.getList() has.
You then go to the whiteboard, following this coordinate (obj2.setField - I see a dot, so, that's 'follow the coords and get out your whiteboard pen'), and modify what is there.
Hopefully that clears up how it works. Keep thinking of that whiteboard. When reasoning about this stuff.
Solutions
The simplest solution is to adopt immutables as much as is reasonable. An immutable object is, effectively, the notion of writing the object in permanent marker. A string is immutable. it has no set or add methods at all. For example, str.toLowerCase() does not lowercase the string that str is pointing at. That method makes a new string instead. It's the equivalent of going to the whiteboard which has "hEllo!" written on it someplace, and then instead of wiping out the E and writing an e in its place (that'd be mutating, and no method in string lets you do this), toLowerCase() just draws a new little box on the whiteboard somewhere and copies the characters over, lowercasing them on the fly. The toLowerCase() call then returns the location of this new box.
If you apply the same ideas to public class Obj1, this problem goes away. So, don't call .setField, call .withField (which makes a clone but with that one field changed) or some such.
If that's not an option, you'd have to deep-clone the list, yes. This is incredibly annoying, because how deep does deep-clone mean? ArrayList itself can't simply deep-clone, you'd have to write it yourself. Something like:
List<Obj1> clone = new ArrayList<>();
for (Obj1 o : original) clone.add(new Obj1(o));
And you'd have to write the Object1(Object1 original) {} constructor yourself, copying each field. And, of course, for each non-primitive field pointing at a mutable object, you'd have to clone that too.
The JavaDoc for ArrayList(Collection<? extends E> c) says:
Constructs a list containing the elements of the specified collection, in the order they are returned by the collection's iterator.
It doesn't say "copy".
There's also no "deep copy" mechanism in Java. Even if you use Object.clone (which in general you shouldn't), you will only copy the references inside this object. The references itself will still point to the original contents.
For example:
class Obj {
String a;
int b;
OtherObj c;
}
In memory this will look like this:
[Reference To String a] [Value of int b] [Reference to OtherObj c]
(only primitive types will be stored directly inside an object, everything else is a Class and will be stored as a reference. Even the primitive wrappers like Integer are classes and will be stored as references, but those primitive wrappers are immutable, though you can't change their inner values)
Though if you create a copy of this object, you will get a new memory location for the copy, but that memory location then will contain the same data: [Reference To String a] [Value of int b] [Reference to OtherObj c].
The same happens with ArrayList. In memory it looks like this:
[Reference to Element 1] [Reference to Element 2] [Reference to Element 3] ...
And if you copy that list, you'll get a copy of that part in memory. But all the references will still point to the very same objects.
This all may change with the introduction of Project Valhalla and Value types. But that may still take months or years.
Most of the linked list implementations in C++ are like this, a pointer reference will be used as the type for the "next" node
class Node {
public:
int data;
Node* next;
}
But for languages like C#, Java and Python, why pointer is is not directly used? I could see only this kind of implementation:
// C#
class Node {
int data;
Node next;
}
// Java
class Node {
int data;
Node next;
}
What is the underlying difference? Ofcourse Java doesn't support pointers, but what about c#?
CPP"s Node* is equivalent to java's Node, and I'm pretty sure C#'s Node as well. In java, all primitives are the direct value. The primitives are int, long, short, byte, char, double, float, and boolean. These are passed directly, by value: If you call a method passing 5, 5 is pushed onto the stack. If the method you invoke changes their value, the caller can't tell.
But aside from that hardcoded list of primitives, all other types are called references which is just java-ese for pointers - except in java, you can't do pointer arithmatic. at all. You can't ask for 'the memory location 5 higher than where-ever this object lives', like you can do in C.
Here's a trivial example:
class Example {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("Hello!");
System.out.println(list);
example1(list);
System.out.println(list);
example2(list);
System.out.println(list);
}
static void example1(List<String> in) {
list.add("World!");
}
static void example2(List<String> in) {
in = new ArrayList<String>();
in.add("Bye!");
}
}
This will print:
[Hello!]
[Hello!, World!]
[Hello!, World!]
example1 never changes the variable (The reference), it merely 'dereferences it' (follows the pointer), thus the changes you make are observed in the caller.
But example2 has no effect on main's list variable: It reassigns the variable (makes a new object and then updates its reference to point at this new object). example1's list doesn't change; its pointer doesn't change.
It's like treasure maps: Everybody has a copy of the treasure map, but not of the treasure. in.add is like: "Follow the map, open the treasure chest, put a new item in". in = new ArrayList is: "Make a new treasure chest, bury it in the sand, wipe out this treasure map, and now write the location of this newly buried treasure chest on it". If I have a copy of your map, if you follow your copy and add to the treasure then I'll see that if I later follow my map. But if you make an entirely new map, then whatever you do to the treasure at your new location is never going to be noticed by me.
This matches C++'s behaviour.... at least, for Node*. Not for Node.
What is the underlying difference?
Probably none at all. At the machine-code level, each node contains the address of the next node in the chain.
The question is, rather, about how languages represent objects in source code. Is a variable declaration written as Foo bar (for example) going to be an actual instance of the type Foo or is it going to be a way to get at (handle, pointer, reference) the actual instance. If it's the actual instance, your language probably also needs some syntax to describe not-the-instance but way-to-get-at-the-instance. Perhaps more than one way (Foo*, Foo& in C++).
The possibility of different approaches is one reason why we have different programming languages.
In C++ variables (objects) can be passed by three ways:
by value
by pointer
by reference
(all of them are in reality passed by value, but very specific one)
In e.g. Java, objects are always passed by reference, while primitives by value. There are no pointers or explicit references in Java.
In C++ when you stop needing an object, you need to use delete to remove it. In Java, you just need to replace variable or just don't use it - GB will remove it for you.
After reading the posted answers and other stackoverflow stuffs related to references and pointers like this one C++ references Vs C# references
This is what Makes more sense to me,
C# References are Managed references. But in C++ there is no such
manged environment hence we need to allocate and carefully
de-allocate the memory. In C# this will be manged automatically by
GC. So it is recommended to use references where ever possible rather
than directly using pointers.
Similar to C++ Pointers, C# can also hold nulls. C++ pointers hold
address of a memory location, C# References holds the address of
another object in the memory.
In C# we can use pointers only under unsafe scope, and in java there is no such pointer concepts.
Taking all this into account we can use references rather than pointers for programming languages that execute in a managed environment.
Feel free to edit if this answer can be further improved!
This question already has answers here:
What are classes, references, and objects?
(12 answers)
Closed 6 years ago.
Exactly what are the differences between variables, objects, and references?
For example: they all point to some type, and they must all hold values (unless of course you have the temporary null-able type), but precisely how are their functions and implementations different from each other?
Example:
Dog myDog = new Dog(); //variable myDog that holds a reference to object Dog
int x = 12; //variable x that hold a value of 12
They have the same concepts, but how are they different?
(Just to be clear, the explanation I'm giving here is specific to Java and C#. Don't assume it applies to other languages, although bits of it may.)
I like to use an analogy of telling someone where I live. I might write my address on a piece of paper:
A variable is like a piece of paper. It holds a value, but it isn't the value in itself. You can cross out whatever's there and write something else instead.
The address that I write on the piece of paper is like a reference. It isn't my house, but it's a way of navigating to my house.
My house itself is like an object. I can give out multiple references to the same object, but there's only one object.
Does that help?
The difference between a value type and a reference type is what gets written on the piece of paper. For example, here:
int x = 12;
is like having a piece of paper with the number 12 written on it directly. Whereas:
Dog myDog = new Dog();
doesn't write the Dog object contents itself on the piece of paper - it creates a new Dog, and then writes a reference to the dog on that paper.
In non-analogy terms:
A variable represents a storage location in memory. It has a name by which you can refer to it at compile time, and at execution time it has a value, which will always be compatible with its compile-time type. (For example, if you've got a Button variable, the value will always be a reference to an object of type Button or some subclass - or the null reference.)
An object is a sort of separate entity. Importantly, the value of a variable or any expression is never an object, only a reference. An object effectively consists of:
Fields (the state)
A type reference (can never change through the lifetime of the object)
A monitor (for synchronization)
A reference is a value used to access an object - e.g. to call methods on it, access fields etc. You typically navigate the reference with the . operator. For example, if foo is a Person variable, foo.getAddress().getLength() would take the value of foo (a reference) and call getAddress() on the object that that reference refers to. The result might be a String reference... we then call getLength() on the object that that reference refers to.
I often use the following analogy when explaining these concepts.
Imagine that an object is a balloon. A variable is a person. Every person is either in the value type team or in the reference type team. And they all play a little game with the following rules:
Rules for value types:
You hold in your arms a balloon filled with air. (Value type variables store the object.)
You must always be holding exactly one balloon. (Value types are not nullable.)
When someone else wants your balloon, they can blow up their own identical one, and hold that in their arms. (In value types, the object is copied.)
Two people can't hold the same balloon. (Value types are not shared.)
If you want to hold a different balloon, you have to pop the one you're already holding and grab another. (A value type object is destroyed when replaced.)
Rules for reference types:
You may hold a piece of string that leads to a balloon filled with helium. (Reference type variables store a reference to the object.)
You are allowed to hold one piece of string, or no piece of string at all. (Reference type variables are nullable.)
When someone else wants your balloon, they can get their own piece of string and tie it to the same balloon as you have. (In reference types, the reference is copied.)
Multiple people can hold pieces of string that all lead to the same balloon. (Reference type objects can be shared.)
As long as there is at least one person still holding the string to a particular balloon, the balloon is safe. (A reference type object is alive as long as it is reachable.)
For any particular balloon, if everyone eventually lets go of it, then that balloon flies away and nobody can reach it anymore. (A reference type object may become unreachable at some point.)
At some later point before the game ends, a lost balloon may pop by itself due to atmospheric pressure. (Unreachable objects are eligible for garbage collection, which is non-deterministic.)
You can think of it like a answering questions.
An object is a what...
It's like any physical thing in the world, a "thing" which is recognizable by itself and has significant properties that distinguishes from other "thing".
Like you know a dog is a dog because it barks, move its tail and go after a ball if you throw it.
A variable is a which...
Like if you watch your own hands. Each one is a hand itself. They have fingers, nails and bones within the skin but you know one is your left hand and the other the right one.
That is to say, you can have two "things" of the same type/kind but every one could be different in it's own way, can have different values.
A reference is a where...
If you look at two houses in a street, although they're have their own facade, you can get to each one by their one unique address, meaning, if you're far away like three blocks far or in another country, you could tell the address of the house cause they'll still be there where you left them, even if you cannot point them directly.
Now for programming's sake, examples in a C++ way
class Person{...}
Person Ana = new Person(); //An object is an instance of a class(normally)
That is to say, Ana is a person, but she has unique properties that distinguishes her from another person.
&Ana //This is a reference to Ana, that is to say, a "where" does the variable
//"Ana" is stored, wether or not you know it's value(s)
Ana itself is the variable for storing the properties of the person named "Ana"
Jon's answer is great for approaching it from analogy. If a more concrete wording is useful for you, I can pitch in.
Let's start with a variable. A variable is a [named] thing which contains a value. For instance, int x = 3 defines a variable named x, which contains the integer 3. If I then follow it up with an assignment, x=4, x now contains the integer 4. The key thing is that we didn't replace the variable. We don't have a new "variable x whose value is now 4," we merely replaced the value of x with a new value.
Now let's move to objects. Objects are useful because often you need one "thing" to be referenced from many places. For example, if you have a document open in an editor and want to send it to the printer, it'd be nice to only have one document, referenced both by the editor and the printer. That'd save you having to copy it more times than you might want.
However, because you don't want to copy it more than once, we can't just put an object in a variable. Variables hold onto a value, so if two variables held onto an object, they'd have to make two copies, one for each variable. References are the go-between that resolves this. References are small, easily copied values which can be stored in variables.
So, in code, when you type Dog dog = new Dog(), the new operator creates a new Dog Object, and returns a Reference to that object, so that it can be assigned to a variable. The assignment then gives dog the value of a Reference to your newly created Object.
new Dog() will instantiate an object Dog ie) it will create a memory for the object. You need to access the variable to manipulate some operations. For that you need an reference that is Dog myDog. If you try to print the object it will print an non readable value which is nothing but the address.
myDog -------> new Dog().
I know how C-style languages store the data in a variable. They use one or two blocks on the stack, and in the case of objects space is also allocated on the heap, for its fields. But where does java store whether two blocks make a double or an int? How does it know that a particular object reference in the stack points to an object.
The thought that spawned this question is what happens if I do
String s;
If I understand correctly, this creates an object reference in the stack that is set to null, so two bytes of zeros, and no corresponding space on the heap. If so, how does Java "remember" that this reference belongs to a String?
I can imagine that remembering types isn't necessary, and the bytecode just operates on raw data, and we know it does so correctly, because it compiles. On the other hand, that sounds like type erasure, which leads to lots of corner cases and unsafety. If this is the case, why is the type erasure on generics different from type erasure on the primitives and objects themselves? (ie. for the latter, you never ever have to think about it, and with generics it crops up all the time).
NB: I say C-style, because I assume the solution is the same for all languages in that family. If there are different approaches, I'd like to know about the differences as well.
If String s is
a variable inside a method, the bytecode is compiled with the knowledge that that reference is a String.
a variable in a class, static or non-static, then the class definition includes the knowledge that that field holds a String, though that's almost never used -- it's not really necessary.
Each object in Java has a few bytes allocated that refer to its own type. (This is not stored in the reference -- it's stored in the object itself.)
When you do this:
String s;
In Java, it doesn't occupy the heap, it only keeps data of its type in the bytecode, if to associate to it with heap object of the same type later on.
The heap is occupied once new keyword is used explicitly (or used implicitly in case of String, you can look at it here ).
String s = "foo"; // or
String s = new String("foo"); // or
MyObject myObject = new MyObject();
^
|_ _ _ _ Right here
Check this out.
hey people,
I have created a class which extends application to share certain variables. Within each activity I then use an object of that class (globalstate) as so:
gs = (GlobalState) getApplication();
I then declare local variable which reference the shared ones such as:
boolean localStr = gs.str;
Now I am under the impression this would be passed a a reference and therefore any change to localStr would be reflected in str within globalstate. However this does not seem to be the case.
Some variables created in this manor such as an array of object seem to be passed as reference and therefore any changes are reflected within globalstate however for almost every other variables (booleans, strings & ints) it seems the changes aren't reflected and therefore are being copied rather than referenced.
Have I done something wrong or is this how android works, if so how can i pass by reference? Thanks.
boolean is a value type, Java doesn't use a reference to store it. It's the same for all Java primitive types (int, long, ...). Strings are different, they are reference types but are immutable as explained by Johan Sjöberg.
That's why when using an ArrayList (for example) you will get an error if you try to use a value type like new ArrayList<boolean>(). But new ArrayList<Boolean>() will work because Boolean is a reference type, not a value type.
To avoid your problem you should use your reference everywhere (use gs.str instead of creating a local variable, localStr). I can explain it better if you don't really understand what I'm saying.
That's not only how android works, that's how java works. Strings are immutable, meaning they cannot be changed. Every time you try and modify a string a new string is created; hence the following code will leave the string named first unchanged:
String first = "first"; // First points to mem address e.g., 0x1
String second = first; // Second also does
second = "something else"; // Second now points to 0x2, first still to 0x1
It's exactly the same behaviour for all primitive types (int, boolean etc).
However, when you pass a List of objects, alterations of the list contents will be changed everywhere. This is since your objects share the same list reference (which itself doesn't change, only it's contents).