Effective Java 3rd 条目16 在公开类使用访问方法而不是公开域

偶然地你可能忍不住编写一个退化的类,除了把实例域分组以外不作为任何目的:

// 像这样的退化的类不应该是公开的! 
class Point {
    public double x;
    public double y; 
}

因为这样的类的数据域可以直接访问,所以这些类没有提供封装的优点(条目15)。没有改变API你就不能改变这个表示,你不能实现不变性,而且当访问一个域时你不能采取辅助行动。不妥协的面向对象程序员感觉这种类是诅咒,应该总是用这样的类替代:它有私有域和公开访问子方法(accessor method)(getter),而且有对于可变类的设置方法(mutator)(setter):

// 通过访问子方法和设置方法的数据封装
class Point {
    private double x; 
    private double y;

    public Point(double x, double y) { 
        this.x = x; this.y = y; 
    }

    public double getX() { return x; } 
    public double getY() { return y; }

    public void setX(double x) { this.x = x; } 
    public void setY(double y) { this.y = y; }
}

当然,当涉及到公开类,这些不妥协者是正确的:如果一个类在它的包外是可访问的,那么提供访问子方法来维持改变类内部表示的灵活性。如果一个公开类暴露了它的数据域,那么失去了改变它的表示的所有希望,因为客户端代码可以到处分布。

然而,如果一个类是包私有的或者是私有嵌套类,那么暴露它的数据域本质上没有什么错误–假设它们能够充分描述由类提供的抽象。相对于访问子方法,这个方法在类声明中和在使用它的客户端代码中有更少的视觉混乱。虽然客户端代码捆绑于类的内部表示,但是这个代码是限制在包含这个类的包中。如果表示中的改变变得迫切,那么你可以执行这个改变,而没有触碰到包外的任何代码。对于私有内嵌类这个情形,这个改变的范围进一步地限制在包含类中。

Java平台库中的许多类违反了公开类不应该直接暴露域这个建议。显著的例子包括java.awt包中的Point和Dimension类。这些类应该看作警世故事,而不是模仿它们。就像在条目67中描述的一样,暴露Dimension类内部的决定导致了今天仍然困扰我们的严重性能问题。

虽然直接暴露公开类的域从来都不是一个好主意,但是当域是不可变时它有较低危害。你不能改变这种类的表示而没有改变它的API,而且当域是可读的时候,你不可以采取辅助行动,但是你可以实施不可变性。比如,下面的类保证每个实例代表一个有效的时间:

// 暴露不可变域的公开方法 - 有问题的 
public final class Time {
    private static final int HOURS_PER_DAY = 24; 
    private static final int MINUTES_PER_HOUR = 60;

    public final int hour; 
    public final int minute;

    public Time(int hour, int minute) { 
        if (hour < 0 || hour >= HOURS_PER_DAY) 
            throw new IllegalArgumentException("Hour: " + hour); 
        if (minute < 0 || minute >= MINUTES_PER_HOUR) 
            throw new IllegalArgumentException("Min: " + minute); 
        this.hour = hour; 
        this.minute = minute; 
    } 
    ... // Remainder omitted
}

概括起来,公开类从不应该暴露可变域。尽管仍然有问题,但是公开类暴露不可变域有较低危害。然而,包私有的或者私有的内嵌类暴露不管可变与不可变的域,有时是合适的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值