For the code given what will be stored in ArrayList? What are shallow pointers in Java?

Suppose we have three Bear objects: momma, poppa, and baby. We create a "bears" ArrayList and add pointers to the three bears to the ArrayList.

// Create three bears 
Bear momma = new Bear();
Bear poppa = new Bear(); 
Bear baby = new Bear(); 
 
// Create an ArrayList, add the three Bear pointers 
ArrayList bears = new ArrayList();
bears.add(momma); 
bears.add(poppa);
bears.add(baby);

The above code produces the memory structure shown in the document.

Notice that the line bears.add(momma) does not add a copy of the momma Bear object to the ArrayList. Instead, it just adds a pointer to the momma Bear object to the ArrayList. It is common in Java to have such "shallow" pointers to an object – there is one object with many pointers spread around pointing to it.

For memory structure please refer to the diagram on page 3 of the document given below: Document

My doubts,

1)Can someone explain what the above paragraph is trying to say?

  1. What is the meaning of shallow pointer in java as stated in the document?

  2. what is exactly stored in the ArrayList. In the image showing the structure, it is shown that there are two pointers to each element in ArrayList.

From my knowledge, ArrayLists can only store reference variables to objects. However, what is the pointer that points from inside the blocks in the ArrayList.

What is it that is stored in ArrayLists?


Solution 1:

Bear momma = new Bear();

This code is shorthand for this:

Bear momma; [1]
new Bear(); [2]
momma = that thing; [3]

The first line creates a new variable, and names it momma. In java, all variables are tiny. Think post-it note with a title. So, this grabs a post-it note, writes a title on it, and leaves it blank.

The second line makes an entire bear, which is considerably larger than a post-it note. Remember that: If you want a new bear, new Bear() needs to be executed by you or somebody else's code.

The third line simply writes the address of where the bear lives on your post-it.

Post-its are tiny; they have enough room for a primitive (int, long, byte, double, float, short, boolean, character - that's all the primitives, hardcoded in the language).. or an address.

Whenever you call a method, you make a copy of your postit (postits are small and you have plenty) and hand the copy to the method. When the method is done, it tosses those postits in the trash.

Let's try some stuff. Let's say bears have a setName method.

Bear bear1 = new Bear();
Bear bear2 = bear1;
bear1.setName("Bruno");
System.out.println(bear2.getName());

This will print Bruno! - we have 2 postits, both with the same address on it. There is only one bear.


Bear bear = new Bear();
bear.setName("Bruno");
test(bear);
System.out.println(bear.getName());

public void test(Bear bear) {
  bear.setName("Brenda");
}

This will print "Brenda". We made a new bear, then we have a post-it with the address to this bear. Then we make a copy of this postit, hand it to the test method. The method then follows the address on the post it (. is java for: Follow ("Dereference" is the official term) and tells the bear it finds there what its name is.


private static final Bear brenda = new Bear("brenda");

...

Bear bear = new Bear();
bear1.setName("Bruno");
test(bear);
System.out.println(bear1.getName());

public void test(Bear bear) {
  bear = brenda;
}

This prints Bruno! You may have expected Brenda. Remember, = in java is: "Wipe out your postit and copy over the address of this postit".

The main code hands a copy of a postit to the test method. This test method then wipes this postit out, writes the address of another bear on it, and then tosses the note in the trash. The test method does nothing useful here.


ArrayLists are lists of postits. Not lists of bears - that would require an entire zoo, much too unwieldy.

Bear bear = new Bear();
List<Bear> bears = new ArrayList<Bear>();
bears.add(bear);
test(bears);
System.out.println(bears.get(0));

public void test(List<Bear> bears) {
  bears.clear();
  bears.add(brenda);
}

The above code's test method removes the postit with the first bear's address on it from the list, then adds a new postit with brenda's address on it. The main code then gets a copy of the first postit from the list. Which will have the address of brenda. (Why a copy? Everything is a copy, all the time. Java is copying millions of postits. From a CPU perspective it's just copying a single number around).


Bear bear = new Bear("bruno");
bear = new Bear("brenda");

This makes a new bear, writes on your one post-it note its address.

It then makes another bear (we now have 2 bears). It then scratches out the address to bruno and writes the address to brenda on it.

What happens to bruno? Bruno is lost in the woods. There are now zero post-its in the world with Bruno's address on it, so this information (where bruno lives) is lost. Bruno is still around, but we don't know where. The forest is vast, it doesn't matter, we'll never run into him.

Eventually, the garbage collector will get rid of bruno entirely. Poor bruno.