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

概要

1.使类和成员的可访问性最小化的意义

2.类和成员的可访问性类别

3.其他注意事项

4.最后的原则


一、使类和成员的可访问性最小化的意义

1. 概念:信息隐藏(或者"封装")

一个模块对外部模块隐藏其内部数据和其他实现细节,将它的API与它的实现细节清晰地隔离开来,模块之间只通过API进行通信,其他模块不需要知道该模块的内部工作情况。

2. 封装的作用

(1) 有效的解除组成系统的各模块之间的耦合关系,使得各个模块可以独立地开发,测试,优化,使用,理解和修改。

(2) 减轻程序员维护的负担。维护的模块的时候,只需要维护单个的模块,不用考虑其它模块的事情,只需要考虑模块对外提供的API。

(3) 模块复用,可以将模块移植到其他系统(模块拆分),重复使用

(4) 优化方便,检测性能的时候,可以确定出是哪个模块的问题,只需要专门针对该模块进行优化

二、类和成员的几种可访问性

1.顶层类(非嵌套)和接口,有两种访问级别,包级私有和公有的

顶层类,如果是包级私有,只有该包中的类才能使用它

接口,如果是包级私有,只有该包中的类能实现它

package test.topclass;

    class OneClass {

}

--------------------------------------

package test.topclass;

    interface OneInterface {

}

----------------------------------------

package test.topclass;

public class TestClass implements OneInterface{
    public static void main(String[] args) {
        OneClass one = new OneClass();
    }
}

2.私有嵌套类(或者接口)

如果一个包级私有的顶层类(或者接口)只是在某一个类的内部被用到,就应该考虑使它成为唯一使用它的那个类的私有嵌套类(或者接口)。这样可以将它的可访问范围从包中的所有类缩小到了使用它的那个类

package test.privateclass;

class TopClass {
    private interface TopInterface {

    }
   
    private class UserClass {
        private TopInterface oneInterface = new TopInterface(){};
        private TopClass oneClass = new TopClass();
    }
}

3.类成员(域,方法,嵌套类和嵌套接口),有四种可访问级别

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

包级私有的(package-private) -- 声明该成员的包内部的任何类都可以访问这个成员。从技术上讲,它被称为"缺省(default)访问级别",如果没有为成员指定访问修饰符,就采用这个访问级别

受保护的(protected) -- 声明该成员的类的子类可以访问这个成员,并且,声明该成员的包的内部的任何类也可以访问这个成员

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

访问权限        类         包        子类        其他包

public              √           √           √               √

protected        √           √            √               ×

default            √           √            ×               ×

private             √            ×           ×                ×

对于接口的成员,只有一种访问级别,公有的。(下面例子是错误的)

package test;

public interface OneInteface {
    private int ten = 10;
    private void add();
}

三、其他注意事项

1.实例域决不能是公有的

如果域是非final的,或者是一个指向可变对象的final引用,那么一旦使这个域成为公有的,就放弃了对存储在这个域中的值进行限制的能力

2.静态公共域只能为final修饰的基本类型或者final修饰的不可变类

假设常量构成了类提供的整个抽象中的一部分,可以通过公有的静态final域来暴露这些常量

package test.other;


public class PublicClass {
    public static final String STRING_HELLO="HELLO";

}

final修饰引用类型的变量:test.staticpublic

3.长度非零的数组总是可变的,可被修改的

package test.other;


public class PublicArray {
    public static final int[] VALUES = { 1, 2, 3 };
    private static final float[] VALUES_FLOAT = {1.2f,1.3f};

    public static float[] getFloatArray(){
    return VALUES_FLOAT;
    }

    public static void main(String[] args){
    PublicArray.VALUES[0] = 10;
    PublicArray.getFloatArray()[0] = 10.2f;
        System.out.println("--------VALUE----------");
        for(int value:VALUES) {
            System.out.println(value+"");
        }
        System.out.println("--------VALUE_FLOAT----------");
        for(float valueFloat:VALUES_FLOAT) {
            System.out.println(valueFloat+"");
        }
    }
}



package test.other;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class PublicArrayTwo {
    private static final int[] VALUES = { 1, 2, 3 };
    private static final float[] VALUES_FLOAT = { 1.2f, 1.3f };

    public static final List<int[]> values() {
    return Collections.unmodifiableList(Arrays.asList(VALUES));
    }

    public static final float[] getFloatArray() {
    return VALUES_FLOAT.clone();
    }
}

package test.other;

import java.util.List;

public class TestPublicArrayTwo {
    public static void main(String[] args) {
        List<int[]> pat = PublicArrayTwo.values();
        if(pat.size() > 0){
            int[] publicArray = pat.get(0);
            for(int i = 0; i < publicArray.length; i++){
            int j = publicArray[i];
            System.out.println(j);
            }
        }
        System.out.println("------------------------------------------------");
        float[] oneFloat = PublicArrayTwo.getFloatArray();
        for(int i = 0; i < oneFloat.length; i++){
        System.out.println(oneFloat[i]);
        }
    }
}

四、最后的原则

总而言之,你应该始终尽可能地降低可访问性。你在仔细地设计了一个最小的公有API之后,应该防止把任何散乱的类、接口和成员变成API的一部分。除了公有静态final域的特殊情形之外,公有类都不应该包含公有域。并且要确保公有静态final域所引用的对象都是不可变的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容