美文网首页
使类和成员的可访问性最小化

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

作者: 998584f56259 | 来源:发表于2016-09-14 15:07 被阅读49次

    1、对于顶层的(非嵌套的)类和接口,只有两种可能的访问级别:包级私有的(package-private)和公有的(public)。如果类或者接口能够做成包级私有的,它就应该被做成包级私有。通过把类或者接口做成包级私有,它实际上成了这个包的实现的一部分,而不是包导出的API的一部分。

    2、如果一个包级私有的顶层类(或者接口)只是在某一个类的内部被用到,就应该考虑使它成为唯一使用它的那个类的私有嵌套类。

    3、对于成员(域、方法、嵌套类和嵌套接口)有四种可能的访问级别,下面按照可访问性的递增顺序列出来。private 、 package-private、 protected 、public。

    4、私有成员和包级私有成员都是一个类的实现中的一部分,一般不会影响它的导出的API。然而,如果这个类实现了Serializable接口,这些域就有可能会被“泄露”到导出的API中。

    5、对于公有类的成员,访问级别从包级私有变成保护级别时,会大大增强可访问性,受保护的成员是类的导出的API的一部分,因此,受保护的成员应该尽量少用。

    6、如果方法覆盖了超类中的一个方法,子类中的访问级别就不允许低于超类中的访问级别。这样可以确保任何使用超类实例的地方也都可以使用子类的实例。这个规则还有一个特殊的情形:如果一个类实现了一个接口,那么接口中所有的类方法在这个类中也都必须被声明为公有的。之所以如此,是因为接口中的所有方法都隐含着公有访问级别。

    7、实例域决不能是公有的。如果域是非final的,或者是一个指向可变对象的final引用,那么一旦使这个域成为公有的,就放弃了对存储在这个域中的值进行修改的能力,这意味着,也就放弃了强制这个域不可变的能力。同时,当这个域被修改的时候,你也就失去了对它采取任何行动的能力。因此,包含公有可变域的类并不是线程安全的。即使域是final的,并且引用不可变的对象,当把这个域变成公有的时候,也就放弃了“切换到一种新的内部数据表示法”的灵活性。同样的建议也适用于静态域,只是有一种例外情况。假设常量构成了类提供的整个抽象中的一部分,可以通过公有的静态final域来暴露这些常量。

    8、注意:长度非零的数组总是可变的,所以,类具有公有的静态final数组域,或者返回这种域的访问方法,这总是错误的。如果类具有这样的域或者访问方法,客户端将能够修改数组中的内容。这是安全漏洞的一个常见根源。

        //Potential security hole! 潜在的安全漏洞
        public static final Thing[] VALUES = {...... }
    

    要注意,许多IDE会产生返回指向私有数组域的引用的访问方法,这样就会产生这个问题。要修正这个问题有两种方法:

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

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

    2、第二种方法:使数组变成私有的,并添加一个公有方法,它返回私有数组的一个备份。

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

    相关文章

      网友评论

          本文标题:使类和成员的可访问性最小化

          本文链接:https://www.haomeiwen.com/subject/voevettx.html