Memra

Java objects & references (recap)

◈ 5 cards

References vs values, where objects and variables live, null, and aliasing.

Variables hold references, not objects

This is the one mental model the rest of COMP 308 is built on, so re-anchor it before the advanced material.

In Java there are exactly two kinds of value:

  • Primitivesbyte short int long float double boolean char. The variable is the value. Assigning copies the value.
  • Reference types — everything else (objects, arrays, String). The variable holds a reference (a handle) to an object that lives elsewhere. Assigning copies the reference, not the object.

The slogan from Thinking in Java is: "you manipulate objects with references." A reference is like a TV remote — the remote is not the TV, and several remotes can drive one TV.

Stack vs heap

Local variables and method parameters live on the stack (per call, short-lived). Objects created with new live on the heap and are reclaimed by the garbage collector once nothing references them.

int x = 10;                 // primitive: the int 10 sits on the stack
String s = new String("hi");// reference s (stack) -> String object (heap)

Aliasing: two references, one object

Because assignment copies the reference, two variables can point at the same object. Mutating through one is visible through the other:

StringBuilder a = new StringBuilder("cat");
StringBuilder b = a;        // b now refers to the SAME object as a
b.append("s");              // mutate through b
System.out.println(a);      // prints "cats" -- a sees the change

Contrast with primitives, where each variable is independent:

int p = 5;
int q = p;                  // q gets a COPY of the value 5
q = 99;
System.out.println(p);      // prints 5 -- p is unaffected

null and the default

A reference that points at no object holds null. Fields of reference type default to null; calling a method on a null reference throws NullPointerException at runtime.

Pass-by-value (the careful version)

Java is always pass-by-value. For a reference type the reference is passed by value, so the method can mutate the pointed-to object but cannot make the caller's variable point somewhere new:

static void rename(StringBuilder sb) {
    sb.append("!");          // visible to caller (same object)
    sb = new StringBuilder("x"); // reassigns the LOCAL copy only
}

After rename, the caller's builder ends in ! but is not the new "x" object.

Identity vs equality (preview)

a == b for references asks "are these the same object?" (identity). a.equals(b) asks "are these objects logically equal?" (value). For String, always use .equals== can lie. We return to this in the Strings and Collections modules.

refers torefers toastackbstackStringBuilderheap: "cats"Two references, one object.
After StringBuilder b = a; there is still exactly ONE object. b.append("s") mutates that object, so printing a shows "cats".
assignmentwhat gets copiedso afterwardsint q = p;the value 5q = 99 leaves p at 5StringBuilder b = a;the referenceb.append("s") makes a printcatsJava is always pass-by-value; for objects the reference is the value.
The same syntax, two different meanings. A primitive assignment duplicates the value; a reference assignment duplicates only the handle, leaving one shared object.
NORMAL ~/memra/learn/comp-308/objects-and-references utf-8 LF