2017-03-05 90 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);