我试图通过在会话中设置项目列表来向JSP发送。我在这里使用Spring控制器。
List<Item> l = new ArrayList<Item>();
l.add("item1");
l.add("item2");
l.add("item3");
session.setAttribute("fisrt_item_list", l); // So the fisrt_item_list
会话对象包含所有三个项目。
...
...
// Somewhere down the code, l.remove(2); //removing item3.
return "some_page";
问题:
预期: fisrt_item_list
会话对象应包含3个项目。
实际:会话中只有2项可用,因为删除第三项更新了会话对象。但我从未将更新的l对象添加到会话中。为什么java在返回页面之前重新分配会话对象?那么,我是否需要将l复制到另一个列表并使用它?
答案 0 :(得分:3)
您必须先了解Java中值类型和引用类型之间的区别,请查看以下链接StackOverflow
让我举一个值类型
的简单示例
MAIN.java:
class Main{
public static void main(String [] args){
C1 obj1 = new C1();
obj1.print();
obj1.increment();
obj1.print();
}
}
<强> C1.java:强>
class C1{
int a = 10;
int b = 20;
public C1(){
}
void increment(){
System.out.println("incrementing a and b");
new C2().inc(a,b);
}
void print(){
System.out.println("Value of a "+ a);
System.out.println("Value of b "+ b);
}
}
<强> C2.java 强>
class C2{
void inc(int a, int b){
a++;
b++;
}
}
<强>输出强>
Value of a 10
Value of a 20
incrementing a and b
Value of a 10
Value of a 20
<强>结论强>
int a
中的int b
和C1 class
的值没有增加,因为in是java中的primitive type
(恰好是值类型)
值类型的真实示例可以如下:
如果我给你你的标记表的照片副本,如果你涂鸦,它就不会发生原始标记表,因为它是我的标记表的副本,当你传递变量int a和int b时,这些变量的副本被发送到inc函数因此它不会增加C1类int a
和int b
中的原始值
让我们看一下参考类型的例子
MAIN.java:
class Main{
public static void main(String [] args){
C1 obj1 = new C1();
obj1.print();
C2.inc(obj1);
obj1.print();
}
}
<强> C1.java:强>
class C1{
int a = 10;
int b = 20;
public C1(){
}
void print(){
System.out.println("Value of a "+ a);
System.out.println("Value of b "+ b);
}
}
<强> C2.java 强>
class C2{
public static void inc(C1 obj1){
obj1.a++;
obj1.b++;
}
}
<强>输出强>
Value of a 10
Value of a 20
incrementing a and b
Value of a 11
Value of a 21
<强>结论强>
这里int a和int b的原始值递增,因为对该对象的引用被传递
当我们说C1 obj1 = new C1();
关键字new在堆内存上创建class C1
的对象,并且对该对象的引用存储在variable obj1
type C1
中,{{1} }它不是它在堆中创建的obj1
句柄的对象,所以当我们在Object of C1
中将obj1
传递给inc(C1 obj1)
时,我们传递对象的句柄而不是对象,对象在堆中
所以这不是对象的副本,但是原始对象是因为句柄obj1而传递的(例如前面给出的引用现实世界)
回答主要问题
class C2
这里你在List<Item> l = new ArrayList<Item>();
l.add("item1");
l.add("item2");
l.add("item3");
session.setAttribute("fisrt_item_list", l);
中设置了ArrayList object
,但是对象并没有字面上存储在会话对象中,Arraylist对象的句柄存储在会话对象中,所以当一个值是从Arraylist对象中删除它会反映在会话对象中,因为您的会话对象保存了Arraylist对象的句柄,该对象仍指向从中删除该值的堆上的同一对象
注意:一个对象持有对另一个对象的引用称为对象组合,请检查此链接StackOverflow
答案 1 :(得分:2)
Java使用引用分配。在您为会话属性分配列表对象的情况下,会话不存储该列表对象的副本,而只是存储列表对象的引用。
因此,该列表对象中的任何修改都将反映到会话中。如果您不想更新会话,请从现有列表中创建一个新列表,如下所示:
列表列表=新的ArrayList(l);