封装与集合_回归基础:封装集合

封装与集合

年轻的时候,我了解了面向对象范例的3个属性:

  • 封装形式
  • 遗产
  • 多态性

在Java中,封装是通过将私有属性与访问器方法(通常称为getter和setter)一起使用来实现的。 这种封装是否正确尚有争议,不在本文讨论范围之内。 但是,当属性是一个集合(类型为java.util.Collectionjava.util.Map及其子类型)时,使用此方法来实现封装是完全错误的。

我经常看到的代码如下:

publicclassMyBean{

    privateCollectioncollection;

    publicCollectiongetCollection(){
        returncollection;
    }

    publicvoidsetCollection(Collectioncollection){
        this.collection=collection;
    }
}

这是我看到的最常见的代码:该设计已被Hibernate之类的ORM框架所普及。 很多时候,我提出这一点时,下一个建议就是一成不变的。

publicclassMyBean{

    privateCollectioncollection;

    publicMyBean(Collectioncollection){
        this.collection=collection;
    }

    publicCollectiongetCollection(){
        returncollection;
    }
}

没有适当的封装

但是,对于集合来说,这没有任何变化,因为Java集合本身是可变的。 显然,在构造函数中传递对集合的引用并返回对它的引用完全不是封装。 仅当不保留也不返回任何对集合的引用时,才可以进行真正的封装。

Listlist=newArrayList();
MyBeanmybean=newMyBean(list);
list.add(newObject());// We just modified the collection outside my bean

无法使用特定的子类型

此外,我的bean可能需要自己的特定集合,例如ListSet 。 使用以下代码段,根本不可能传递Set

publicclassMyBean{

    privateListcollection;

    publicListgetCollection(){
        returncollection;
    }

    publicvoidsetCollection(Listcollection){
        this.collection=collection;
    }
}

没有选择具体的实现

作为最后的推论,使用提供的引用会阻止我们使用我们自己的(也许更高效)类型, 例如 Apache Commons FastArrayList。

实施方案

任何真正封装的起点如下:

publicclassMyBean{

    privateListcollection=newArrayList();

    publicMyBean(Collectioncollection){
        this.collection.addAll(collection);
    }

    publicCollectiongetCollection(){
        returnCollections.unmodifiableList(collection);
    }
}

这修复了上述缺点:

  1. 构造函数中不传递对集合的引用,因此可以防止在对象外部进行任何后续更改
  2. 自由使用选定的收集实现,完全隔离-留有更改的空间
  3. 在getter返回的集合中没有传递对包装的集合的引用
以前的代码段不使用泛型来简化可读性,请使用它们。

翻译自: https://blog.frankel.ch/back-to-basics-encapsulating-collections/

封装与集合

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值