本文是小编为大家收集整理的关于Java会话对象被重新分配的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。
问题描述
我正在尝试通过在会话中设置项目列表到JSP.我在这里使用弹簧控制器.
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复制到另一个列表中并使用它?
推荐答案
您必须首先了解值类型和参考类型在Java中,请检查以下链接
c2.java 输出 结论 int a和int b in C1 class的值没有增加,因为在Java中为a primitive type(恰好是值类型) 让我们看到一个参考类型的示例 main.java: c1.java: c2.java 输出 结论 在这里,int a和int b的原始值会增加,因为对该对象的引用是传递的 回答主要问题 在这里,您将ArrayList object设置在session object中,但是对象并未存储在session对象中,arrayList对象的句柄存储在会话对象中,因此,当从arraylist删除一个值时对象它反映在会话对象中,因为您的会话对象将句柄保存到阵列列表对象上,该对象仍指向在堆上删除该值 注意:一个持有对另一个对象的引用的对象称为对象组成,请检查此链接> stackoverflow Java使用参考分配.在您的情况下,当您将列表对象分配给会话属性时,会话不存储该列表对象的副本,而只是存储列表对象的引用. 因此,该列表对象中的任何修改也会反映为会话.如果您不想更新会话,请在现有列表中创建一个新列表,如下所示: list = new arraylist(l); 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时,发送了这些变量的副本因此,对于INC函数,它并不在类C1
class Main{
public static void main(String [] args){
C1 obj1 = new C1();
obj1.print();
C2.inc(obj1);
obj1.print();
}
}
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);
}
}
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
当我们说C1 obj1 = new C1();关键词new是在堆内存上class C1的对象,并且对该对象的引用存储在variable obj1的variable obj1 of obj1中,obj1不是对象,它是对象Object of C1在堆中创建,因此,当我们将obj1传递给inc(C1 obj1) class C2> class C2时,我们将对象的句柄而不是对象传递给对象,则对象在堆中
因此,这不是对象的副本,而是由于句柄OBJ1(参考为前面给出的现实世界)而传递的原始对象
List<Item> l = new ArrayList<Item>();
l.add("item1");
l.add("item2");
l.add("item3");
session.setAttribute("fisrt_item_list", l);
其他推荐答案
问题描述
I am trying to send List of Items to JSP by setting them in a session. I am using Spring controller here.
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
The session object contains all three items.
... ... // Somewhere down the code, l.remove(2); //removing item3. return "some_page";
The Problem:
Expected: fisrt_item_list session object should contain 3 items.
Actual : Only 2 items available in session as the removal of third item updated the session object. But I have never added the updated l object into session. Why does java reassign the session object before returning a page? So, do I need to copy over the l to another list and use that?
推荐答案
You must first understand the difference between Value Type and Reference Type in Java , check the following link StackOverflow
let me give you a simple example of Value Type
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++; } }
Output
Value of a 10 Value of a 20 incrementing a and b Value of a 10 Value of a 20
Conclusion
The value of int a and int b in C1 class was not incremented because in is a primitive type in java(which happens to be a value type)
A real world example to value type can be as follows :
If I give you photo copy of my mark sheet and if you scribble on it nothing will happen to original mark sheet because it is a copy of my mark sheet similarly when you pass the variable int a and int b , copy of those variables is sent to the inc function hence it doesnot increment the original value in int a and int b of class C1
let us see an example for reference type
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++; } }
Output
Value of a 10 Value of a 20 incrementing a and b Value of a 11 Value of a 21
Conclusion
here the original value of int a and int b is incremented , because the reference to that object is passed
When we say C1 obj1 = new C1(); the key word new makes an object of class C1 on the heap memory and the reference to that object is stored in variable obj1 of type C1 , obj1 is not the object it is a handle to the Object of C1 created in heap, so when we pass obj1 to inc(C1 obj1) in class C2 we pass the handle of the object not the object , the object is in the heap
So this is not the copy of the object but the original object is passed because of the handle obj1(with ref to real world eg given earlier)
Answer to the main question
List<Item> l = new ArrayList<Item>(); l.add("item1"); l.add("item2"); l.add("item3"); session.setAttribute("fisrt_item_list", l);
here you set the ArrayList object in the session object ,but object is not literally stored in the session object , the handle to the object of Arraylist is stored in the session object , so when a value is deleted from the Arraylist object it is reflected in the session object because your session object holds the handle to the Arraylist object which is still pointing to the same object on the heap from which the value is deleted
Note : One object holding the reference to another object is Called Object Composition , do check this link StackOverflow
其他推荐答案
Java uses reference assignment. In your case when you assigns a list object to session attribute, session does not store a copy of that list object, instead it just stores the reference of the list object.
So any modification in that list object will reflect to session as well. If you don't want to update session, create a new list out of the existing list like below:
List list=new ArrayList(l);