Is final variable changing its value throughout time?

I’m currently teaching myself Java from a textbook, and found a piece of code that I don’t understand – why does the final variable id change it’s value?

import static net.mindview.util.Print.*;
class Shared {
    private int refcount = 0;
    private static int counter = 0;
    private final int id = counter++;
    public Shared() {
        print("Creating " + this);
    }
    public void addRef() { refcount++; }
    protected void dispose() {
        if(--refcount == 0)
            print("Disposing " + this);
    }
    protected void finalize() {
        if(refcount != 0)
            print("Error: object is not properly cleaned-up!");
    }
    public String toString() { return "Shared " + id; }
}
class Composing {
    private Shared shared;
    private static int counter = 0;
    private final int id = counter++;
    public Composing(Shared shared) {
        print("Creating " + this);
        this.shared = shared;
        this.shared.addRef();
    }
    protected void dispose() {
        print("disposing " + this);
        shared.dispose();
    }
    public String toString() { return "Composing " + id; }
}
public class E13_VerifiedRefCounting {
    public static void main(String[] args) {
        Shared shared = new Shared();
        Composing[] composing = { new Composing(shared),
                new Composing(shared), new Composing(shared),
                new Composing(shared), new Composing(shared) };
        for(Composing c : composing)
            c.dispose();

Answer

This:

    private static int counter = 0;
    private final int id = counter++;
    public Shared() {
        print("Creating " + this);
    }

is the same as this:

    private static int counter = 0;
    private final int id;
    public Shared() {
        id = counter++;
        print("Creating " + this);
    }

That is, the id is assigned every time the constructor executes, with the side effect that counter is incremented.

id is an instance variable, so each instance of shared gets its own id value.