Можно ли установить Объект как 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;
}
}
Это приведет к тому, что одна ссылка на значение второй ссылки исчезнет, поскольку вторая ссылка устанавливает первую ссылочную ссылку на нуль.