重新分配Java会话对象

时间:2017-03-05 08:22:29

标签: java spring session arraylist

我试图通过在会话中设置项目列表来向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复制到另一个列表并使用它?

2 个答案:

答案 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 bC1 class的值没有增加,因为in是java中的primitive type(恰好是值类型)
值类型的真实示例可以如下:
如果我给你你的标记表的照片副本,如果你涂鸦,它就不会发生原始标记表,因为它是我的标记表的副本,当你传递变量int a和int b时,这些变量的副本被发送到inc函数因此它不会增加C1类int aint 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);