Уничтожение объектов в Java - PullRequest
2 голосов
/ 04 августа 2011

У меня есть общее представление о том, как работает сборщик мусора в Java, но мои соображения по поводу уничтожения объекта не в том, что я забочусь об освобождении памяти, а из-за функциональности.Я могу объяснить лучше на примере:

Скажем, я делаю игру, в которой участвуют деньги.Когда человек поднимает объект Money с земли, я хочу вызвать метод addTo этого объекта, который включает добавление значения в кошелек этого человека.

public class Money {

  /** The value of this object. */
  private final int value;

  // constructor
  public Money(double x) {
    this.value = x;
  }

  // Should be called when a Person picks up this object.
  public void addTo(Person bob) {
    bob.addToWallet(this.value);
  }

  // MAIN METHOD
  public static void main(String[] args) {
    Person bob = new Person();
    Money dollar = new Money(1.00);
    dollar.addTo(bob);    // bob finds $1.00
  }
}

После того, как dollar найденЯ не хочу, чтобы кто-то еще мог это поднять.Другими словами, я не хочу, чтобы я или любая другая программа могли случайно вызвать линию:

dollar.addTo(alice);

Так что после того, как Боб забирает деньги, их ценность добавляется в его кошелек, и нетнеобходимость в объектном представлении этого значения больше.Не то, чтобы я заботился о памяти, которую использует объект, но я не хочу, чтобы этот объект случайно использовался где-то еще в программе.Как мне уничтожить dollar помимо настройки dollar = null;?

Ответы [ 8 ]

3 голосов
/ 04 августа 2011

Если вы действительно пытаетесь смоделировать реальный мир как можно ближе, вы можете добавить атрибут доллара к доллару, чтобы при вызове dollar.addTo () вам приходилось менять владельца, только долларпринадлежит одному человеку в любой момент времени.

3 голосов
/ 04 августа 2011

Вы не должны думать о сборке мусора вообще.Решение о том, когда можно собирать мусор, зависит от JVM, и в 99% случаев вам не нужно вообще об этом думать, если вы программируете ответственно.

Ответьте мне на это .. как бы?объект был случайно использован где-то еще в программе "?

Ответ - невозможно.Локальная ссылка существует до конца вашего основного метода и больше не существует.Если вы не сохраните ссылку на нее, на нее нельзя будет ссылаться.

По мере роста вашей программы, возможно, будет хорошей идеей временно сохранить ссылку на нее.Вам необходимо представить свое понятие «земля» с помощью объекта.Поскольку описываемая вами функциональность является базовой, вы можете просто использовать любую из встроенных реализаций Collection, например List.

List<Money> floorMoney = new LinkedList<Money>();
floorMoney.add(new Money(1.00));

, и когда вы связываете деньги из зала с PersonВы бы удалили его с пола.

Money dollar = floorMoney.get(0); // how you access elements may vary
floorMoney.remove(dollar);
dollar.addTo(bob);

Теперь, если вы не сохраните ссылку на dollar где-то в вашей реализации addTo, объект Money будет заброшен, а затем GC'd.

1 голос
/ 04 августа 2011

В качестве дополнения к тому, что сказал @pstanton, сохраняйте коллекции принадлежащих объектов.Вот сложный способ, который полезен для предотвращения повреждения вашего состояния ошибочным кодом.

public abstract class Possession {
  private Object _key = null;

  public synchronized Object acquire() {
    if (_key != null) { throw new IllegalStateException(); }
    _key = new Object();
  }

  public synchronized void release(Object key) {
    if (_key != key) { throw new IllegalStateException(); }
    _key = null;
  }
}

public class Possessions implements Iterable<Possession> {
  private final Map<Possession, Object> _possessions = new IdentityHashMap<...>();

  public synchronized void add(Possession p) {
    if (!_possessions.containsKey(p)) {
      _possessions.put(p, p.acquire());
    }
  }

  public synchronized void remove(Possession p) {
    Object key = _possessions.remove(p);
    if (key != null) {
      p.release(key);
    }
  }

  public Iterator<Possession> iterator() {
    return Collections.unmodifiableSet(_possessions.keySet()).iterator();
  }
}

public class Money extends Possession { ... }

public class Person {
  private final Possessions _possessions = new Possessions();

  public void add(Money money) {
    _possessions.add(money);
  }
}
1 голос
/ 04 августа 2011

У вас есть НЕТ УПРАВЛЕНИЯ через сборщик мусора Java -GC-, и теперь есть способ заставить виртуальную машину Java уничтожить объект для вас.

Вы можете вызвать System.gc() [или Runtime.getRuntime().gc()], но это только предполагает, что JVM запустит сборку мусора.Дело в том, что JVM не должна прислушиваться к вам, и выполнение GC не гарантируется .Не надейтесь на это.

Относительно вашей потребности в дизайне, положите свои деньги в банк (или на улицу, если вы хотите, чтобы люди их нашли) и попросите банк дать вам один.Если предположить, что в банке только 1, то последующие вызовы вернутся на нуль.

РЕДАКТИРОВАТЬ ПОСЛЕ ЗАГРУЗКИ

Я решил удалить пыль с моих книг и привести несколькостроки из раздела Принудительная сборка мусора 3-ей главы учебного пособия SCJP .Книга, которую я изучал на предмет чистого мазохизма.

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

.. эторекомендуется, чтобы вы никогда не вызывали System.gc () в своем коде - оставьте это JVM.

.. можно только предложить JVM, что он выполняет сборку мусора.Однако нет никаких гарантий, что JVM действительно удалит все неиспользуемые объекты из памяти (даже если запущена сборка мусора).

Сборка мусора сложнее, чем кажется ...

1 голос
/ 04 августа 2011

dollar=null сделает свое дело. Удаляя ссылку на этот объект, на объект нельзя ссылаться. Сборщик мусора здесь не актуален.

Думайте об этом так: если вы не хотите, чтобы кто-то приходил к вам домой, вам не нужно взрывать свой дом. Только не дай им адрес. К счастью, Объекты не могут преследовать других Объектов, как сумасшедшая бывшая девушка может преследовать парня, который бросил ее ... парковаться возле своей работы, отправлять текстовые сообщения в любое время, звонить своим родителям ...

Ой, простите, вернемся к вашему вопросу.

Если земля имеет вид Collection (например, List), то удаление этих денег из вашей коллекции земли также будет держать их вне досягаемости других игроков или мошеннических чувствующих Объектов.

И если ваши деньги также равны Object со значением, после того, как первый игрок их заберет, вы можете установить его значение на -1000, наказывая тем самым игроков, которые возьмут то, что явно не принадлежит им.

0 голосов
/ 08 августа 2011

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

Например, совершенно неважно, когда человек взял свои деньги.И как только деньги будут взяты, игре все равно, кому принадлежит этот экземпляр Money

. Я предлагаю просто добавить атрибут isPicked:

public class Money {

  private final int value;
  private boolean _isPicked = false;

  public Money(double x) {
    this.value = x;
  }

  public boolean isPicked(){
    return _isPicked;
  }

  public void addTo(Person bob) {
    if( this.isPicked )
        throw new Exception("some message for developers");

    bob.addToWallet(this.value);
    _isPicked = true;
  }

  public static void main(String[] args) {
    Person bob = new Person();
    Money dollar = new Money(1.00);
    dollar.addTo(bob);    // bob finds $1.00
    // dollar = null;     // don't need this anymore

    Person alice = new Person();
    dollar.addTo( alice ); // <------   RUNTIME EXCEPTION
  }
}

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

0 голосов
/ 04 августа 2011

почему вы не можете добавить логическое «выбранное» default = false?или создать список и удалить из него?

0 голосов
/ 04 августа 2011

Вы просто должны избегать предоставления «доллара» в тех местах, где вы не хотите, чтобы он шел.Обратите внимание, что это не проблема GC.В среде без GC (например, C ++) тот, кто каким-то образом видит указатель на удаленный объект, аварийно завершит работу, если попытается получить к нему доступ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...