跟我学(Effective Java 2)第13条:使类和成员的可访问性最小化

跟我学(Effective Java 2)第13条:使类和成员的可访问性最小化第 13 条 使类和成员的可访问性最小化区别设计良好的模块和设计不好的模块 最重要的因素在于 这个模块对于外部的其他模块而言 是否隐藏其内部数据和其他实现细节

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

区别设计良好的模块和设计不好的模块,最重要的因素在于,这个模块对于外部的其他模块而言,是否隐藏其内部数据和其他实现细节。设计良好的模块会隐藏所有的实现细节,把它的API于它的实现清晰地隔离开来。然后,模块之间通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况,这个概念称为信息隐藏(information hiding)或封装(encapsulation)。

封装的目的都源于这样一个事实:可以有效地解除组成系统的各模块之间的耦合关系,使得这些模块可以独立地开发、测试、优化、使用、理解和修改。虽然封装本身不会带来更好的性能,但是它可以有效地调节性能:一旦完成一个系统,并通过剖析确定哪些模块影响了系统的性能,这部分模块就可以被进一步优化,而不影响其他模块的正确性,提高软件的可重用性。

Java提供的访问控制(accesscontrol)机制决定了类、接口和成员的可访问性(accesssibility)。实体的可访问性由该实体声明所在的位置,以及该实体声明中所出现的访问修饰符共同决定的。

第一条规则: 尽可能地使每个类或者成员不被外界访问(6大设计原则之迪米特原则)。

对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别,包级私有的(package-private)和公有的(public)。如果类或者接口可以被做成包级私有,就应该被做成包级私有,这样它实际上成了包的实现的一部分,而不是该包导出的API的一部分,在以后的发行版本中,可以对它进行修改、替换、删除,而无需担心影响现有的客户端程序。如果被做成公有的,就有责任永远支持它,以保持兼容性。

如果一个包级私有的顶层的类(或者接口)只是在某一个类的内部可以被用到,就应该考虑使它成为唯一使用它的那个类的私有嵌套类(内部类)。这样可以进一步缩小到了使用它的那个类。然而降低不必要的共有类的可访问性,比降低包级私有的顶层类的更重要得多:因为公有类是包的API的一部分,而包级私有的顶层类则已经是这个包的实现的一部分。

对于成员(域、方法、嵌套类和嵌套接口)有四种可能的访问级别:

私有的(private)——只有在声明该成员的顶层类内部才可以访问这个成员。

包级私有的(package-private)——声明该成员的包内部的任何类都可以访问这个成员。如果没有为成员指定访问修饰符,就采用这个访问级别,“缺省”受保护的(protected)——声明该成员的子类可以访问这个成员(即使不在同一包),并且声明该成员的包内部任何类也可以访问这个成员。

公有的(public)——在任何地方都可以访问该成员。

只有当同一个包中的另一个类真正需要访问一个成员时,才应该删除private修饰符,使该成员变成包级私有的。私有成员和包级成员都是一个类的实现中的一部分,一般不会影响它导出的API,然而,如果类实现了Serializable接口,这些域就有可能被“泄漏”到导出的API中。

实例域决不能是公有的。如果域是非final,或者是一个指向可变对象的final引用,那么一旦使这个域成为公有的,就放弃了对存储在这个域中的值进行限制的能力。因此,包含公有可变域的类不是线程安全的。即使域是final的,并且引用不可变的对象,当把这个域变成公有的时候,也就放弃了“切换到一种新的内部数据表示法”的灵活性。

注意:长度非零的数组总是可变的,所以,类具有公有的静态final数组域,或者返回这种域的访问方法,这几乎是错误的。这是安全漏洞的一个常见根源:

public static final Thing[] VALUES = { ... }; 

修正的两种办法:

1.可以使公有数组变成私有的,并增加一个公有的不可变列表:

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

2.可以使数组变成私有的,并添加一个公有方法,它返回私有数组的一个备份:

private static final Thing[] PRIVATE_VALUES = { ... }; public static final Thing[] values() { return PRIVATE_VALUES.clone(); } 

总而言之,你应该始终尽量可能地降低可访问性。除了公有静态 final 域的特殊情形之外,公有类都不应该包含公有域。并且要确保公有静态 final 域所引用的对象都是不可变的。

今天的文章 跟我学(Effective Java 2)第13条:使类和成员的可访问性最小化分享到此就结束了,感谢您的阅读。
编程小号
上一篇 2025-01-06 22:21
下一篇 2025-01-06 22:17

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/103129.html