 <p>Pointing <code>i</code> to a different object does not mutate the (original) object. This is not special to primitives. Say you have a <code>List&lt;List&lt;Object&gt;&gt;</code> or a <code>List&lt;List&lt;String&gt;&gt;</code>:</p> <pre><code> List&lt;List&lt;String&gt;&gt; wrapper = new ArrayList&lt;List&lt;String&gt;&gt;(); List&lt;String&gt; l1 = new ArrayList&lt;String&gt;(); wrapper.add(l1); l1 = new ArrayList&lt;String&gt;(); l1.add("hello"); for(List&lt;String&gt; list : wrapper) { for(String string : list) { System.out.println(string); } } </code></pre> <p>If you now iterate over <code>wrapper</code> you find it contains 1 empty list. This is equivalent to your first example. Your second example looks like:</p> <pre><code> List&lt;List&lt;String&gt;&gt; wrapper = new ArrayList&lt;List&lt;String&gt;&gt;(); List&lt;String&gt; l1 = new ArrayList&lt;String&gt;(); wrapper.add(l1); l1.add("hello"); for(List&lt;String&gt; list : wrapper) { for(String string : list) { System.out.println(string); } } </code></pre> <p>In this case the <code>wrapper</code> now contains 1 list with one value in it.</p>