我用以下的例子来展现这样的问题:
我们定义两个类:Drawer和Apple
/** * Object Apple */ public class Apple { private String color; public String getColor() { return color; } public void setColor(String color) { this.color = color; } }
/** * Object Drawer that is used to put apples. * Actually, it is used to put appleBox which is used to put apples. */ public class Drawer { private List<Apple> appleBox; public Drawer() { appleBox=new ArrayList<Apple>(); } public Drawer(List<Apple> appleBox) { this.appleBox = appleBox; } public void putAppleToBox(Apple apple){ this.appleBox.add(apple); } public void setAppleBox(List<Apple> appleBox) { this.appleBox = appleBox; } public List<Apple> getAppleBox(){ return appleBox; } }Our test case is :
public void testDrawer(){ Drawer drawer=new Drawer(); Apple apple=new Apple(); apple.setColor("Red"); drawer.putAppleToBox(apple); System.out.println(drawer.getAppleBox().get(0).getColor()); System.out.println("---------"); Drawer drawer2=new Drawer(); drawer2.setAppleBox(drawer.getAppleBox());//关键所在 Apple apple2=new Apple(); apple2.setColor("Yellow"); drawer2.putAppleToBox(apple2); System.out.println(drawer.getAppleBox().size()); System.out.println(drawer2.getAppleBox().size()); System.out.println("---------"); drawer2.getAppleBox().get(0).setColor("Green"); System.out.println(drawer.getAppleBox().get(0).getColor()); System.out.println(drawer.getAppleBox().get(1).getColor()); System.out.println(drawer2.getAppleBox().get(0).getColor()); System.out.println(drawer2.getAppleBox().get(1).getColor()); }The test result will be:
Red
---------
2
2
---------
Green
Yellow
Green
Yellow
经验丰富的程序员可能一眼就看出来这样一个实质问题:这里的AppleBox的ArrayList实例只有一个。两个抽屉里面的appleBox引用指向的是同一个ArrayList实例。
这里有个误区,就是以为new了两个抽屉的实例就以为万事大吉了。
当使用drawer2.setAppleBox(drawer.getAppleBox());时,只是将drawer2的appleBox引用指向drawer的appleBox指向的实例。
我们再简化上面的程序:
Apple不变,讲抽屉简化只能放一个苹果,去掉AppleBox这个类:
/** * Object Drawer that is used to put one apple. */ public class Drawer { private Apple apple; public Drawer() { } public void putApple(Apple apple){ this.apple=apple; } public Apple getApple(){ return apple; } }Our Test case :
public void testDrawer(){
Drawer drawer=new Drawer(); Apple apple=new Apple(); apple.setColor("Red"); drawer.putApple(apple); System.out.println(drawer.getApple().getColor()); Drawer drawer2=new Drawer(); drawer2.putApple(drawer.getApple()); drawer2.getApple().setColor("Green"); System.out.println(drawer.getApple().getColor()); System.out.println(drawer2.getApple().getColor()); }The test result will be:
Red
Green
Green
其实实质是一样的,这里的Apple实例只有一个,两个抽屉的apple引用指向同一个Apple实例。
总结:
1. Java中的Reference实质就是指针;
2. 使用他,你得特别地注意了。