1

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?

Donald Duck
  • 8,409
  • 22
  • 75
  • 99
Akash Kaundinya
  • 109
  • 1
  • 6

2 Answers2

3

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

Community
  • 1
  • 1
Pushkarraj Pujari
  • 666
  • 11
  • 25
  • Thanks. I understood it now. How do you suggest is the best way to solve my problem. I have a main list from which I have to make a lot of sub list. Each sub list will be stored as a session object.Does this mean if I need 5 sub list, I need to have 5 new list objects ?Currently I was adding the items from main list to secondary list and adding that to session and clearing the secondary list to add more from the main list and so on. – Akash Kaundinya Mar 05 '17 at 10:00
  • You can do something similar to this, a function will create and return a new list which can be saved in your session object [StackOverflow/new](http://stackoverflow.com/questions/715650/how-to-clone-arraylist-and-also-clone-its-contents) or you can use the clone current arraylist and use it here is another link [StackOverflow/clone](http://stackoverflow.com/questions/4592478/clone-arraylist-clone-i-thought-does-a-shallow-copy) – Pushkarraj Pujari Mar 05 '17 at 10:08
2

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);