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

时间:2021-03-04 04:21:35

       模块之间只能通过api进行通信,也就是通过暴露出来的预先定义好的函数进行通信,一个模块不需要,也不应该知道其他模块的内部工作情况,这个概念叫做信息隐藏,,也叫封装,是软件设计的重要的基本原则之一。之所以重要,是因为它能有效地解除各模块的耦合关系,使得各模块能够进行独立的开发,测试,优化,使用,和修改。

 可能的四种访问级别有:

        一   私有的(private)

       二   公有的(public)

       三   受保护的(protect)

       四   包级私有的(package-private)

       大多数人开始学java,只了解前三种,而不了解第四种,简单介绍一下第四种-包级私有 

  对于Java类的访问修饰符有public, 包级私有两种

       在项目pro下包和类的组织如下:

       Java代码  

  1. //pro  
  2.    //mypack1  
  3.        //Student.java  
  4.        //Test.java  
  5.    //mypack2  
  6.        //Test.java 
       如果Student的声明为

       public  class Student{}

       那么为公有,这时候两个包mypack1和mypack2的Test类都能够访问到Student类

      如果Student的声明为

       class Student{}

       那么为包级私有,这时候在同一个包下的mypack1才能访问Student类,mypack2不行。

       这就是包级私有。

 对于顶层的类和接口,只有两种可能的访问级别:包级私有的和公有的。如果用public修饰了顶层类或接口,那么它就是公有的,否则就是包级私有的。

重要的几个原则:

       一   如果类或者接口能过被做成包级私有的,那么他就应该被做成包级私有的。

       通过把类或者接口做成包级私有,实际上它就成了这个包中实现的一部分,而不是该包导出的API的一部分。这样,在以后对它进行修改,替换,或者删除的时候,就不会担心影响到现有的客户端,如果把它做成公有的,那么你永远都要考虑兼容性去维护它。

      二    一个包级私有的顶层类只是在某一个类的内部被用到,那么就考虑使它成为唯一使用它的那个类的私有嵌套类。

      这样可以把它的访问范围从包中的所有类缩小到了使用它的那个类。

      三   当访问级别从包级私有变成保护级别时,会大大增强其访问性。

     受保护成员是类的导出的API的一部分,必须得到永久支持。因此少用受保护的成员。

    四   如果方法覆盖了超类的一个方法,子类的访问级别就不允许低于超类中的访问级别。

     这样可以确保任何可使用超类实例的地方也可以使用子类,否则编译器会报错。

     特殊的情形是:如果一个类实现了一个接口,那么接口中的所有类方法在这个类中必须都是公有的,原因是接口的所有方法都隐含着公有访问级别。

    五  实例域绝对不能是公有的。

       什么是实例域?通俗来说,人是动物的一个实例,那么人的所有成员,比如说手,脚,身高等具体的键值都是他的实例域。

       原因是如果一旦使这个域,就相当于放弃了对存储在这个域的值进行限制的能力,同时,当这个域被修改时,你也失去的对他采取行动的能力。

       静态域也适用于这个规则。但只有一种特殊情况——通过公有的静态final域去暴露常量。

       六  类不能拥有公有的静态final数组域,原因是客户端能够改变数组的内容!

        public static int[] values={1,2,3};//potential security hole!

       应该这么做:

               private static int[] FIRST_VALUES={1,2,3};

              public static final List<Integer> values=Collections.unmodifiableList(Arrays.asList(FIRST_VALUES));

       或者

               private static int[] FIRST_VALUES={1,2,3};

               public static final int[] values(){

                      return  FIRST_VALUES.clone();

          }    

     如何选择就要看你的需求

    

     这是我结合书本总结出来的一些方法,希望它能帮助大家不断优化自己的代码!