Как подсчитать количество экземпляров класса
Может ли кто-нибудь сказать мне, как подсчитать количество экземпляров класса?
Вот мой код
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 ответов:
Поскольку переменные
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); } }