2017-03-05 100 views
1

我想通过在会话中设置它们来将项目列表发送给JSP。我在这里使用Spring控制器。Java会话对象被重新分配

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复制到另一个列表中并使用它?

回答

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的值和在C1 classint b不递增,因为在是在Java primitive type(这恰好是一个值类型)
价值类型的真实世界示例如下:
如果我为您提供了我的标记表的照片副本,并且如果您在其上涂写了原始标记表,则将不会发生任何事情,因为它是我的标记表的副本,类似地当您通过时的变量int a和INT b,这些变量的副本被发送到所述INC函数因而在int a和类C1的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和INT B的原始值递增,这是因为参考该对象被传递
当我们说C1 obj1 = new C1();新的关键词对T使得class C1对象他堆内存和该对象的引用存储在type C1variable obj1obj1是不是它是一个句柄在堆上创建的Object of C1对象,所以当我们在class C2传递obj1inc(C1 obj1)我们通过对象的句柄不对象,该对象是在堆中
所以这不是对象的副本,但原始的对象,因为手柄OBJ1传递(与裁判前面给出真实世界EG)

答到主问题

List<Item> l = new ArrayList<Item>(); 
l.add("item1"); 
l.add("item2"); 
l.add("item3"); 
session.setAttribute("fisrt_item_list", l); 

这里你设置了session object中的ArrayList object,但是对象并不是按字面存储在会话对象中,Arraylist对象的句柄存储在会话对象中,所以当从Arraylist对象中删除一个值时,它是体现在会话对象,因为您的会话对象握住手柄,其仍然指向同一个对象从该值将被删除堆中ArrayList对象

注:一个对象持有引用到另一个对象所谓的对象组合,做检查此链接StackOverflow

+0

谢谢。我现在明白了。你如何建议是解决我的问题的最佳方法。我有一个主要清单,我必须从中制定很多子清单。每个子列表将被存储为一个会话object.Does这意味着,如果我需要5分名单,我需要有5个新的列表对象?目前我是从加入主列表中的项目,以二次列表,并补充说,会话和清除辅助列表中添加更多来自主列表等。 –

+0

你可以做一些类似的,一个函数会创建并返回它可以保存在您的会话对象新名单[StackOverflow的/新](http://stackoverflow.com/questions/715650/how-to-clone-数组列表和-也克隆其通的内容),也可以使用克隆当前ArrayList和这里使用它是另一个链接[StackOverflow上/克隆(http://stackoverflow.com/questions/4592478/clone-arraylist-clone -i-认为此结果一浅拷贝) –

2

Java使用参考分配。在你将一个列表对象分配给会话属性的情况下,会话不会存储该列表对象的副本,而只是存储列表对象的引用。

因此,该列表对象中的任何修改都会反映到会话中。如果您不想更新会话,请从现有列表中创建一个新列表,如下所示:

List list = new ArrayList(l);