代码之家  ›  专栏  ›  技术社区  ›  Gee

如何确定何时可以重用对象?

  •  0
  • Gee  · 技术社区  · 7 年前

    假设我有以下代码片段为一个小的随机游戏创建彩色蔬菜,我正在练习将对象属性从对象类中分离出来:

        List<Vegetable> vegList = new ArrayList<Vegetable>();
    
        Map<MyProperty, Object> propertyList = new HashMap<MyProperty, Object>();
    
        propertyList.put(MyProperty.COLOR, "#0000BB");
        propertyList.put(MyProperty.TYPE, MyType.VEGETABLE);
        propertyList.put(MyProperty.COMMONNAME, "Potato");
    
        vegList.add(new Vegetable("Maisie", propertyList));
    
        propertyList.put(MyProperty.COLOR, "#00FF00");
        propertyList.put(MyProperty.COMMONNAME, "Poisonous Potato");
    
        vegList.add(new Vegetable("Horror", propertyList));
    

    我意识到在做这件事的时候(基本上是从Head First OOA&D开始做我自己的例子),我不知道为什么要第二次更改propertyList 影响之前在Maisie中设置的值。

    我遵循了这本书提供的结构,但在第一次将其添加到列表之前,我为每个单独的蔬菜对象创建了一个新的HashMap。这本书表明这是不必要的,但没有深入到 为什么? .

    我所能看到的是,解释器在第二次在蔬菜构造函数中指定hashmap时,正在选择创建一个新的hashmap实例。但是 为什么? ?

    它怎么知道我宁愿在那里有一个不同的HashMap,而不是重用第一个对象和。put()更改两种蔬菜的值?


    第二个相关问题是。。。。如果我真的想让两种蔬菜共享完全相同的属性列表(相同的HashMap对象),我该怎么做?这真的应该是一个可怕的想法。。。为什么?我不知道自己在做什么,怎么会想要这个节目呢?

    我的理解超出了“它与对象引用有关”的范畴。

    谢谢你帮我弄清楚这件事。


    要求的蔬菜等级:

    public class Vegetable {
        public VegetableSpec characteristics;
        public String name;
    
        public Vegetable(String name, Map<MyProperty, Object> propertyList) {
            this.name = name;
            this.characteristics = new VegetableSpec(propertyList);
        }
    
        public void display() {
            System.out.printf("My name is %s!\n", this.name);
            for (Entry<MyProperty, Object> entry : characteristics.properties.entrySet()) {
                System.out.printf("key: %s, val: %s\n", entry.getKey().toString(), entry.getValue().toString());
            }
        }
    }
    

    ... 这让我再次审视了VegetableSpec(我把它放进去是因为这本书使用了一个单独的Spec类,但我不明白为什么除了添加搜索功能之外还需要它;现在我想我看到它有两个功能,一个是防御性复制!):

    public class VegetableSpec {
        Map<MyProperty, Object> properties;
    
        public VegetableSpec(Map<MyProperty, Object> properties) {
            if (properties == null) {
                // return a null = bad way to signal a problem
                this.properties = new HashMap();
            } else {
                // correction above makes it clear this isn't redundant
                this.properties = new HashMap(properties);
            }
    
        }
    
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Michael Lloyd Lee mlk    7 年前

    听起来像是蔬菜的构造器在做一个 defensive copy . 通常,这样做可以防止任何人以对象设计者不希望的方式更改对象。你应该(几乎)一直在制作防御性拷贝。

    我想让两种蔬菜共享完全相同的属性列表(相同的HashMap对象),我该怎么做?

    传入相同的哈希映射,并忽略它生成防御性副本的事实,这对作为消费者的您来说并不重要。