Java jsp会话:ArrayList<;字符串>;反映最新值,但对于字符串,它不反映最新值
我注意到ArrayList反映了最新的值,但对于String,它不反映Java jsp会话:ArrayList<;字符串>;反映最新值,但对于字符串,它不反映最新值,java,jsp,session-state,Java,Jsp,Session State,我注意到ArrayList反映了最新的值,但对于String,它不反映 //Initializing List and String ArrayList<String> list = new ArrayList<String>(); list.add("Item1"); String name = "String1"; //Setting Attribute for both session.setAttribute("mylist", list); session.s
//Initializing List and String
ArrayList<String> list = new ArrayList<String>();
list.add("Item1");
String name = "String1";
//Setting Attribute for both
session.setAttribute("mylist", list);
session.setAttribute("myname", name);
//getting attribute for both
out.println("<br> Printing intial valus <br>");
list = (ArrayList<String>)session.getAttribute("mylist");
for (String s:list){
out.println(s);
}
name = (String) session.getAttribute("myname");
out.println(name);
//updating the values for both
list.add("Item2");
name = "String2";
//Need to add session.setAttribute again for String
//for it to reflect updated value "String 2"
//session.setAttribute("myname", name);
//getting attribute value after the update
list = (ArrayList<String>)session.getAttribute("mylist");
name = (String) session.getAttribute("myname");
//printing the value for both again
out.println("<br><br><br> Prining updated values <br><br>");
for (String s:list){
out.println(s);
}
out.println(name);
在更新值部分,它不应该打印“String2”,但对于ArrayList,它也打印“Item2”。如果我在更新字符串名称值之后手动添加
session.setAttribute(“myname”,name)
,那么它将打印“String2”。但是ArrayList不需要此session.setAttribute,因为当您将setAttribute
设置为会话时,如果该值是字符串,则会话正在内存中保存(复制)字符串值。但是,当值是数组列表时,它会保存(复制)指向该变量的指针(内存位置而不是值)。
这就是为什么当您从会话中获取并更改值时,指向ArrayList
的指针不会更改,只有值会更改。因此会话仍在保存正确的指针。但是,当您更改字符串时,该值是change,并且由于会话正在保存旧值,因此不会自动更改。
我希望您能理解我的解释。我认为,当您将名称添加到会话属性时,名称的值正在被复制。这就是为什么在再次添加之前,您不会看到它更新。然而,list指向一个对象,当您调用add()时,该对象确实会得到更新,因此您可以看到更新,而不做任何进一步的操作
如果您假装自己实现会话属性,则更容易看出这一点。在大多数实现中,属性只是一个HashMap
:
HashMap<String,Object> attributes = new HashMap<>();
您应该看到,name
的值被放入带有以下值的EntrySet
:
new EntrySet( "myname", name );
ctor会做一些类似的事情
class EntrySet {
Object key;
Object value;
EntrySet( Object key, Object value ) {
this.key = key;
this.value = value;
}
}
现在我想更容易看出,如果您在原始程序中更改name
,则value
的值不会更新
name = "String2"; // does nothing about the contents of EntrySet.value
但是,当您对ArrayList
执行相同的操作时,很明显,您有两个对同一对象的引用,因此很明显,单个对象只会更新
ArrayList<String> list = new ArrayList<>();
list.add( "Item1" );
ArrayList<String> value = list; // clearly both list and value point to the same object
value.add( "Item2" ); // the same list just gets updated
ArrayList list=new ArrayList();
列表。添加(“第1项”);
ArrayList值=列表;//显然,列表和值都指向同一个对象
值。添加(“项目2”);//相同的列表刚刚更新
因此,您可以看到列表更新,而无需再次调用setAttribute()
顺便说一句,拥有这样一个“共享”的对象(列表)是一个巨大的多线程漏洞。如果可能,您应该改为在请求
对象上设置属性。否则,您必须锁定会话或提供其他形式的互斥锁,以确保所有内容的安全和同步。ArrayList list=new ArrayList();
ArrayList<String> list = new ArrayList<String>();
list.add("Item1");
String name = "String1";
列表。添加(“第1项”);
String name=“String1”;
上面的几行创建了一个名为list的变量,该变量指向内存中具有列表元素“Item1”的位置(将该位置命名为locatinoLOC123)
您还创建了一个名为name的变量,该变量指向内存中的一个位置(将locatinoLOC456命名),该位置的字符串值为“String1”
将名称和列表变量传递给会话.setAttribute方法时,只传递了列表和名称变量的参考值。
现在会话对象在内存中引用LOC123&LOC456,这允许它检索实际值
当您执行list.add(“Item2”)时命令您向同一内存位置添加了一个以上的元素LOC123。鉴于会话已经指向LOC123,您设法看到了反映的更改值
Java字符串是不可变的,一旦创建它们,就不能更改它们。当您执行name=“String2”您在内存中创建了一个新位置LOC789,其字符串值为“String2”,名称变量现在已更改为指向LOC789
假定会话对象仍然指向LOC456,并且它对LOC789一无所知,则更新的“String2”值未反映在会话中
要解决此问题,您可以使用可编辑的StringBuffer(或StringBuilder)。当您将String2
分配给name
时,您可以这样想
上一个String
对象String1
失去了它的引用,但是会话仍然具有属性myname
的值,它没有返回null
因此,当您编写类似于session.setAttribute(“myname”,name)的代码时代码>名称和会话属性都位于两个不同的内存位置,这就是为什么名称中的更改不会反映在会话中的原因
当您将object作为参数传递给Java的method时,可以在这个链接中检查String
类的特例ArrayList
是可变的,因此:
List<String> list = new ArrayList<String>();
// copy of object reference passed to session
session.setAttribute("list", list);
// adding new value to same object, so all references to it will see the chages
list.add("Something");
我认为现在的情况是,当您将name
添加到会话属性时,它的值会被复制。这就是为什么在再次添加之前,您不会看到它更新。然而,list
指向一个对象,当您调用add()
时,该对象确实会得到更新,因此您可以看到更新,而不做任何进一步的操作。这是不正确的,对String和ArrayList都传递了对方法的引用。主要区别在于list.add(…)更新初始对象的值,而String name=“new”将新对象分配给变量名,而不更新初始对象。
ArrayList<String> list = new ArrayList<String>();
list.add("Item1");
String name = "String1";
List<String> list = new ArrayList<String>();
// copy of object reference passed to session
session.setAttribute("list", list);
// adding new value to same object, so all references to it will see the chages
list.add("Something");
// object "value" created, reference passed to 'name' variable
String name = "value";
// copy of reference to object value passed to session
session.setAttribute("string", name);
// NEW object "otherString" created and its reference assigned to variable 'name'
// session still has it's copy of reference to "value" object
name = "otherString";