类和接口的使用-类和成员可访问性最小化

时间:2021-08-30 04:22:10

一个良好的程序设计应该是层次清晰,各模块对于外部模块来说,是否只提供了对外的API而隐藏了具体的实现细节,通常对于使用者而言,只需要知道实现功能的API 而无法操作具体实现的过程,这种设计理念被称为信息隐藏也就是我们通常所说的封装。

对于顶层的设计 例如接口之类的类只有两种访问级别

包级私有(只能被同级包下的其他类和接口访问  也就是默认修饰符 default)和公有(public)

举个例子

 
 
package IO.Demo;
public interface DemoTest {
    static final String NUMBER="ONE";
}
package IO.FileIo;

import IO.Demo.DemoTest;

public class Demo {
private DemoTest demoTest;
}
 

接口 DemoTest 和类 Demo 分别属于不同的包

IO.Demo和IO.FileIo

请注意这时的 DemoTest 是属于*接口 被public修饰 表示公有的 这时它可以在Demo类中被调用

假如此时去掉public修饰符 则此时的会发生这样的情况

类和接口的使用-类和成员可访问性最小化

 

Demo此时无法调用接口 原因就是不在同级包下无法调用

如果类和接口能被设定为包级私有的,请将它设计为包级私有的

 

对于成员(域(也就是变量常量)、方法、嵌套类和嵌套接口)有四种可能的访问级别

1 private (私有的)  只有在声明的该成员的顶层类内部才能访问到这个成员 但是有一点需要注意 在接口里面是不能被声明为private的。 大家可以考虑下为什么会是这样?

类和接口的使用-类和成员可访问性最小化

2 包级私有的 简称缺省的(default)   

3 受保护的(protected) 声明该成员的子类可以访问这个成员(有一定限制)

4 公有的(public) 表示在任意地方都可以访问该成员 

以上的4中访问修饰符是按照访问递增等级排列的。

举个应用例子

package IO.FileIo;



public class Demo {
    private static  void run(){

    }

    public static void startRun(){
            run();
    }

    public static void main(String[] args) {
        Demo.startRun();
    }
}

在同包内的Test类中无法调用Demo类私有的Run()方法 但是Demo提供了使用Run方法的startRun()方法

这种做法就是应用了封装的理念

类和接口的使用-类和成员可访问性最小化

最近项目中 有一个程序设计的要求是要求把数据库查询的数据存储到内存中,减少对数据库的访问次数,减少程序的开销

package IO.FileIo;


import java.util.HashMap;
import java.util.Map;

public class Demo {
    private static Map<String,Object> cache=new HashMap<String,Object>();
    private static  Map<String,Object> run(){
        //假定这个方法里面执行了获取数据库数据的方法 getData():
        //cache=getData();
        //此时cache里面已经存在了数据 注意看cache是被static修饰的 cache存在方法区中
        // 方法区在JVM中也是一个非常重要的区域,它与堆一样,是被线程共享的区域。
        // 在方法区中,存储了每个类的信息(包括类的名称、方法信息、字段信息)、静态变量、常量以及编译器编译后的代码等。
        // 所以此时cache的值被存储在内存中
    return cache;
    }

    public static Map<String,Object> startRun(){
       return run();
    }

}

如何拿到这个map

package IO.FileIo;

import java.util.Map;

public class Test {

    public static void main(String[] args) {
        //此时调用的Demo.startRun() 会有一个Map的引用被传回来 我们就可以对数据进行操作了
        //在spring框架中Controller层就可以把这个map传到页面呈现
        Map<String,Object> map= Demo.startRun();

    }
}

在这里我们用到了啥 

 private static Map<String,Object> cache=new HashMap<String,Object>();

 

Demo类中cache是私有的 我们对外提供了获得这个对象引用的API
startRun()
在其他类中我们就可以调用这个方法来获取cache 而隐藏了具体怎么获得cache的细节

对于类的设计而言 ,类的域决不能是公有的(public)

例如这样

public class Test {

    public String password; }

此时的password可以被任意类被使用修改数值 假如这个属性被你用作充当用户的密码属性 这是灾难性的后果

public class Demo {
    public static void main(String[] args) { Test test=new Test(); test.password="1"; System.out.println(test.password); } }

在其他类中 Test的password域直接被修改,这并不是程序设计的初衷,这样会导致数据的不可控

 java是面向对象的所以java提供了让外部操作内部数据域的方法 get/set

这里提供了最简单的get/set方法实现(spring ioc的依赖注入于这种方式来注入)

public class Test {

    private String password; public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }

这样程序的数据域就在可控制的范围 ,开发程序的过程中完全可以在setPassword()中对数据域进行限制,而不是让数据被肆无忌惮的修改