I'm having some trouble understanding the third loop in my code below. After the second loop the list didn't change so I assumed that d was a copy of the element in the list. After the third output the element has its name changed so it's not a copy.
public class Test {
    public static void main(String[] args) {
        List<Dog> list = new ArrayList<>();
        list.add(new Dog("a"));
        list.add(new Dog("b"));
        list.add(new Dog("c"));
        list.forEach(d -> System.out.println("dog name: " + d.getName())); // a,b,c
        for (int i = 0; i < list.size(); i++) {
            list.set(i, new Dog("z"));
        }
        list.forEach(d -> System.out.println("dog name: " + d.getName())); // z,z,z
        for (Dog d : list) {
            d = new Dog("y");
        }
        list.forEach(d -> System.out.println("dog name: " + d.getName())); // z,z,z
        for (Dog d : list) {
            d.setName("w");
        }
        list.forEach(d -> System.out.println("dog name: " + d.getName())); // w,w,w
    }
    public static class Dog {
        private String name;
        public Dog(String n) {
            name = n;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
}
 
     
    