我知道this = null
是非法的。
我想知道是否还有其他方法让对象自行清理。
我的愿望是能够做到这样的事情:
A a = new A();
a.doStuffAndDisappear();
if(a == null){
//this is true after my doStuffAndDisappear() method.
}
我怀疑没有办法让这种情况发生,但我认为值得一提。
答案 0 :(得分:16)
不,因为a
是引用(不是此问题标题中的对象),并且没有方法可以修改引用的值,除了定义它的方法(我假设从代码上下文a
是一个局部变量)。
由于Java没有传递引用,因此无法完成您的要求:无法收集地址的引用以管理指向的地址。您可以使用包装器对象,但不确定它是什么意思。
答案 1 :(得分:5)
正如其他人所说,这根本不可能。如果它正在清理您所追求的资源,那么您可以考虑使用以下模式:
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...
}
或者你甚至可以将两者结合起来,无论你喜欢哪种方式。
或者最后你可以像William Morrison所解释的那样(虽然我可能会作弊,只是使用java.util.concurrent.atomic.AtomicReference
而不是自己上课,而且还带来了作为一般化类型的额外好处),根据您的情况,可能真的没必要。毕竟,你可以随时做(尽管看起来有点奇怪):
A a = new A();
a.doStuffAndDisappear();
a = null;
if(a == null){
//...
}
答案 2 :(得分:2)
我可能会遗漏一些东西但是,因为你提到:
我想知道是否有其他方法让对象自行清理 起来。
和
我有一个自包含的小部件,如果有的话可以大大改进 在做了它需要做的事情后,它可以让自己为null。从而 让GC清理它并且不让Widget的用户拥有它 手动将其设置为空。
怎么样,根本不保留对象的引用?
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
将其引用设置为每个父级,只需更改A
以保存父级列表(List<AParent> parents
),并实现跟踪父级的方法:< / p>
void addParent(AParent parent)
{
parents.add(parent);
}
加上void cleanUp()
迭代其父项设置null:
void cleanUp()
{
for (AParent parent : parents)
{
parent.setA(null);
}
parents.clear();
}
注意这个解决方案看起来很像JavaBeans Bound Properties ......这不是巧合;在某种程度上,我们创建了一个简单的事件/侦听器架构,A
可以通知其父母获取对它的引用。
答案 3 :(得分:2)
这个简洁的问题在技术上很有趣。但是,考虑到您的意图:您试图强制所有引用的条件为null
,以便您可以防止无效使用已过期的实例。
将任何含义分配给null
。
相反,修改(或者如果你不能修改门面)你的A
对象,以便有一些其他标志可用。例如public boolean isClosed() ...
答案 4 :(得分:1)
我认为这是不可能的。如果a
是某个对象x
的实例变量,doStuffAndDisappear
可能会以某种方式获得对x
的引用,并调用setter将a
设置为null。最好不要走这条路,因为它完全违反直觉。
最好是在doStuffAndDisappear
中清理(好吧,不能让它消失),并确保没有其他人指的是a
。 GC应该好好休息。
答案 5 :(得分:1)
是的,如果您在应用程序中重新实现GC,则可以。我的答案受到你与Patricia的讨论的启发,你说你希望将对该对象的所有引用设置为null。 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 :(得分:0)
你不能让一个对象设置另一个对象对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;
}
}
这将导致一个值对第二个引用的引用消失,因为第二个引用将第一个引用的引用设置为null。