1

我有一个对象存储在会话中。在我的控制器中,当用户发送请求时,它同时执行以下代码:

MyObject obj = (MyObject) req.getSession().getAttribute("myObject");
while(!obj.isNewResultAvailable()){
    //will loop until new result is available.
}

正如我所指出的,它是并发执行的,因此当控件仍在循环中时,用户可以做一些其他事情,例如,当用户按下另一个按钮时,将向执行以下操作的控制器发送请求:

MyObject obj = (MyObject) req.getSession().getAttribute("myObject");
obj = null;

我的期望是,循环直到有新结果可用的代码将抛出一个NullPointerException. 才发现我们不是。

那么,为什么从另一个控制器中的会话中提取的对象不是null尽管将该对象设置为另一个控制器null

编辑 :

在我当前的代码中,我实际上尝试过

req.getSession().setAttribute("myObject", null);

req.getSession().removeAttribute("myObject");

仍然,这并没有解决我的问题,while 循环中的对象仍然没有为空。

实现

对于那些会遇到这种困惑的人来说,我的问题的根源是我对 Java 中对象的传递方式感到困惑。我的问题很简单,obj = null只是将引用设置为objnull 而不是对象本身。

正如 morgano 所指出的,会话中的对象已被执行 while 循环的线程在本地引用,因此req.getSession().setAttribute("myObject", null);不会req.getSession().removeAttribute("myObject");导致对象为空。这些只是基本上从会话中删除对对象的引用(因此理想情况下使其成为 gc 的候选者,这在我的情况下不会发生,因为该对象是由长时间运行的 http 请求本地引用的 [the while loop thing]) .

4

3 回答 3

3

不要那样做,这样做:

req.getSession().setAttribute("myObject", null);

或者更好:

req.getSession().removeAttribute("myObject");

您正在做的是将对象的引用设置为空,您根本没有修改会话属性。

问题版后更新:

一旦“迭代”线程引用了您的对象,“删除”线程将其从会话中删除是徒劳的,您的对象已被第一个线程中的局部变量引用。

于 2013-07-23T03:14:39.093 回答
1

考虑这个例子:

MyObject a = new MyObject();
MyObject b = a;
b = null;

你似乎期待的是:

MyObject a = new MyObject(); // a is the new object
MyObject b = a; // b is the same object
b = null; // set the object referenced by both a and b to null

真正发生的事情:

MyObject a = new MyObject(); // a is the new object
MyObject b = a; // b points to the same object as a
b = null; // b doesn't point to anything

简而言之:您实际上将引用本身设置为null(即在您的示例中),而不是将引用的值设置为null(即您的示例中的会话)。obj

于 2013-07-23T03:17:51.360 回答
0

做这样的事情。会话是一个键值映射。您必须针对特定的键值显式设置 null。

req.getSession().setAttribute("myObject", null);

或完全删除密钥。

req.getSession().removeAttribute("myObject");
于 2013-07-23T03:15:26.353 回答