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).
Related
enter image description hereWhen I'm learning array's knowledge, there are such descriptions saying array holds reference variables(not object itself) or primitives, as opposed to ArrayList holding an object. I want to confirm why ArrayList can hold object rather than reference variables. enter image description here
You're just taking everything out of context...
if you would read further in the second image then you'd understand that there exists primitve arrays (int[]) but no such thing as a primitive List (List<int>).
Instead you have to use wrapper classes (List<Integer>).
Then don't mess up the definition of Object and Object reference because in java you never can have an Object in place, you're always working with Object-references (and also with primitives to be really clear).
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.
I'm turning crazy on this one.
What I want to do is to get an object from an ArrayList, and add it in 3 others after modifying it.
The problem is that the object I get from my ArrayList is modified aswell when I modify the others... Can't figure out why, is this normal?
Code below:
final Product tmpRef = productsRef.get(i);
Product tmp = tmpRef;
tmp.setPos(products1.size());
Log.d("test2","tmpRef:"+tmpRef.getPos()+";tmp:"+tmp.getPos());
Product tmp2 = tmpRef;
tmp2.setPos(products2.size());
Log.d("test2","tmpRef:"+tmpRef.getPos()+";tmp:"+tmp.getPos()+";tmp2:"+tmp2.getPos());
Product tmp3 = tmpRef;
tmp3.setPos(products3.size());
Log.d("test2","tmpRef:"+tmpRef.getPos()+";tmp:"+tmp.getPos()+";tmp2:"+tmp2.getPos()+";tmp3:"+tmp3.getPos());
tmp.setPos(products1.size());
"pos" is just a simple int, with a getter/setter.
LogCat output:
03-21 09:56:14.926: D/test2(6200): tmpRef:9;tmp:9
03-21 09:56:14.926: D/test2(6200): tmpRef:7;tmp:7;tmp2:7
03-21 09:56:14.926: D/test2(6200): tmpRef:0;tmp:0;tmp2:0;tmp3:0
With #FD_, #blackbelt and #Guidobaldo da Montefelt's explainations, I ended creating a simple new Porduct's constructor to be able to copy the object, and not only the reference. Thanks guys.
Essentially, you just store references in your ArrayList, so it does not matter whether you use something like Product tmp = tmpRef;. tmp still points to the same object, thus changes are applied to both.
In this case, final just means that a pointer cannot be changed once it has been set.
Just search for deep copy java for possible solutions.
final Product tmpRef
means that the Object's reference of tmpRef can not be change. Meaning that you can not do
tmpRef = null;
or
tmpRef = anotherProdocut;
after
final Product tmpRef = productsRef.get(i);,
but the content of the object could change if its member are not final.
Adding to what #blackbelt said, you are getting confused between
"final" and "immutable" concepts. If you don't want the "object's
value" to change, then you have to make it immutable (java doesn't
provide any built-in mechanism for this). final merely prevents you
from reassigning the reference to another object.
EDIT:
1. final - if a "reference" is made final, then you cannot reassign it to point to something else. if a primitive is made final, then it's value cannot change.
eg:
final int i=5;
i=10; // error
final List<String> l = new ArrayList<String>();
l.add("one"); // works
l =new ArrayList<String>() // fails
2. Immutable - you cannot change the values of attributes of the object.
if list l were immutable, then
List<String> l = new ArrayList<String>();
l.add("one"); // fails, depending on your definition/implementation of immutablility
l =new ArrayList<String>() // l is not final, so it works fine
Before doing such a thing, you should really try to understand the difference between references and objects, and more deeply, the difference between copying a reference vs copying an object.
Product is an object stored in a memory zone called Heap. "tmpRef" is a reference that contains the address that points to that object.
This code:
Product tmp = tmpRef;
does not copy any "Product" objects but it simply assign the tmpReference in a new reference variable called tmp. So, you´ll have 1 Object pointed by 2 references. Passing a reference (4 bytes in a 32bit system) is very cheap. That´s why you can pass objects in your methods as parameters. It´s what it is called "copy by reference".
The final keyword means that the reference is immutable, not the Product object.
Probably you have confusion because these logic is not applied to primitive objects, where reference copy does not exist, but primitives are always copied by value, and never by reference.
So if you want to do not change the original object, you do need to create new Product objects in the heap.
Hope this helps.
This is a little confusing question for me to express, but I'll do my best.
So:
ArrayList<Object> fieldList = new ArrayList<Object>();
I then dump a lot of different variables to this array:
fieldList.add(objectsURL); //string
fieldList.add(X); //int
fieldList.add(Y); //int
...
If I change the variable, the values in the array change
too-confirming the array stores a reference to the memory, rather
then value itself.
However, if I then retrieve data from the array then set that...
Object object = ((String)this.fieldList.get(0));
Then set object
object = "meeep!"
objectsURL is not set to "meep!" but rather it retains its original
value.
I assume this is because the "object" is not referencing the original
variable anymore, that instead its pointing to a new immutable string
in the memory.
All expected Java behavior I think....but then, how would I go about
setting the actual original variable? is this possible in java?.
So, in other words. Given only access to "fieldList" is it possible to change the value of
"objectsURL"?
So, if:
String objectsURL = "www.google.com"
fieldList.add(objectsURL);
Is there a way to set objectsURL to "www.stackoverflow.com" using only a reference from fieldList?
I dont want to change the fact that fieldList contains "objectsURL", I want to change what string the variable "objectsURL" actualy contains.
If not, is there an alternative method to achieve the same thing?
I hope my question explains the problem well enough.
My use-case is trying to make a serialization/
deserialization system for a bunch of my objects. I was hoping to put
all the fields into a arraylist I could retrieve for both reading and
writing....thus avoiding having to hard-code long lists of
field[0]=blah and blah=field[0] and then going though constant pains
of needing to renumber them each time I add a new field before
another.
(I cant use Javas inbuilt serialization, as I am using GWT and this is client side only.)
Thanks,
I assume this is because the "object" is not referencing the original variable anymore, that instead its pointing to a new immutable string in the memory.
Correct, each time you use the assignment operator = on an object you change the object it refers to, not the object itself.
To change the values in the List, you use the .set method of an ArrayList
this.fieldList.set(0, newValue);
Since your variable is a String, there is no way you can change the String-variable through the list
Your alternatives:
using a char-array
List myList = new ArrayList();
char[] charArray = "My String".toCharArray();
myList.add(charArray);
charArray[0] = 'A';
String theString = new String(myList.get(0)); // "Ay String"
If you use a char-array, make sure that the length of the array is enough to contain the number of characters you want to have in the future, because to change the length of the array you will need to create a new array (array lists can be expanded dynamically, arrays can not)
Embed the String inside your own class (I have ignored getters and setters here)
class MyString {
public String value;
public MyString(String value) {
this.value = value;
}
}
MyString myStr = new MyString("some value");
list.add(myStr);
((MyString) list.get(0)).value = "a new value";
System.out.println(myStr.value); // will print "a new value"
Strings are immutable, so it is impossible to change the contents of a String object. Also, you cannot use the list to change what object the reference variable objectsURL points to. To achieve what you want, you will need to create a custom class that has a String member. You can then store instances of this class in a List and change the String references to via the references in the list. The changes will then be reflected in any other reference variables which refer to the objects in the list.
First, you declare a variable 'object' and assign some Object out of the ArrayList. Later you assign some other object "meeep!" to this variable. There is no reason that your 'object' variable is related to the ArrayList.