Note when going straight for success of Mr.Wang

0%

必读图书

计算机组成原理(大学教材)

操作系统(大学教材)

计算机网络(大学教材)

算法与数据结构(大学教材或谢路云译第4版)

Java编程思想

阿里巴巴 Java 开发手册

Clean Code-代码整洁之道

重构 改善既有代码的设计

Head First Java

Head First Design Patterns

Java 核心技术卷

Effective Java

Java 并发编程实战

深入理解Java虚拟机

其他

  1. 在使用正则表达式时,利用好其预编译功能,可以有效加快正则匹配速度。
    反例:
    Pattern pattern = Pattern.compile(“regex”);
    //todo: reason: why?

  2. 注意 Math.random() 这个方法返回是 double 类型,注意取值的范围 0≤x<1(能够取到零值,注意除零异常),如果想获取整数类型的随机数,不要将 x 放大 10 的若干倍然后取整,直接使用 Random 对象的 nextInt 或者 nextLong 方法。
    // todo:

  3. 获取当前毫秒数 System.currentTimeMillis(); 而不是 new Date().getTime();
    reason:为什么不用new Date(),看源码,是多此一举。先用 System.currentTimeMillis(),在getTime获取System.currentTimeMillis()。
    正例:如果想获取更加精确的纳秒级时间值,使用 System.nanoTime()的方式。在 JDK8 中,针对统计时间等场景,推荐使用 Instant 类。
    https://blog.csdn.net/weixin_41987908/article/details/89204729

  4. 日期格式化:
    yyyy 表示当天所在的年,而大写的 YYYY 代表是 week in which year(JDK7 之后引入的概念),意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,返回的 YYYY 就是下一年。另外需要注意:
    表示月份是大写的 M
    表示分钟则是小写的 m 24 小时制的是大写的 H 12 小时制的则是小写的 h
    正例:yyyy-MM-dd HH:mm:ss

  5. 任何数据结构的构造或初始化,都应指定大小,避免数据结构无限增长吃光内存

  6. 及时清理不再使用的代码段或配置信息。
    正例:对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码上方,统一规定使用三个斜杠(///)来说明注释掉代码的理由。

注释规约

  1. 类、类属性、类方法的注释必须使用 Javadoc 规范,使用/内容*/格式,不得使用// xxx 方式。**
    reason: 增强可读性(工程调用方法时,不进入方法即可悬浮提示方法、参数、返回值的意义,提高阅读效率。)

    阅读全文 »

控制语句

  1. 在一个 switch 块内,每个 case 要么通过 continue/break/return 等来终止,要么注释说明程序将继续执行到哪一个 case 为止;在一个 switch 块内,都必须包含一个 default 语句并且放在最后,即使它什么代码也没有。
    reason: 有确定性的退出程序,不然以后程序会执行到哪个地方自己都搞不清楚

    阅读全文 »

代码格式

  1. 如果是大括号内为空,则简洁地写成{}即可,大括号中间无需换行和空格;如果是非空代码块:
    1) 左大括号前不换行。
    2) 左大括号后换行。
    3) 右大括号前换行。
    4) 右大括号后还有 else 等代码则不换行;表示终止的右大括号后必须换行。

  2. 左小括号和字符之间不出现空格;同样,右小括号和字符之间也不出现空格

  3. if/for/while/switch/do 等保留字与括号之间都必须加空格。

  4. 任何二目、三目运算符的左右两边都需要加一个空格

  5. 采用 4 个空格缩进,禁止使用 tab 字符
    reason: 国标是4个空格,一个tab字符不一定是四个空格,若使用tab,必须对编译器设置:
        idea设置方式:todo:
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    public class FormatClass {
    public static void main(String[] args) {
    // 缩进 4 个空格
    String say = "hello";
    // 运算符的左右必须有一个空格
    int flag = 0;
    // 关键词 if 与括号之间必须有一个空格,括号内的 f 与左括号,0 与右括号不需要空格
    if (flag == 0) {
    System.out.println(say);
    // 左大括号前加空格且不换行;左大括号后换行
    if (flag == 1) {
    System.out.println("world");
    // 右大括号前换行,右大括号后有 else,不用换行
    } else {
    System.out.println("ok");
    // 在右大括号后直接结束,则必须换行
    }
    }
    }
    }
  6. 注释的双斜线与注释内容之间有且仅有一个空格

  7. 在进行类型强制转换时,右括号与强制转换值之间不需要任何空格隔开
    正例:
    long first = 1000000000000L;
    int second = (int)first + 2;

  8. 单行字符数限制不超过 120 个,超出需要换行
    1)第二行相对第一行缩进 4 个空格,从第三行开始,不再继续缩进。
    2)运算符与下文一起换行。
    3)方法调用的点符号与下文一起换行。
    4)方法调用中的多个参数需要换行时,在逗号后进行。
    5)在括号前不要换行
    code:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 正例
    StringBuilder sb = new StringBuilder();
    // 超过 120 个字符的情况下,换行缩进 4 个空格,点号和方法名称一起换行
    sb.append("Jack").append("Ma")...
    .append("alibaba")...
    .append("alibaba")...
    .append("alibaba");
    // 反例
    StringBuilder sb = new StringBuilder();
    // 超过 120 个字符的情况下,不要在括号前换行
    sb.append("Jack").append("Ma")...append
    ("alibaba");
    // 参数很多的方法调用可能超过 120 个字符,不要在逗号前换行
    method(args1, args2, args3, ...
    , argsX);
  9. 方法参数在定义和传入时,多个参数逗号后边必须加空格
    正例:method(args1, args2, args3)

  10. IDE 的 text file encoding 设置为 UTF-8; IDE 中文件的换行符使用 Unix 格式,不要使用 Windows 格式。
    reason: 很多windows格式会有问题,比如记事本开头添加0xefbbbf(十六进制)的字符,会导致文本问题
    配置方式:todo:

  11. 单个方法的总行数不超过 80 行(除注释之外的方法签名、左右大括号、方法内代码、空行、回车及任何不可见字符的总行数不超过
    80行, 建议把独立的逻辑抽取出来形成单独的方法,清晰明了)

  12. 没有必要增加若干空格来使变量的赋值等号与上一行对应位置的等号对齐。
    reason: 并不好看;变量比较多的情况下会非常麻烦;
    正例:

    1
    2
    3
    4
    int one = 1;
    long two = 2L;
    float three = 3F;
    StringBuilder sb = new StringBuilder();
  13. 不同逻辑、不同语义、不同业务的代码之间插入一个(仅仅一行就够了)空行分隔开来以提升可读性。

常量定义

  1. 不允许任何魔法值(即未经预先定义的常量)直接出现在代码中
    反例:String key = “Id#taobao_” + tradeId;
       cache.put(key, value);
       代码复制时容易漏掉下划线,导致缓存击穿而出现问题

    阅读全文 »

命名风格

  1. 命名均不能以下划线()或美元符号($)开始,也不能以下划线()或美元符号($)结束。
    反例:name / __name / $name / name / name$ / name__
    reason:python下划线开头是内部变量.

    阅读全文 »

设计模式之策略模式

定义

  策略模式(Strategy Pattern):定义一系列算法类,将每一个算法封装起来,并让它们可以相互替换,策略模式让算法独立于使用它的客户而变化,也称为政策模式(Policy)。策略模式是一种对象行为型模式。

了解

  策略模式实用性强、扩展性好,在软件开发中得以广泛使用,是使用频率较高的设计模式之一
  策略模式将原本庞大的算法类的职责进行分解,将算法的定义和使用分离。我们可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法,在这里,每一个封装算法的类我们都可以称之为一种策略(Strategy),为了保证这些策略在使用时具有一致性,一般会提供一个抽象的策略类来做规则的定义,而每种算法则对应于一个具体策略类。
  策略模式的主要目的是将算法的定义与使用分开,将算法的定义放在专门的策略类中,每一个策略类封装了一种实现算法,使用算法的环境类针对抽象策略类进行编程,符合“依赖倒转原则”。在出现新的算法时,只需要增加一个新的实现了抽象策略类的具体策略类即可。

阅读全文 »

设计模式之代理模式

定义

  代理模式:给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

了解

  代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理远程代理虚拟代理缓冲代理智能引用代理等,它们应用于不同的场合,满足用户的不同需求。
  代理模式是一种对象结构型模式。在代理模式中引入了一个新的代理对象,代理对象在客户端对象和目标对象之间起到中介的作用,它去掉客户不能看到的内容和服务或者增添客户需要的额外的新服务

  • 远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又称为大使(Ambassador)。
      为位于两个不同地址空间对象的访问提供了一种实现机制,可以将一些消耗资源较多的对象和操作移至性能更好的计算机上,提高系统的整体运行效率。
  • 虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
      通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销
  • 保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
  • 缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
      为某一个操作的结果提供临时的缓存存储空间,以便在后续使用中能够共享这些结果,优化系统性能,缩短执行时间。
  • 智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等。
阅读全文 »

设计模式之享元模式

定义

  享元模式(Flyweight Pattern):运用共享技术有效地支持大量细粒度对象的复用。系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式,它是一种对象结构型模式。

了解

  当一个软件系统在运行时产生的对象数量太多,将导致运行代价过高,带来系统性能下降等问题。比如在一个文本字符串中存在很多重复的字符,如果每一个字符都用一个单独的对象来表示,将会占用非常多的内存空间。
  享元模式通过共享技术实现相同或相似对象的重用。仍拿字符串为例,在逻辑上每一个出现的字符都有一个对象与之对应,然而在物理上它们却共享同一个享元对象,这个对象可以出现在一个字符串的不同地方,相同的字符对象都指向同一个实例,在享元模式中,存储这些共享实例对象的地方称为享元池(Flyweight Pool)。我们可以针对每一个不同的字符创建一个享元对象,将其放在享元池中,需要时再从享元池取出。
  享元模式以共享的方式高效地支持大量细粒度对象的重用,享元对象能做到共享的关键是区分了内部状态(Intrinsic State)外部状态(Extrinsic State)

  • 内部状态是存储在享元对象内部并且不会随环境改变而改变的状态,内部状态可以共享。如字符串中字符的内容,不会随外部环境的变化而变化,无论在任何环境下字符“a”始终是“a”,都不会变成“b”;
  • 外部状态是随环境改变而改变的、不可以共享的状态。享元对象的外部状态通常由客户端保存,并在享元对象被创建之后,需要使用的时候再传入到享元对象内部。一个外部状态与另一个外部状态之间是相互独立的。如:字符串中字符的颜色,可以在不同的地方有不同的颜色,例如有的“a”是红色的,有的“a”是绿色的,字符的大小也是如此,有的“a”是五号字,有的“a”是四号字。而且字符的颜色和大小是两个独立的外部状态,它们可以独立变化,相互之间没有影响,客户端可以在使用时将外部状态注入享元对象中。

  因此可以将具有相同内部状态的对象存储在享元池中,享元池中的对象是可以实现共享的,需要的时候就将对象从享元池中取出,实现对象的复用。通过向取出的对象注入不同的外部状态,可以得到一系列相似的对象,而这些对象在内存中实际上只存储一份

阅读全文 »