【问题标题】:How to clear properly in Java如何在 Java 中正确清除
【发布时间】:2019-07-02 09:57:44
【问题描述】:

当我在另一个对象中进一步引用了对象时,如何在 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 中有多个国家,每个国家又可以有多个城市。现在我的问题是:

据我所知,垃圾收集器不会触及引用的对象,因此我必须确保删除所有引用。所以,如果我是正确的,那么

continent1.countries.clear();

是不够的。在这种情况下,如果我清除对象大陆中的 ArrayList“国家”以及每个对象国家中的所有 ArrayLists“城市”就足够了吗?还是我错过了什么,或者我完全错了?

【问题讨论】:

  • “据我所知,垃圾收集器不会触及引用的对象”到底是什么意思?
  • 首先当你做continent1.countries.clear()时,不能保证垃圾收集器会立即运行。当它运行时,它会自动标记未引用的对象,然后扫描它们。您不必为此担心。
  • 即使 ArrayList 国家/地区中的对象仍然具有对 City 对象的引用,它是否也有效?因为它们仍然可以访问。
  • 可访问的对象不会被垃圾回收。这是相当基本的。
  • 总结一下:只清除“顶部”对象,例如大陆是不够的。所以我必须清除大陆中的数组列表,以及“低级”对象中的所有数组列表,例如国家。正确的?我是否还必须将“最低”对象(在本例中为城市)设置为空?

标签: java arraylist garbage-collection


【解决方案1】:

您对垃圾收集器工作原理的理解存在缺陷。

大多数算法(有许多不同的算法)都是从创建可引用对象的根集开始的。那就是堆栈上、寄存器中的对象等。根集中的每个对象都被标记为活动的,然后递归地跟踪(并标记)对其他对象的引用。这可确保识别所有可引用对象(无论多深)。这被称为精确收集器。

然后收集器能够回收不再需要的对象使用的空间(即未标记为活动的)。具体如何发生取决于对象是在年轻代还是老年代以及正在使用什么算法(CMS、并行、G1 等)。

在您的情况下,您维护对所有对象的单独引用,因此即使不再引用continent1,也不会收集 Country 和 City 对象。如果对 Country 和 City 对象的唯一引用是通过 Continent 对象,则可以在收集continent1 时收集它们。

这里的关键点是,作为开发人员,您无需负责告诉 JVM 和 GC 何时不再需要对象。这一切都是自动发生的。

【讨论】:

    猜你喜欢
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-08
    • 2014-09-08
    • 1970-01-01
    相关资源
    最近更新 更多