2

I am going through the book "Thinking in Java" by Bruce Eckel, and I've come across a code snippet that I, more or less, understand, but want to modify. In effect, the purpose of the code is to show that class static variables are instantiated only once and before said class's constructor method is called.

Here is link to the book's code on repl.it (I added the comments): https://repl.it/Bhct/6, and I'll post it and its result below:

class Main {
    public static void main(String[] args) {
        System.out.println("Inside main()");
        Cups.c1.f(99);
    }

    // Want to initialize a counter int here
    // static int counter = 1;

    // Want to pass counter to Cups constructor here:
    // static Cups x = new Cups(counter);
    static Cups x = new Cups();
    // counter++;
    // static Cups x = new Cups(counter);
    static Cups y = new Cups();
    // counter++;
    // static Cups x = new Cups(counter);
    static Cups z = new Cups();
}

class Cup {
    Cup(int marker) {
        System.out.println("Cup("+ marker +")");
    }
    void f(int marker) {
        System.out.println("f(" + marker + ")");
    }
}

class Cups {
    int counter = 1;
    static Cup c1;
    static Cup c2;
    static {
        c1 = new Cup(1);
        c2 = new Cup(2);
    }
    // Want to pass an arg to Cups() like this: 
    // Cups(int counter) {
    //     System.out.println("Cups() constructor #" + counter);
    // }
    Cups() {
        System.out.println("Cups()");
    }
}

Result

Cup(1)
Cup(2)
Cups()
Cups()
Cups()
Inside main()
f(99)

What I want to do is to edit the Cups() constructor function's log to include a counter that represents the order in which they are called, i.e.:

Cup(1)
Cup(2)
Cups() 1
Cups() 2
Cups() 3
Inside main()
f(99)

Please see my comments for how I assumed this could be done. Defining a static variable in main and incrementing it via calling counter++ doesn't work because an "" is expected. However, I thought I declared counter as an int earlier?

I've tried a few variations of this, like making the incrementation a method inside and outside main, but I haven't had luck.

What major Java concept am I missing here?

I apologize in advance for the wording of this question. Not entirely sure how to ask this question.

pward
  • 1,049
  • 1
  • 8
  • 17
  • You can make an static class counter, or an static int (to print it, just cast it with String.valueOf(int value). – kunpapa Jan 28 '16 at 17:40

1 Answers1

1

Your approach was right, but you have to make your counter static inside Cups:

class Cups {
    static int counter = 1;
    static Cup c1;
    static Cup c2;
    static {
      c1 = new Cup(1);
      c2 = new Cup(2);
    }

    Cups() {
        System.out.println("Cups() constructor #" + counter);
        counter++;
    }
}

The reason is that all Cups instances share the same counter. If they had each one separate counter, it would be 1 for each instance of Cups. By making the counter static, all instances increment the same variable.


This was the faster solution. The is another way, which needs more changes in your code, but is actually more similar to your approach (as you intended):

class Main {
    public static void main(String[] args) {
        System.out.println("Inside main()");
        Cups.c1.f(99);
    }

    static int counter = 1;

    // Want to pass counter to Cups constructor here:
    static Cups x = new Cups(counter);

    // Want to increment that counter here
    static Cups y = new Cups(counter);

    // Want to increment that counter here
    static Cups z = new Cups(counter);

}

Cups(int counter) {
    System.out.println("Cups() constructor #" + counter);
    Main.counter++;
 }

You need to reference the counter by Main.counter.

exception1
  • 1,239
  • 8
  • 17
  • Gotcha. Thanks! Correct me if I'm wrong, but, in JavaScript, I would have defined counter outside the scope of the Cups constructor function (in lieu of a class), but here I don't have to worry about scope, per se, because static variables are instantiated only once. – pward Jan 28 '16 at 17:52
  • @Bathsheba This is right if one uses `Thread`s. However, this class doesn't, so there is only the main thread. Or is class loading multithreaded in Java? – exception1 Jan 28 '16 at 17:56
  • it appears static initialization occurs once per class loader http://stackoverflow.com/questions/878577/are-java-static-initializers-thread-safe/#answer-878624 . I'm not familiar with class loading, but here are some links I'll have to dig into later: https://dzone.com/articles/java-classloader-handling, http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html – pward Jan 28 '16 at 18:05