13

Can anyone tell me how to count the number of instances of a class?

Here's my code

public class Bicycle {

    //instance variables
    public int gear, speed, seatHeight;
    public String color;

    //constructor
    public Bicycle(int gear, int speed, int seatHeight, String color) {
        gear = 0;
        speed = 0;
        seatHeight = 0;
        color ="Unknown";      
    }

    //getters and setters
    public int getGear() {
        return gear;
    }
    public void setGear(int Gear) {
        this.gear = Gear;
    }

    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int Speed){
        this.speed = Speed;
    }

    public int getSeatHeight() {
        return seatHeight;
    }
    public void setSeatHeight(int SeatHeight) {
        this.seatHeight = SeatHeight;
    }

    public String getColor() {
        return color;
    }
    public void setColor(String Color) {
        this.color = Color;
    }

 }//end class



public class Variable extends Bicycle {

    public Variable(int gear, int speed, int seatHeight, String color) {
        super(gear, speed, seatHeight, color);

    }

}//end class


public class Tester {

    public static void main(String args[]){


       Bicycle bicycle1 = new Bicycle(0, 0, 0, null);
       bicycle1.setColor("red");
       System.out.println("Color: "+bicycle1.getColor());
       bicycle1.setSeatHeight(4);
       System.out.println("Seat Height: "+bicycle1.getSeatHeight());
       bicycle1.setSpeed(10);
       System.out.println("Speed: "+bicycle1.getSpeed());
       bicycle1.setGear(6);
       System.out.println("Gear: "+bicycle1.getGear());

       System.out.println("");//space

       Bicycle bicycle2 = new Bicycle(0, 0, 0, null);
       bicycle2.setColor("black");
       System.out.println("Color: "+bicycle2.getColor());
       bicycle2.setSeatHeight(6);
       System.out.println("Seat Height: "+bicycle2.getSeatHeight());
       bicycle2.setSpeed(12);
       System.out.println("Speed: "+bicycle2.getSpeed());
       bicycle2.setGear(6);
       System.out.println("Gear: "+bicycle2.getGear());

       System.out.println("");//space

    }//end method
 }//end class

The class variable is to be used to keep count of the number of instances of the Bicycle class created and the tester class creates a number of instances of the Bicycle class and demonstrates the workings of the Bicycle class and the class variable. I've looked all over the internet and I can't seem to find anything, could someone show me how to do it please, thanks in advance :)

RifferRaffers
  • 213
  • 2
  • 5
  • 11
  • 4
    Look into `static` (i.e. class-scoped) fields. – Mena Mar 09 '15 at 16:55
  • 1
    That subclass Variable doesn't actually do anything. It sounds like you are looking for a data structure to track the instances of your class. This would be something that would be outside of your class such as java's [collection objects](http://www.tutorialspoint.com/java/java_collections.htm). Static class variables can also be used for this purpose. – JNYRanger Mar 09 '15 at 16:57

9 Answers9

30

Since static variables are initialized only once, and they're shared between all instances, you can:

class MyClass {

    private static int counter;

    public MyClass() {
        //...
        counter++;
    }

    public static int getNumOfInstances() {
        return counter;
    }
}

and to access the static field counter you can use MyClass.getNumOfInstances()

Read more about static fields in the JLS - 8.3.1.1. static Fields:

If a field is declared static, there exists exactly one incarnation of the field, no matter how many instances (possibly zero) of the class may eventually be created. A static field, sometimes called a class variable, is incarnated when the class is initialized (§12.4).

Note that counter is implicitly set to zero

Dhia Djobbi
  • 1,176
  • 2
  • 15
  • 35
Maroun
  • 94,125
  • 30
  • 188
  • 241
13

Pleae try the tool of java

jmap -histo <PDID>

Out put

     num     #instances         #bytes  class name
----------------------------------------------
   1:       1105141       97252408  java.lang.reflect.Method
   2:       3603562       86485488  java.lang.Double
   3:       1191098       28586352  java.lang.String
   4:        191694       27035744  [C
Lee Tuấn
  • 321
  • 3
  • 4
3

In addition, you should override finalize method to decrement the counter

public class Bicycle {
...
    public static int instances = 0;

    {
        ++instances; //separate counting from constructor
    }
...
    public Bicycle(int gear, int speed, int seatHeight, String color) {
        gear = 0;
        speed = 0;
        seatHeight = 0;
        color ="Unknown";
    }

    @Override
    protected void finalize() {
        super.finalize();
        --instances;
    }

}

You should have in mind that static variables are CLASS scoped (there is no one for each instance, only one per class)

Then, you could demonstrate instance decrement with:

...
System.out.println("Count:" + Bicycle.getNumOfInstances()); // 2
bicycle1 = null;
bicycle2 = null;
System.gc(); // not guaranteed to collect but it will in this case
Thread.sleep(2000); // you expect to check again after some time
System.out.println("Count again:" + Bicycle.getNumOfInstances()); // 0
djangofan
  • 28,471
  • 61
  • 196
  • 289
Danilo Gomes
  • 571
  • 6
  • 13
  • 1
    Yuck. NEVER override `finalize()` if you can possibly avoid it. It probably isn't too harmful in this simple context, but you really should not develop the habit. Note further that in this case there is an alternative involving phantom references (which is rather a lot more sophisticated than I would guess is expected). Note, too, that it is possible for an object to live past invocation of its `finalize()` method, so using `finalize()` this way isn't even, in general, guaranteed to work. – John Bollinger Mar 09 '15 at 17:13
2

why not using a static counter?

public class Bicycle {

    private static int instanceCounter = 0;

    //instance variables
    public int gear, speed, seatHeight;
    public String color;

    //constructor
    public Bicycle(int gear, int speed, int seatHeight, String color) {
        gear = 0;
        speed = 0;
        seatHeight = 0;
        color ="Unknown";      
instanceCounter++;
    }

    public int countInstances(){
        return instanceCounter;
    }

........
Matteo Rubini
  • 831
  • 5
  • 9
  • 2
    The `countInstances()` method would more appropriately be `static`. – John Bollinger Mar 09 '15 at 17:00
  • depending on philosophy of your application – Matteo Rubini Mar 09 '15 at 17:04
  • 2
    The number of instances is a property of the class, not of any specific instance, regardless of how you spell the name of the accessor method. That accessor should therefore be a class method. That's a matter of consistency of design. As a practical matter, it allows you to determine how many instances were created without having one in hand. With it as an instance method, I may be forced to do this: `int numInstances = new Bicycle().countInstances() - 1;`. That ugliness arises from a flawed design. – John Bollinger Mar 09 '15 at 17:31
  • 1
    It should be defined as static that countInstances() method. @JohnBollinger is just right. – ardarda Jan 28 '20 at 11:29
1

You just need static counter in class.

public class Bicycle {
    private static volatile int instanceCounter;

    public Bicycle() {
        instanceConter++; 
    }

    public static int getNumOfInstances() {
        return instanceCounter;
    }

    protected void finalize() {
        instanceCounter--;
    }
}

As mentioned in many comments finalize() is not recommended to use so there could be another approach to count the Bicycle instances -

public class Bicycle {

    private static final List<PhantomReference<Bicycle>> phantomReferences = new LinkedList<PhantomReference<Bicycle>>();
    private static final ReferenceQueue<Bicycle> referenceQueue = new ReferenceQueue<Bicycle>();
    private static final Object lock = new Object();
    private static volatile int counter;
    private static final Runnable referenceCleaner = new Runnable() {
        public void run() {
            while (true) {
                try {
                    cleanReferences();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    };

    static {
        Thread t = new Thread(referenceCleaner);
        t.setDaemon(true);
        t.start();
    }

    private Bicycle() {
    }

    public static Bicycle getNewBicycle() {
        Bicycle bicycle = new Bicycle();
        counter++;
        synchronized (lock) {
            phantomReferences.add(new PhantomReference<Bicycle>(new Bicycle(), referenceQueue));
        }
        System.out.println("Bicycle added to heap, count: " + counter);
        return bicycle;
    }

    private static void cleanReferences() {
        try {
            PhantomReference reference = (PhantomReference) referenceQueue.remove();
            counter--;
            synchronized (lock) {
                phantomReferences.remove(reference);
            }
            System.out.println("Bicycle removed from heap, count: " + counter);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static int getNumOfBicycles() {
        return counter;
    }
}

public class BicycleTest {

    public static void main(String[] args) {
        int i = 0;
        while (i++ < 1000) {
            Bicycle.getNewBicycle();
        }
        while (Bicycle.getNumOfBicycles() > 0) {
            try {
                Thread.sleep(1000);
                System.gc(); // just a request
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
hemant1900
  • 1,226
  • 8
  • 9
  • 1
    No, no, NO! Do not override `finalize()`. Don't. Don't develop the habit, don't recommend it to others, don't give it a pass in code reviews. It can have harmful effects (e.g. objects living longer than they otherwise would), and it is not, in general, guaranteed to lead to the behavior you probably expect. – John Bollinger Mar 09 '15 at 17:22
  • 2
    Agree!. Although I think is it was not that harmful to use finalize() in this particular case but yes you are right it is not a recommended solution. So i have modified my answer with another approach to count the instances. – hemant1900 Mar 11 '15 at 12:10
1

Alternatively, you can create a counter with an initializer block and a static variable.

class SomeClass
{
    private static int instanceCounter;
    {
         instanceCounter++;
    }
}

Initializer blocks get copied by the compiler into every constructor, so, you will have to write it once no matter how many constructors you will need (As referred into the above link). The block in {} runs every time you create a new object of the class and increases the variable counter by one. And of course get the counter by something like:

public static int getInstanceCounter()
{
    return instanceCounter;
}

or directly

int numOfInstances = SomeClass.instanceCounter;

If you do not make numOfInstances private

Alexandros
  • 11
  • 3
0

One basic approach is to declare a static numeric member field thats incremented each time the constructor is invoked.

public class Bicycle {

    //instance variables
    public int gear, speed, seatHeight;
    public String color;
    public static int bicycleCount = 0;

    //constructor
    public Bicycle(int gear, int speed, int seatHeight, String color) {
        gear = 0;
        speed = 0;
        seatHeight = 0;
        color ="Unknown";
        bicycleCount++;      
    }
    ...
  }
Amir Afghani
  • 37,814
  • 16
  • 84
  • 124
0

If you want to count and test instances based on the number of objects created, you can use a loop to see what really is happening. Create a constructor and use a static counter

public class CountInstances {
public static int count;
public CountInstances() {
    count++;
}
public int getInstaces() {
    return count;
}
public static void main(String []args) {
    for(int i= 0; i<10; i++) {  
        new CountInstances();
    }       
    System.out.println(CountInstances.count);
  } 
}
karto
  • 3,538
  • 8
  • 43
  • 68
-1
public class Number_Objects {

    static int count=0;
    Number_Objects(){
        count++;
    }

    public static void main(String[] args) {

        Number_Objects ob1=new Number_Objects();
        Number_Objects ob2=new Number_Objects();
        Number_Objects obj3=new Number_Objects();
        System.out.print("Number of objects created :"+count);
    }

}
hellow
  • 12,430
  • 7
  • 56
  • 79
  • While this might answer the authors question, it lacks some explaining words and links to documentation. Raw code snippets are not very helpful without some phrases around it. You may also find [how to write a good answer](https://stackoverflow.com/help/how-to-answer) very helpful. Please edit your answer. – hellow Sep 27 '18 at 13:48