美文网首页
【工作】《码出高效》读书笔记

【工作】《码出高效》读书笔记

作者: 苏柏亚的星空 | 来源:发表于2020-05-14 09:09 被阅读0次
    • 这是一本兼顾深度与广度的通用技术书籍
    • 列出了每节目录,与个人觉得是知识点的地方
    • 以及每章概述

    第1章 计算机基础

    追根究底是深度分析和解决问题、提升程序员素质的关键所在,有助于编写高质
    的代码。基础知识的深度认知决定着知识上层建筑的延展性。试问 对于如下的基
    础知识,你的认知是否足够清晰呢?

    • 位移运算可以快速地实现乘除运算 那位移时要注意什么?
    • 浮点数的存储与计算为什么总会产生微小的误差?
    • 乱码产生的根源是什么?
    • 程序执行时 CPU 是如何与内存配合完成程序使命的?
    • 网络连接资源耗尽的 题本质是 么?
    • 黑客攻击的通常套路是什么?如何有效地防止?

    本章从编程的角度深度探讨计算机组成原理、计算机网络、信息安全等相关内容,与具体编程语言无关。本章将不会讨论内部硬件的工作原理、网络世界的协议和底层传输方式、 全领域的攻防类型等内容。

    1.1 走进0与1的世界

    1.2 浮点数

    1.2.1 科学计数法

    1.2.2 浮点数表示

    1.2.3 加减运算(解释浮点运算的偏差原因)

    1.2.4 浮点数使用

    1.3 字符集与乱码

    • 一个byte 8个bit的原因:有一个bit是校验位
    • GB2312 -> GBK -> GB18030(国家标准)
    • Unicode为每个字符设置了编码
    • UTF是Unicode的实现方式(或者叫压缩格式)分为UTF-8、UTF-16、UTF-32。UTF-8基本思路是越长用越短,会有1-6个字节对Unicode变长编码

    1.4 CPU与内存

    1.5 TCP/IP

    1.5.1 网络协议

    • 网络协议族
    • 分层框架:应用层(HTTP、FTP等)、传输层(TCP、UDP)、网络层(IP)、链路层(IEEE)
    • 报文->路由->端到端->解析

    1.5.2 IP协议

    1.5.3 TCP握手

    需要三次握手的原因:信息对等、防止脏连接


    image.png

    1.5.4 TCP 断开连接

    四次挥手


    image.png

    1.5.5 连接池

    1.6 信息安全

    1.6.1 黑客与安全

    1.6.2 SQL注入

    1.6.3 XSS与CSRF

    1.6.4 CSRF(跨站请求伪造)

    1.6.5 HTTPS

    • 非对称性加密 RSA。核心在于对称加密在需要使用时,密钥的分发危险(不告诉别人,别人就没法加密),但是非对称加密,用于加密的公钥是随便公开的,自己解密的私钥自己保存即可。
    • CA认证中心 HTTPS证书
    • HTTPS通信大概可以分为双方建立加密通信并协定秘钥的过程(这里用非对称),和后续的数据传输过程(这里是对称加密)
    • 非对称加密 性能慢
    • TLS(传输层安全协议)是SSL(安全套接字层)的升级版

    1.7 编程语言的发展

    第2章 面向对象

    本章开始讲解面向对象思想,并以 Java 为载体讲述面向对象思想在具体编程语
    言中的运用与实践。当前主流的编程语言有50种左右,主要分为两大阵营:面向对象编程与面向过程编程。
    面向对象编程( object -Oriented Programming, OOP )是划时代的编程思想变革,推动了高级语言的快速发展和工业化进程。 OOP的抽象、封装、继承、多态的理念使软件大规模化成为可能,有效地降低了软件开发成本、维护成本和复用成本。面向对象编程思想完全不同于传统的面向过程编程思想,使大型软件的开发就像搭积木那样隔离可控、高效简单,是当今编程领域的一股势不可当的潮流。 OOP 实践了软件工程的三个主要目标:可维护性、可重用性和可扩展性。

    2.1 OOP理念

    • 面向过程的结构相对松散 强调如何流程化地解决问题;面向对象的思维更加内聚,强调高内聚、低藕合,先抽象模型,定义共性行为再解决实际问题。
    • 传统意义上 面向对象有三大特性封装、继承、多态。+ 本书强调的抽象

    2.2 初识JAVA

    2.3 类

    2.3.1 类的定义

    2.3.2 接口与抽象类

    • 抽象类是模板式设计,而接口是契约式设计。
    • 抽象类在被继承时体现的是 is -a 关系,接口在被实现时体现的是 can - do 关系。
    • Java 言中类的继承采用单继承形式,避免继承泛滥、菱形继承、循环继承,甚至“四不像”实现类的出现。
    • 当纠结定义接口还是抽象类时,优先推荐定义为接口,遵循接口隔离原则,按某个维度划分成多个接口,然后再用抽象类去 implements 某些接口,这样做可方便后续的扩展和重构。

    2.3.3 内部类

    • 静态内部类,如:static class StaticinnerCass {} ;
    • 成员内部类,如:private class InstancelnnerCass {} ;
    • 局部内部类,定义在方法或者表达式内部;
    • 匿名内部类,如: (new Thread(){} ).start()。

    无论是什么类型的内部类,都会编译成一个独立的class文件
    类加载与外部类在同一个阶段进行。JDK源码中定义包内可见静态内部
    类的方式很常见,这样做的好处是:

    • 作用域不会扩散到包外。
    • 可以通过”外部类 内部类”的方式直接访问。
    • 内部类可以访问外部类中的所有静态属性和方法。

    2.3.4 访问权限控制

    2.3.5 this 与 super

    2.3.6 类关系

    • 继承 extends (is-a)
    • 实现 implements (can do)
    • 组合 类是成员变量(contains-a)
    • 聚合 类是成员变量 (has-a)比组合要松散,例如小狗有腿(组合),有狗绳(聚合)
    • 依赖 import类(use a)

    随着业务和架构的发展,类与类的关系是会发生变化的。

    2.3.7 序列化

    2.4 方法

    2.4.1 方法签名

    2.4.2 参数

    • 形参
    • 实参
    • 可变参数(即 ... )觉得不建议用

    2.4.3 构造方法

    创建类对象时,会先执行父类和子类的静态代码块 然后再执行父类和子类的构造方法。并不是执行完父类的静态代码块和构造方法后,再去执行子类。静态代码块只运行一次,在第二次对象实例化时,不会运行。

    2.4.4 类内方法

    2.4.5 getter setter

    2.4.6 同步与异步

    2.4.7 覆写

    2.5 重载

    JVM在重载方法中,选择合适的目标方法的顺序如下:
    1)精确匹配
    2)如果是基本数据类型,自动转换为更大表示类型的数据类型
    3)自动拆箱与装箱
    4)从子类向上转型类型依次匹配
    5)通过可变参数匹配

    2.6 泛型

    • 泛型的本质是类型参数化,解决不确定具体对象类型的问题。
    • 尖括号里的每个元素都指代一种未知类型(可以是T等,也可以是一个名字)
    • 泛型擦除成Object
    • 泛型与集合的联合使用,可以把泛型的功能发挥到极致。

    2.7 数据类型

    2.7.1 基本数据类型

    • 对象头最小占用空间为12个字节
    • 实例数据
    • 对齐填充

    2.7.2 包装类型

    2.7.3 字符串

    • String是只读的
    • String常量池

    第3章 代码风格

    一致性很重要。
    代码风格并不影响程序运行,没有潜在的故障风险,通常与数据结构、逻辑表达无关,是指不可见字符的展示方式、代码元素的命名方式和代码注释风格等。比如,大括号是否换行、缩进方式、常量与变量的命名方式、注释是否统一放置在代码上方等。代码风格的主要诉求是清爽统一、便于阅读和维护。统一的代码风格可以让开发工程师们没有严重的代码心理壁垒,每个人都可以轻松地阅读并快速理解代码逻辑,便于高效协作,逐步形成团队的代码“味道”。

    3.1 命名规约

    3.1.1 常量

    3.1.2 变量

    3.2 代码展示风格

    3.2.1 缩进、空格与空行

    3.2.2 换行与高度

    3.2.3 控制语句

    3.3 代码注释

    3.3.1 注释三要素

    3.3.2 注释格式

    第4章 走进JVM

    Oracle的HotSpot JVM 实现,是目前最主流的JAVA虚拟机。它采用解释与编译混合执行的模式。本章从字节码说起,分析类加载的过程,并结合内存布局,讲解对象创建与垃圾回收等各个知识点。

    4.1 字节码

    • 是一种中间码
    • JAVA总共有200多个指令
    • 因此叫ByteCode
    • 解释执行 + 编译执行(热点代码直接JIT编译成机器码)

    主要指令类型有

    • 加载或存储指令
    • 运算指令
    • 类型转换指令
    • 对象创建或访问指令
    • 操作栈指令
    • 方法调用与返回指令
    • 同步指令

    4.2 类加载过程

    • ClassLoader类加载过程
    • Load、Link、Init过程
    • Class类 - 可以通过反射把实现和定义解耦,可以获取类的声明,注解,方法等

    类加载器的分层体系

    • 最高层 Bootstrap ClassLoader:负责JAVA的核心类型如 Object System String 等
    • 第二层 Platform/Extension ClassLoader:加载扩展的系统类如加密
    • 第三层 Application ClassLoader:加载用户自定义的CLASSPATH下的类

    其中Bootstrap是c语言实现的,后面是JAVA实现的
    类加载器具有等级制度,但是并无继承关系,以组合的方式来复用父加载器的功能。
    -XX:+TraceClassLoading可以查看加载了哪个jar中哪个类。
    下图说明了类的加载顺序和覆盖机制,即高层优先,低层不能覆盖高层。

    image.png

    用户可以自定义类加载器

    • 隔离加载类,防止冲突
    • 修改类加载方式 :按需动态加载
    • 扩展源代码:如从网络加载
    • 有时候源码加密后,同样需要自定义类加载器还原

    4.3 内存布局

    image.png
    • 堆区:新生代(Eden + S0+ S1)和老年代,在S区停留x次后,移动到老年代
    • 元空间 MetaSpace(前身Permanent区)即以前的永久代。主要存储类的信息
    • 虚拟机栈:执行方法的内存区,线程私有
    • 本地方法栈(native方法):本地方法调用的栈数据,也是线程私有的
    image.png

    4.4 对象实例化

    4.5 垃圾回收

    • 与GC Roots失去引用(GC Roots指常量、静态对象、方法栈中的对象)
    • 标记-清除是GC的基础
    • 引入Mark-Copy解决碎片问题

    主要GC算法:

    • Serial 常用与YGC 单线程串行,stop the world
    • CMS(初始标记、并发标记、重新标记、并发清除)共4个步骤。其中1和3 STW
    • G1 将对划分为Regoin,优先回收垃圾较多的区域,对停顿时间更可控

    第5章 异常与日志

    捕获异常时需要分清稳定代码和非稳定代码。
    如果异常在当前方法的处理能力范围之内且没有必要对外透出,那么就直接
    捕获异常并做相应处理;否则向上抛出,由上层方法或者框架来处理。

    5.1 异常分类

    • 所有异常都是 Throwable 的子类
    • 分为Error(致命异常)和Exception(非致命异常)

    5.2 try 代码块

    • finally 是在 return 表达式运行后执行的。因此finally里面的计算可能是无用的。
    • 不要在finally中使用return,会使返回值判断变得复杂

    5.3 异常的抛与接

    5.4 日志

    5.4.1 日志规范

    5.4.2 日志框架

    image.png
    • 日志门面:它只提供一套接口规范如slf4j,自身不负责日志功能的实现
    • 日志库:主流的日志库有三个 分别是 log4j,log-jdk,logback(log4j的升级版)
    • 曰志适配器:包括日志门面适配器如(slf4j-log4j12)和日志库适配器

    第6章 数据结构与集合

    本书中其他地方出现的集合概念,都指的是 Collection来保存各种各样的对象。非是数学意义上的Set(互异)。在进入高并发编程时代后,由集合引发的相关故障占比越来越高。比如,多线程共享集合时出现的脏数据问题,某些集合在数据扩容时出现节点之间的死链问题;写多读少的场景误用某些集合导致性能下降问题等。本章将从数组讲起,引申到集合框架,再到重点集合源码分析,最后介绍高并发集合框架,目的是对集合的了解成竹在胸、运用得心应手。

    6.1 数据结构

    • 数据结构定义:数据结构是指逻辑意义上的数据组织方式及其相应的处理方式。
    • 数据结构分类:线性、树、图、哈希

    6.2 集合框架图

    • 框架图中主要分为两类。第一类是按照单个元素存储的 Collection,第二类是KV结构的Map
    • Collection接口主要有Set、List、Queue三大类子实现
    • Map主要有HashMap、TreeMap、SortedMap等
    image.png

    6.2.1 List 集合

    • 最常用的是 ArrayList和LinkedList 两个集合类
    • LinkedList 的优点在于可以将零散的内存单元通过附加引用的方式关联起来。内存利用率较高

    6.2.2 Queue 集合

    • 队列是一种特殊的线性表,它只允许在表的一端进行获取操作,在表的另一端进行插入操作
    • 经常被作为Buffer (数据缓冲区)使用

    6.2.3 Map 集合

    • Map 类提供三种 Collection 视图
    • KeySet、ValueSet、EntrySet
    • 最早用于存储键值对的 Hashtable 因为性能瓶颈已经被淘汰
    • HashMa 线程是不安全的,ConcurrentHashMap 是线程安全的
    • TreeMap是Key有序的Map类集合,有headMap、lower/higher key等特别的操作接口

    6.2.4 Set 集合

    • Set 体系最常用的是 HashSet、TreeSet、LinkedHashSet三个集合类
    • HashSet 从源码分析是使 HashMap 来实现的(Valu 固定为一个静态对象)
    • LinkedHashSet维护了插入元素的顺序

    6.3 集合初始化

    • 合理初始大小可以避免被动扩容和数组复制的额外开销
    • HashMap扩容还会重建哈希表,非常影响性能
    • 默认值大小ArrayList 为10,HashMap 默认为16

    6.4 数组与集合

    • 数组是固定容量大小的
    • 对于动态大小的数组,集合提供了 Vector和ArrayList两个类,前者是线程安全,性能较差,基本弃用
    • Arrays 是针对数组对象进行操作的工具类,包括数组的排序、查找、对比、拷贝等操作。通过这个工具类也可以把数组转成集合
    • Arrays asList 体现的是适配器模式,后台的数据仍是原有数组。并不是通用意义上的ArrayList,是一个内部类实现。。
    • 使用集合toArray(T[] array )方法,转换为数组时注意需要传人类型完全一样的数组,并且它的容量为list.size,这样效率是最高的

    6.5 集合与泛型

    • (略,知识点多又不太常用。。)

    6.6 元素的比较

    6.6.1 Comparable和Comparator

    • Comparable是表示自身有比较的能力,比较方法是compareTo
    • Comparator是第三方实现的比较,比较方法是compare

    6.6.2 hashCode和equals

    • 注意任何时候覆写equals 都必须同时覆写 hashCode

    6. 7 fail-fast 机制

    • 遍历过程对集合的操作可能导致异常
    • CopyOnWriteArrayList可以优化读多写少的场景

    6.8 Map 类集合

    image.png

    6.8.1 红黑树

    • 树的结构
    • 二叉树是经典的二分法实现
    • 二叉树:平衡二叉树、查找二叉树、红黑树(TODO 一些重点数据结构,需要展开理解)

    6.8.2 TreeMap

    6.8.3 HashMap

    • 并发写的死链问题(CPU大量占用)

    6.8.4 ConcurrentHashMap

    • 是学习并发编程的一个绝佳示例,此类超过 6300 行代码,涉及volatile、CAS 锁、链表、红黑树等众多知识点
    • 原理与算法 (TODO 也需要展开。。)

    第7章 并发与多线程

    并发与并行两个概念非常容易混淆,它们的核心区别在于进程是否同时执行。以 KTV 唱歌为例,并行指的是有多少人可以使用话筒同时唱歌,并发指的是同一个话筒被多个人轮流使用。

    7.1 线程安全

    • 线程可以拥有自己的操作栈、程序计数器、局部变量表等资源
    • 线程安全的核心理念就是“要么只读,要么加锁”
    • Java 并发包( java.util.concurrent)JUC核心功能
      • 线程同步类:CountDownLatch等。替换notify、wait等
      • 并发集合类:ConcurrentHashMap等
      • 线程管理类:Executors工厂类等
      • 锁相关类:ReentrantLock等

    7.2 什么是锁

    • 计算机的锁也是从开始的悲观锁,发展到后来的乐观锁、偏向锁(降低无竞争开销)、分段锁等
    • 锁主要提供两种特性:互斥性和不可见性

    7.3 线程同步

    7.3.1 同步是什么

    • 原子性:不可分割,要么全部成功,要么全部失败
    • 实现线程同步的方式有很多,比如同步方法、锁、阻塞队列等

    7.3.2 volatile

    • 指令优化,指令重排
    • volatile延伸为敏感的易变的,局部阻止了指令重排的发生
    • 双重锁问题(double-check):对象创建和引用赋值不是原子的(JVM的实现或者JIT的编译可能让代码不是按预期顺序执行)

    7.3.3 信号量同步

    7.4 线程池

    7.4.1 线程池的好处

    ThreadPoolExecutor 的构造方法:

     public ThreadPoolExecutor(int corePoolSize, 常驻核心线程数
                                  int maximumPoolSize, 同时执行的最大线程数
                                  long keepAliveTime, 线程池中的线程空闲时间 
                                  TimeUnit unit, 时间单位
                                  BlockingQueue<Runnable> workQueue, 缓存队列
                                  ThreadFactory threadFactory, 线程工厂
                                  RejectedExecutionHandler handler 执行拒绝策略的对象
    )
    

    7.4.2 线程池源码详解

    7.5 ThreadLocal

    7.5.1引用类型

    7.5.2 Threadlocal 价值

    7.5.3 ThreadLocal 副作用

    • 脏数据(原因是线程会被重用,其附带的ThreadLocal也会留存)
    • 内存泄露(没有remove)

    第8章 单元测试

    8.1 单元测试的基本原则

    8.2 单元测试覆盖率

    8.3 单元测试编写

    8.3.1 JUnit 单元测试框架

    8.3.2 命名

    8.3.3 断言与假设

    第9章 代码规约

    9.1 代码规约的意义

    9.2 如何推动落地

    9.3 手册纵览

    9.4 聊聊成长

    相关文章

      网友评论

          本文标题:【工作】《码出高效》读书笔记

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