There are still 2 objects at the end of go().
What might be confusing is that a Fiji object also has a Fiji member within it.
Line 12 creates a Fiji instance, and f1 points to it. Let's call it Fiji Instance 1.
Line 13 sets the static "base" is set to point to Fiji instance 1 as well.
Line 14 creates a Fiji instance, and f2 points to it. We'll call it Fiji Instance 2.
Line 15 sets f1.f to point to Fiji Instance 2.
Line 16 sets f3 to point to f1.f. thus pointing to Fiji Instance 2.
Line 17 sets f2.f to point to f1, thus pointing to Fiji Instance 1.
Note that as a result of all this, f3 is pointing to Fiji Instance 2, and f3.f is pointing to Fiji Instance 1. In effect, if line 16 was rewritten to say "Fiji f3 = f2" it would do EXACTLY the same as the code as written in your example.
Line 18 throws out the base, f1, and f2 references. However, f3 still exists. It's pointing to Fiji Instance 2. Since Fiji Instance 2's "f" member is pointing to Fiji Instance 1, and f3 is keeping the references live, there are 2 Fiji objects that must remain in existence, and cannot be garbage-collected.
This is one of those things, though, that's visualized more easily with pen and paper... I hope my explanation clarifies somewhat rather than muddying the
water.