Как подсчитать количество экземпляров класса


Может ли кто-нибудь сказать мне, как подсчитать количество экземпляров класса?

Вот мой код

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
Переменная класса должна использоваться для подсчета количества экземпляров созданного класса Bicycle, А класс tester создает несколько экземпляров класса Bicycle и демонстрирует работу класса Bicycle и переменной класса. Я искал по всему интернету и не могу ничего найти, Может кто-нибудь покажет мне, как это сделать, пожалуйста, спасибо заранее:)
8 2

8 ответов:

Поскольку переменные static инициализируются только один раз, и они являются общими для всех экземпляров, вы можете:

class MyClass {

    private static int counter;

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

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

Подробнее о полях static читайте в разделе JLS - 8.3.1.1. статические поля:

Если поле объявлено static, существует ровно одно воплощение поля, независимо от того, сколько экземпляров (возможно, ноль) класса может быть в конечном итоге создано . Поле static, иногда называемое переменной класса, воплощается, когда класс является инициализировано (§12.4).

обратите внимание, что counter неявно устанавливается равным нулю

Кроме того, вы должны переопределить метод finalize для уменьшения счетчика

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;
    }

}

Вы должны иметь в виду, что статические переменные являются областью действия класса (нет ни одной для каждого экземпляра, только одна для каждого класса)

Тогда вы можете продемонстрировать декремент экземпляра с помощью:

...
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

Почему бы не использовать статический счетчик?

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;
    }

........

Pleae попробуйте инструмент 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

Один из основных подходов заключается в объявлении статического числового поля-члена, которое увеличивается при каждом вызове конструктора.

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++;      
    }
    ...
  }

Вам просто нужен статический счетчик в классе.

public class Bicycle {
    private static volatile int instanceCounter;

    public Bicycle() {
        instanceConter++; 
    }

    public static int getNumOfInstances() {
        return instanceCounter;
    }

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

Как упоминалось во многих комментариях finalize() не рекомендуется использовать, поэтому может быть другой подход для подсчета экземпляров велосипедов -

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();
            }
        }
    }
}

В качестве альтернативы можно создать счетчик с блоком инициализатора и статической переменной.

class SomeClass
{
    static int counter;
    {
         counter++;
    }
}

Блоки инициализаторов копируются компилятором в каждый конструктор, поэтому вам придется написать его один раз независимо от того, сколько конструкторов вам потребуется (как указано в приведенной выше ссылке). Блок в {} запускается каждый раз при создании нового объекта класса и увеличивает счетчик переменных на единицу. И, конечно, получить счетчик чем-то вроде:

public int getCounter()
{
    return counter;
}

Или непосредственно

int numOfInstances = SomeClass.counter;
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);
    }

}