Effective Item - 使可访问性最小化

模块设计是否良好,有个重要的因素在于,相对外部模块是否隐藏内部数据以及实现细节。
设计良好的模块会隐藏实现细节,并将API与其实现隔离开来。
模块之间通过API进行通信,对于内部工作情况互不可见。
即,封装(encapsulation)——软件设计的基本原则之一。

为什么要封装?
通过封装可以有效地接触各个模块之间的耦合关系,使这些模块可以独立地开发、测试、优化、使用、理解和修改。
即:

  • 可以增加开发效率,模块可以并行开发。
  • 封装可以减轻维护的负担,可以更有效的进行优化,且不会影响其他模块的正确性。
  • 提高了软件的可重用性,模块在其他环境中也可以被使用。

(PS:回想我自己以前用php写网站时根本没有这些概念也不影响开发工作。当时觉得没什么,因为是我一个人写的,再加上后来也没有再扩展,于是没有了种种体会。)

可以通过访问控制保证封装。
一个实体的可访问性是通过实体声明所在的位置和访问修饰符共同决定的。
建议尽可能地使每个类或者成员不被外界访问

对于顶层的类和接口只有两种访问级别:包级私有公有
更小的可访问性代表更小的兼容性,在以后发行的版本中可以放心对其进行修改。
如果是公有的,则需要一直考虑客户的行为。(PS:如果一个顶层类只是在某一个类的内部被用到,则可以声明为私有静态内部类。)
比如这样一个类,这样做在以后的版本中便无法改变表示方式,而且无法加入任何约束:

class Point {
    public double x;
    public double y;
}

于是正如很多人的习惯那样,对于公有类用公有的访问方法替代公有field以保证数据在类内部的灵活性:
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;
    }
}

(PS:当然,有些常见的类并没有遵守这一规则比如java.awt.Point、java.awt.Dimension。
但原作者也明确指出这些类不值得效仿。)

如果一个field只能是公有的,且允许将其声明为final,则危害能少一些。
我们仍然可以通过公有的访问方法访问该field。
但不能用公有的setter,而是通过构造器加入约束:

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
}

对于成员(field,method,嵌套类,嵌套接口)有4种访问级别:

  • private
  • package-private(default)
  • protected
  • public

当设计了类的公有API后,我们将所有成员都变成私有。
然后发现同一个包内的另一个类也需要访问这个成员,于是便修改访问级别。如果这种事情经常发生则应该检查设计是否合理。
虽然package和private级别的成员都是类实现的一部分,不会影响导出的API。
但,该类实现了Serializable时则另当别论。
如果使用protected修饰,则需要注意,该成员时导出的API的一部分。

另外,实例field尽量不要设置为公有。如果一个field不是final或者是一个指向可变对象的final field,公有的访问级别会破坏该field的不可变性,它已不是一个内部的数据表示,而且非线程安全。
当然,这对于长度!=0的数组也是一样的。

如果需要将某数组声明为公有,可以尝试以下方式:

private static final Thing[] PRIVATE_VALUES = {...};
public static final List<Thing> VALUES =
    Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES));

或者可以使用clone,每次都拷贝一个数组:

private static final Thing[] PRIVATE_VALUES = {...};
public static final Thing[] values(){
    return PRIVATE_VALUES.clone();
}
时间: 2024-10-10 06:01:15

Effective Item - 使可访问性最小化的相关文章

Effective Item 9 - 尽量使可访问性最小化

模块设计是否良好,有个重要的因素在于,相对外部模块是否隐藏内部数据以及实现细节. 设计良好的模块会隐藏实现细节,并将API与其实现隔离开来. 模块之间通过API进行通信,对于内部工作情况互不可见. 即,封装(encapsulation)--软件设计的基本原则之一. 为什么要封装? 通过封装可以有效地接触各个模块之间的耦合关系,使这些模块可以独立地开发.测试.优化.使用.理解和修改. 即: ·可以增加开发效率,模块可以并行开发. ·封装可以减轻维护的负担,可以更有效的进行优化,且不会影响其他模块的

Effective Java 第三版——15. 使类和成员的可访问性最小化

Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将近8年的时间,但随着Java 6,7,8,甚至9的发布,Java语言发生了深刻的变化. 在这里第一时间翻译成中文版.供大家学习分享之用. 类和接口是Java编程语言的核心.它们是抽象的基本单位.该语言提供了许多强大的元素,可以使用它们来设计类和接口.本章包含指导原则,帮助你充分利用这些元素,使你的类和接口是可

《Effective Java 第二版》学习笔记 第13条 使类和成员的可访问性最小化

第四章 类和接口 第13条 使类和成员的可访问性最小化 1.设计良好的模块会隐藏所有的实现细节,把它的API与实现清晰的隔离开来,模块之间只通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况:即信息隐藏或封装,是软件设计的基本原则之一. 2.Java提供了许多机制来协助信息隐藏.访问控制(access control)机制决定了类.接口和成员的可访问性(accessibility). 3.第一规则:尽可能地使每个类或者成员不被外界访问.或者说在保证功能的情况下,使用最小的访问级别

第13条:使类和成员的可访问性最小化

区别设计良好的模块和设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它的API于它的实现清晰地隔离开来.然后,模块之间通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念称为信息隐藏或封装.使类和成员的可访问性最小化可以有效的解除系统中各个模块的耦合度.实现每个模块的独立开发.使得系统更加的可维护,更加的健壮.对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别,包级私有的和公有的

13 使类和成员的可访问性最小化

要区别设计良好的模块与设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节.设计良好的模块会隐藏所有的实现细节,把它的API与它的实现清晰地隔离开来. 信息隐藏之所以非常重要有许多原因,其中大多数理由都源于这样一个事实:它可以有效的解除组成系统的各个模块之间的耦合关系,使得这些模块可以独立地开发.测试.优化.使用.理解和修改. 第一个规则很简单:尽可能地使每个类或者成员不被外界访问. 对于顶层的(非嵌套)的类和接口,只有两种可能的访问级别:包级私有的

使类和成员的可访问性最小化

本文涉及到的概念 1.使类和成员的可访问性最低的意义 2.类和成员的几种可访问性 3.其它注意事项 4.最后的原则 1.使类和成员的可访问性最低的意义 信息隐藏(information hiding),封装(encapsulation)的概念 一个模块对外部模块隐藏其内部数据和其他实现细节,也就是将它对外提供的API与它的实现细节清晰地隔离开来,它与其他模块的只通过API进行通信,其他模块不需要知道该模块内部的工作情况. 使用类和成员的可访问性最低的意义 a.可访问性越低,一个类对外暴露的信息就

第四章:类和接口。ITEM13:使类和成员的可访问性最小化。

信息隐藏是软件程序设计的基本原则之一,面向对象又为这一设计原则提供了有力的支持和保障.这里我们简要列出几项受益于该原则的优势:1.更好的解除各个模块之间的耦合关系:由于模块间的相互调用是基于接口契约的,每个模块只是负责完成自己内部既定的功能目标和单元测试,一旦今后出现性能优化或需求变更时,我们首先需要做的便是定位需要变动的单个模块或一组模块,然后再针对各个模块提出各自的解决方案,分别予以改动和内部测试.这样便大大降低了因代码无规则交叉而带来的潜在风险,同时也缩减了开发周期. 2.最大化并行开发:

VC++ 如何使窗体最大化或是最小化

最大化最小的使得的函数是 ShowWindow函数 ShowWindow(SW_SHOWMINIMIZED);//最小化 ShowWindow(SW_SHOWMAXIMIZED);//最大化 ShowWindow(SW_RESTORE);//还原 ------- PostMessage(hwnd,WM_SYSCOMMAND,SC_MINIMIZE,0); SC_MAXIMIZE为最大化. 使用方法: BOOL ShowWindow( int nCmdShow ); 参数 nCmdShow 指定

第八章:通用程序设计。ITEM45:将局部变量的作用域最小化。

1.将局部变量的作用域最小化,可以增强代码的可读性和可维护性,并降低出错的可能性.在 C 语言中要求局部变量必须在一个代码块的开头处进行声明,出于习惯,有些开发者延续了这样的做法. 这个习惯需要改正,Java 提供了你在代码块的任何地方声明变量的语法支持. 2."要使局部变量的作用域最小化,最有力的实践就是在第一次使用它的地方声明".如果过早的声明,开发者就有可能在真正使用该变量的时候忘记了它的类型或者初始值了,而且也会带来代码块内变量名的名字污染问题,由此引发的 Bug,往往是令人极