Heis的Blog

保持简单,保持愚蠢
随笔 - 29, 文章 - 1, 评论 - 122, 引用 - 0
数据加载中……

大话深入浅出Effective Java核心实战编程思想之——猴王的把戏

        不知道大家还记不记得在《西游记》里的莲花洞夺宝的故事,就是猴王巧夺宝物,收复金银角大王那一章。到底这个故事给了我们什么启示呢?这故事又和Effective Java有什么联系?还是延续上篇文章的风格吧,看代码,读故事。

  1import static org.junit.Assert.*;
  2import org.junit.Test;
  3
  4
  5public class TestClone {
  6    
  7    @Test
  8    public void testClone(){    
  9        // 西天取经的路上,金角大王和银角大王把唐僧抓走了         
 10        猴王 齐天大圣=new 猴王("齐天大圣孙悟空");
 11        //大圣手拿金箍棒,正要收拾金、银角大王。
 12        齐天大圣.取得武器(new 金箍棒());
 13        
 14        /*
 15         * 这时候,金角大王和银角大王听闻大圣来者不善,立马让小妖去请出他们的宝葫芦
 16         * 当然这一切瞒不过神通广大的大圣爷。大圣猴毛一吹,变出一个老道士。
 17         */
        
 18        猴王 空悟孙道士=(猴王)齐天大圣.变出一个化身();
 19        空悟孙道士.改名("空悟孙道士");
 20        
 21        /*
 22         * 老道士忽悠小妖说他的葫芦更厉害,能把天都给收了,智力值只有20的小妖看了羡慕不已,要求交换葫芦。
 23         * 老道士自然很乐意,换了葫芦,直奔妖怪洞穴,收服了金、银角大王。
 24         */

 25        空悟孙道士.取得武器(new 宝葫芦());
 26        
 27        //问题1:道士拿的是什么武器?道士是由大圣克隆而来,拿的却不是金箍棒,而是宝葫芦?
 28        assertFalse(齐天大圣.的武器() instanceof 金箍棒);
 29        assertTrue(空悟孙道士.的武器() instanceof 宝葫芦);
 30        
 31        //问题2:大圣和道士拿同一个武器?
 32        assertSame(空悟孙道士.的武器(),齐天大圣.的武器());
 33        
 34        //问题3:既然武器是一样的,为什么名字又不一样呢?
 35        assertEquals(齐天大圣.名字(),"齐天大圣孙悟空");
 36        assertEquals(空悟孙道士.名字(),"空悟孙道士");
 37        
 38        /*
 39         * 答案:猴王类继承了Object.clone(),其克隆原理是:如果类每个域包含一个原语类型(primitive)的值,
 40         * 或者包含一个指向非可变(final)对象的引用,那么返回的值或对象是一个相同的拷贝;否则,如果是可变类,则会返回相同的引用。
 41         * 因为金箍棒类不是非可变类,而String是,所以你应该明白,为什么大圣爷和他的克隆体有不同的名字,却有相同的武器吧。
 42         * 
 43         * Object.clone()被称为浅拷贝,或浅克隆。相对应的是深克隆(deep clone),他是指类在克隆时也拷贝可变对象。
 44         * 看到这里你应该知道其实这个猴王类实现得不合理,他应该拥有一个深克隆的方法。
 45         */

 46    }

 47
 48    class 猴王 implements Cloneable{
 49        private String name;
 50        private 武器[] weapon=new 武器[1]; 
 51        
 52        public 猴王(String name){
 53            this.name=name;
 54        }

 55            
 56        /**
 57         * 取得一个猴王的浅克隆化身
 58         * @return
 59         */

 60        public Object 变出一个化身(){
 61            Object cloneObj=null;
 62            try{
 63                cloneObj=clone();
 64            }
catch(CloneNotSupportedException ex){
 65                ex.printStackTrace();
 66            }

 67            return cloneObj;
 68        }

 69        
 70        @Override
 71        protected Object clone() throws CloneNotSupportedException{
 72            return super.clone();
 73        }

 74        
 75        public String 名字() {
 76            return name;
 77        }

 78        
 79        public void 改名(String name){
 80            this.name=name;
 81        }

 82
 83        public 武器 的武器() {
 84            return weapon[0];
 85        }

 86
 87        public void 取得武器(武器 weapon) {
 88            this.weapon[0= weapon;
 89        }

 90    }

 91    
 92    class 武器{
 93        public 武器(){
 94            
 95        }

 96    }

 97    
 98    class 金箍棒 extends 武器{
 99        public 金箍棒(){
100        }

101    }

102    
103    class 宝葫芦 extends 武器{
104        public 宝葫芦(){
105        }

106    }

107    
108
109}

110

        看到这里你应该对深克隆和浅克隆有了初步的了解了吧?现在我们再看怎样深克隆一个猴王,哦,不对,应该是真正猴王的七十二变。(为什么我叫他猴王,因为孙悟空有歧义)。
  1import static org.junit.Assert.assertEquals;
  2import static org.junit.Assert.assertFalse;
  3import static org.junit.Assert.assertNotSame;
  4import static org.junit.Assert.assertTrue;
  5
  6import org.junit.Test;
  7
  8
  9public class TestDeepClone {
 10        
 11    @Test
 12    public void testDeepClone(){    
 13        // 西天取经的路上,金角大王和银角大王把唐僧抓走了         
 14        猴王 齐天大圣=new 猴王("齐天大圣孙悟空");
 15        //大圣手拿金箍棒,正要收拾金、银角大王。
 16        齐天大圣.取得武器(new 金箍棒());
 17        
 18        /*
 19         * 这时候,金角大王和银角大王听闻大圣来者不善,立马让小妖去请出他们的宝葫芦
 20         * 当然这一切瞒不过神通广大的大圣爷。大圣猴毛一吹,变出一个老道士。
 21         */
        
 22        猴王 空悟孙道士=(猴王)齐天大圣.变出一个化身();
 23        空悟孙道士.改名("空悟孙道士");
 24        
 25        /*
 26         * 老道士忽悠小妖说他的葫芦更厉害,能把天都给收了,智力值只有20的小妖看了羡慕不已,要求交换葫芦。
 27         * 老道士自然很乐意,换了葫芦,直奔妖怪洞穴,收服了金、银角大王。
 28         */

 29        齐天大圣.取得武器(new 宝葫芦());
 30        
 31        
 32        assertTrue(空悟孙道士.的武器() instanceof 金箍棒);
 33        assertFalse(空悟孙道士.的武器() instanceof 宝葫芦);
 34        assertNotSame(空悟孙道士.的武器(),齐天大圣.的武器());
 35        assertEquals(齐天大圣.名字(),"齐天大圣孙悟空");
 36        assertEquals(空悟孙道士.名字(),"空悟孙道士");
 37    }

 38    
 39    class 猴王 implements Cloneable{
 40        private String name;
 41        private 武器 weapon; 
 42        
 43        public 猴王(String name){
 44            this.name=name;
 45        }

 46            
 47        /**
 48         * 取得一个猴王的浅克隆化身
 49         * @return
 50         */

 51        public Object 变出一个化身(){
 52            Object cloneObj=null;
 53            try{
 54                cloneObj=clone();
 55            }
catch(CloneNotSupportedException ex){
 56                ex.printStackTrace();
 57            }

 58            return cloneObj;
 59        }

 60        
 61        /**
 62         * 取得一个猴王的深克隆化身
 63         * @return
 64         */

 65        public Object 变出一个新化身(){
 66            Object cloneObj=null;
 67            try{
 68                cloneObj=clone();
 69            }
catch(CloneNotSupportedException ex){
 70                ex.printStackTrace();
 71            }

 72            return cloneObj;
 73        }

 74        
 75        @Override
 76        protected Object clone() throws CloneNotSupportedException{
 77            return super.clone();
 78        }

 79        
 80        public String 名字() {
 81            return name;
 82        }

 83        
 84        public void 改名(String name){
 85            this.name=name;
 86        }

 87
 88        public 武器 的武器() {
 89            return weapon;
 90        }

 91
 92        public void 取得武器(武器 weapon) {
 93            this.weapon = weapon;
 94        }

 95    }

 96    
 97    abstract class 武器 implements Cloneable{
 98        public 武器(){
 99            
100        }

101        
102        @Override
103        public Object clone(){
104            Object result=null;
105            try{
106                result= super.clone();
107            }
catch(CloneNotSupportedException ex){
108                ex.printStackTrace();
109            }

110            return result;
111        }

112    }

113    
114    class 金箍棒 extends 武器{
115        public 金箍棒(){
116        }

117        
118        @Override
119        public Object clone(){
120            return super.clone();
121        }

122    }

123    
124    class 宝葫芦 extends 武器{
125        public 宝葫芦(){
126        }

127        
128        @Override
129        public Object clone(){
130            return super.clone();
131        }

132    }

133}

134


程序员的一生其实可短暂了,这电脑一开一关,一天过去了,嚎;电脑一开不关,那就成服务器了,嚎……

posted on 2009-07-04 14:37 Heis 阅读(1717) 评论(4)  编辑  收藏 所属分类: Effective Java

评论

# re: 大话深入浅出Effective Java核心实战编程思想之——猴王的把戏  回复  更多评论   

直奔妖怪洞穴,收服了金、银角大王
2009-07-04 16:44 | 99网上书店

# re: 大话深入浅出Effective Java核心实战编程思想之——猴王的把戏  回复  更多评论   

写的真好。学习了!
2009-07-04 21:02 | 小人物

# re: 大话深入浅出Effective Java核心实战编程思想之——猴王的把戏  回复  更多评论   

不错!
2009-07-05 12:16 | 凡客诚品

# re: 大话深入浅出Effective Java核心实战编程思想之——猴王的把戏  回复  更多评论   

不错
2009-07-05 12:16 | 凡客诚品

只有注册用户登录后才能发表评论。


网站导航: