当我在另一个对象中进一步引用了对象时,如何在Java中正确清除。假设我有以下示例:
大陆 | ________国家 | ______城市
因此,一个大洲可以有多个国家,而这些国家又可以有多个城市。
public class City {
public String name;
public City(String name) {
this.name = name;
}
}
public class Country {
public String name;
public ArrayList<City> cities = new ArrayList<City>();
public Country(String name) {
this.name = name;
}
}
public class Continent {
public String name;
public ArrayList<Country> countries = new ArrayList<Country>();
public Country(String name) {
this.name = name;
}
}
public static void main(String[] args) {
City city1 = new City("Berlin");
City city2 = new City("Paris");
City city3 = new City("Munich");
Country country1 = new Country("Germany");
Country country2 = new Country("France");
country1.cities.add(city1);
country1.cities.add(city3);
country2.cities.add(city2);
Continent continent1 = new Continent("Europe");
continent1.countries.add(country1);
continent1.countries.add(country2);
}
如您所见,我有一个Continent对象,该对象在ArrayList中具有多个国家,每个国家又可以具有多个Cities。现在我的问题是:
据我所知,垃圾收集器不会碰到引用的对象,因此我必须确保删除所有引用。所以,当我没错的时候,
continent1.countries.clear();
是不够的。在这种情况下,如果我清除对象大陆中的ArrayList“ countries”和每个对象Country中的所有ArrayLists“ cities”,就足够了吗?还是我错过了什么,或者我完全错了?
答案 0 :(得分:0)
您对垃圾收集器工作方式的理解存在缺陷。
大多数算法(有很多不同的算法)都始于创建一组可引用对象的根。那就是堆栈,寄存器等中的那些对象。根集中的每个对象都标记为活动对象,然后递归地跟踪(并标记)对其他对象的引用。这样可以确保识别所有可引用对象(无论深度如何)。这称为精确收集器。
然后,收集器可以回收不再需要的对象(即未标记为活动的)使用的空间。这种情况如何发生取决于对象是年轻一代还是老一代,以及所使用的算法(CMS,并行,G1等)。
在您的情况下,您将维护对所有对象的单独引用,因此即使不再引用continent1,也不会收集“国家和城市”对象。如果对Country和City对象的唯一引用是通过Continent对象,则可以在收集continent1时收集它们。
这里的关键点是,开发人员不需要在不再需要对象时告诉JVM和GC的任何责任。这一切都是自动发生的。