突发奇想开展一个专栏叫读书笔记系列,记录自己阅读心得以及理解。后续会想啃一些大部头的计算机专业基础弥补自己的短板。
简单说明:
本章介绍的java的关键字:private,public,protected,package。通过阅读Bruck Eckel(作者,同时也是thinkg in java作者)感受这些的关键字作用,以及这样设计的思路。
其实编程也是的一个工程的学科,个人认为好的工程非常讲究设计与迭代。因为代码的使用群体可以分来代码开发者(developer),以及代码使用者(user)。那么developer如何开发一个好的工具包给user使用,以及developer在提供的工具包同时,如何自己的不断迭代优化已经提供出去的工具包。个人认为本章内容就是探讨这样的问题。
文章可以归纳成三个方面梳理一下的关键字(packge,访问控制修饰符)
1. package
1.1 package作用
package包其实更多就是一种命名空间,去用来的区分不同的包的。像下面的代码展示
Map map = new HashMap();
map.put("test","onJava");
System.out.println((String) map.get("test"));
代码中构建了一个map对象,然后往对象里面添加一些数据。正常我们写的代码也是如此,很多时候我们网上参考别人的解决方案,他们贴出来的代码也是这样子。出来的结果如下。
会发现跟预期的结果猜想不一样, 因为这个类是我自己重新写的。我把完整的class代码粘贴出来,你会发现我map是没有把java.util.map 去import到测试类上面。
package com.lucas;
/**
* @program: GMUtils
* @author: lucasLu
**/
public class Test {
public static void main(String[] args) {
Map map = new HashMap();
map.put("test","onjava");
System.out.println((String) map.get("test"));
}
}
所以package的引入可以帮忙解决一下名字同名的问题,然后我们包名一般都会是域名倒过来写(域名是独一无二的),所以按照这个契约约定,我们想写出来的工具包才不会跟别人产生冲突。像上面的例子,如果你是编译器,在你现在的大脑里面有两个Map(java.util.Map 跟 onJava.Map),你也不知道此处的代码应该选哪个。
总结:如果有想写能够提供给其他人的代码,关于package的命名空间要考虑清楚,java关于package的设计就是为了解决同名的冲突。
1.2 classpath
classpath的翻译就是"类路径"。这个classpath给我初期学习的时候,也是带来的困扰。其实的类路径的意思就是告诉编译器、计算机他们。类(.class文件)存放的路径是什么。
java的特性优点就是:一次编译,到处运行。它的编译整个生命周期流程是"把.java的文件 通过编译 生成 .class文件",编译器要识别,运行的程序就是的.class文件。所以要告诉他 类路径在哪里是合理的。
还是原来的类作为例子,只是单纯的看类文件的名字,编译器能够知道如何比较准确跟快速找到这个文件吗?即使知道类路径。所以这里就又跟上面的package关联起来。例子的package的名字是com.lucas,那么可以以“."作为文件分层的依据,把文件的路径构建成如下,那么也是解决了所有文件都以一级目录堆放在一个文件夹上面。
${classPath}/com/lucas/Test.class
2. 访问控制修饰符
在解决了文件的同名冲突的这个问题之后,让java的工具包能够百花齐放之后。那么下一个问题就是在于的如何让developer能够迭代自己的代码同时也尽可能不影响user的使用呢?
所以这章节的名称叫实现隐藏,我个人认为原因也在此。举个例子,例如我提供了一个加密工具包encodeUtils,里面有一个方法是encode使用A方法去加密的。user在一直在用encodeUtils.encode(),后面某个时刻,我发现A方法不够安全,想迭代成更安全的方法。此时我可以修改原来的encode方法,或者是构建新的一个方法是encodeOtherWay()。那么如果A方法是一个超级不安全的方法,我是希望是大家都不要用,因为怕产生生产环境问题,我下个版本的工具包直接删掉其实是不太妥当的,那么其实我是可以在原来的encode方法修复好问题,那么user在使用的时候,也不需要因为我的修改,而导致他们要被动跟着修复问题。这个就是实现隐藏,或者我们日常开发的时候。都会写XXXservice接口,然后写XXserviceImpl作为该接口的实现。
一般的访问控制修饰符,会有public、private、protected,默认的包访问。访问控制修饰符的意义在于developer跟user之间。例如我们学习一个新的工具类的时候,总是可以快速看到他们API去知道他们提供什么方法。那么这个就是developer想让你知道的,而关于具体如何实现,通过什么对象组合在一起的,那么就可以选择非public的。再针对其他情况,developer在开发自己的工具包的时候会加入是否具有自定义扩展性的想法, 那么就可以选择的适度的开放字段、方法给到想实现接口的developer,那么就使用使用protecet的去限制访问。沿着思路再进一步,如果是想收窄访问范围,那么可以直接只提供给本类去使用,那么private就可以了。
修饰符 | 可触达的域 |
---|---|
public | 所有人都可以访问 |
private | 只有本类才可以访问 |
protected | 只有本类或继承的类可以访问;即使跨包也可以。 |
默认包访问 | 只有一个package下都可以。 |
总结:个人认为,java就是想通过的访问修饰符,同控制好代码之间的交互。因为在日常开发中,开发人员会存在两种角色(developer,user),developer会有代码设计或者成员变量是不希望被修改,否则会怕引起不可预期的后患。因为站在user的角度,无法知道哪些类的成员变量可以改,哪些不可以改。如果没有的修饰符作为辅助提醒,也容易去修改了developer本身设计好底层的东西。这不一定会是一个好事情,虽然体现了user的能力很强。