Можно ли установить Объект как null изнутри самого себя?

Я знаю, что this = null является незаконным.

Мне интересно, есть ли другой способ очистить объект.

Мое желание состоит в том, чтобы сделать что-то вроде этого:

A a = new A();

a.doStuffAndDisappear();

if(a == null){
     //this is true after my doStuffAndDisappear() method.
}

Я подозреваю, что нет способа сделать это, но подумал, что стоит спросить.

Ответ 1

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

Так как Java не имеет pass-by-reference, то, что вы просите, не может быть выполнено: нет способа собирать адреса-ссылок для управления адресами, на которые указывает. Вы можете использовать объект-оболочку, но не знаете, в чем дело.

Ответ 2

Как и все остальные, это просто невозможно. Если вы очистите ресурсы, которые вам нужны, тогда вы можете использовать шаблон, например:

class A {

    private boolean cleanedUp;

    public void cleanUp() {
        // clean up any resources
        cleanedUp = true;
    }

    public boolean isCleanedUp() {
        return cleanedUp;
    }
}

И затем, используя его так:

A a = new A();
a.cleanUp();
if (a.isCleanedUp()) {
    ...
}

Лучшим решением может быть реализация интерфейсов java.io.Closeable или java.lang.AutoCloseable в зависимости от ваших обстоятельств:

class B implements AutoCloseable {

    private boolean closed;

    public boolean isClosed() {
        return closed;
    }

    @Override public void close() throws Exception {
        // clean up any resources
        closed = true;
    }
}

В этом случае вы можете использовать оператор try-with-resources:

try (B b = new B()) {
    // do stuff
} catch (Exception ex) {
    // oh crap...
}

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

Или, наконец, вы могли бы сделать это так, как объяснил Уильям Моррисон (хотя я, вероятно, обманывал бы и использовал бы java.util.concurrent.atomic.AtomicReference вместо того, чтобы создавать свой собственный класс, и он имеет дополнительное преимущество быть генерализованным типом) в зависимости от ваших обстоятельств, действительно может оказаться ненужным. В конце концов, вы всегда можете просто сделать (хотя это может показаться немного странным):

A a = new A();

a.doStuffAndDisappear();
a = null;

if(a == null){
     //...
}

Ответ 3

Мне может быть что-то не хватает, но, поскольку вы упоминаете, что:

Мне интересно, есть ли другой способ очистить объект вверх.

и

У меня есть самостоятельный виджет, который будет значительно улучшен, если он может просто сделать себя нулевым после выполнения того, что ему нужно сделать. таким образом позволяя GC очистить его и не оставлять пользователя Widget чтобы установить его значение null вручную.

Как насчет, не сохраняя ссылки на объект вообще?

new A().doStuffAndDisappear();
// no reference, instance of A is eligible to GC

Обновление

Поскольку это не то, что ищет OP, позвольте мне расширить решение @Perce:

interface AHolder 
{
    void setA(A a);
}

class AParent implements AHolder {

    private A a;

    public AParent() {
        a = new A();
    }

    public void doSomething() {
        a.doStuffAndDisappear(this);
        if(a == null)
        {
            System.out.println("It is true!");
        }
    }

    public void setA(A a) {
        this.a = a;
    }
}

class A 
{
    void doStuffAndDisappear(AHolder parent) {
        parent.setA(null);
    }
}

Теперь вам не нужно знать тип родителя или поле, содержащее A.

Рабочий пример.


Если вы хотите сделать A null ссылкой для каждого родителя, просто измените A на наличие списка родителей (List<AParent> parents) и реализуйте метод отслеживания родителей:

void addParent(AParent parent)
{
    parents.add(parent);       
}

Плюс a void cleanUp(), который перебирает своих родителей, устанавливая значение null:

void cleanUp()
{
    for (AParent parent : parents)
    {
        parent.setA(null);         
    }   
    parents.clear();  
} 

Обратите внимание, как это решение очень похоже на JavaBeans Bound Properties... Это не случайно; мы, в некотором роде, создаем простую архитектуру Event/Listener, чтобы A мог уведомить своих родителей о том, как получить ссылку на нее.

Ответ 4

Это невозможно, я бы подумал. Если a является переменной экземпляра какого-либо объекта x, doStuffAndDisappear каким-то образом может получить ссылку на x и вызвать setter для установки a на null. Лучше не идти по этому маршруту, поскольку он полностью противодействует интуиции.

Лучше всего было бы очистить в doStuffAndDisappear (ну, can not make исчезнет) и убедитесь, что никто другой не ссылается на a. GC должен позаботиться о отдыхе.

Ответ 5

Да, возможно, если вы переопределите GC в своих приложениях. Мой ответ вдохновлен вашим обсуждением с Патрицией, где вы сказали, что хотите, чтобы все ссылки на этот объект равны нулю. Пример GC:

class MyGC {
   byte[100000] myMemory;
   int nextFreeCell;
   myNew (int value) { }
   get (int myCell) { }
}

Таким образом вы можете контролировать, что в вашем классе нет других ссылок. Ваш класс также должен содержать ссылки на вашу память GC. Ваш пример:

int cell = MyGC.new(A.class)

MyGC.get(cell).doSomething();

if (MyGC.get(cell) == null)
   --- true -----

Ответ 6

Этот опрятный вопрос технически интересен. Однако, учитывая ваше намерение: вы пытаетесь заставить условие всех ссылок быть null, чтобы вы могли защищать от недействительного использования экземпляра с истекшим сроком действия.

Плохая практика присваивать любой смысл null.

Вместо этого измените (или фасад, если вы не можете изменить) свой объект A, чтобы был доступен другой флаг. Например public boolean isClosed() ...

Ответ 7

У вас не может быть объекта, который установил бы другую ссылку на объект как null, если бы они оба не знали друг о друге. Делать то, что вы хотите, невозможно без какой-либо работы. Я рекомендую следующий пример.

public class A{
    A other;
    public A(A a){
        this.other = a;
        if(a!=null)
            a.other = this;
    }
    public void doSomethingAndDisappear(){
        a.other = null;
    }
}

Это приведет к тому, что одна ссылка на значение второй ссылки исчезнет, ​​поскольку вторая ссылка устанавливает первую ссылочную ссылку на нуль.