疯狂java讲义ed3 读书笔记

百度脑图: http://naotu.baidu.com/file/c07a7be593acee73e72451ad1d393f5d?token=ce49cc74688fd5fd
虽然 java 基础看了不下 3 遍了,可是不怎么用 java 写代码

花了几天粗略的看了一下, 算是大致知道语法了, 至少写写 hello world 或者看代码没有压力啦.

高级语言: 汇编之上的语言, c / c++ / java ..
编译型(静态) / 解释型(动态)
jvm统一标准: 指令集 / 寄存器 / 类文件的格式 / 栈 / 垃圾回收堆 / 存储区
jre: jvm + 类加载器 / 字节码校验 / 基础类库
path: jdk/bin/

垃圾回收机制

  1. c/c++ 需要程序员自己负责已经分配的内存, 不及时回收会引起系统运行速度下降, 甚至系统瘫痪(内存泄漏)
  2. 只能回收内存资源(无用对象的内存空间), 不能回收物理资源(db连接, 磁盘I/O)
  3. 发生不可预知: 定时 / cpu 空闲 / 内存消耗过多
  4. 精确性: 精确标记活着的对象 / 精确定位对象之间的引用关系
  5. jvm 有多种垃圾回收实现

结构化程序设计: 设计不够直观, 与人类习惯思维不一样 / 适应性差, 可扩展性不强 / 强调实现某个功能的算法
任何算法都由 顺序结构 / 选择结构 / 循环结构 组合而成
面向对象程序设计: 类 / 对象 / 继承 / 封装 / 消息 等基本概念进行程序设计
类 = 成员变量(状态数据) + 方法(行为)
面向对象: 封装 / 继承 / 多态
UML(统一建模语言): OOA(分析) -> OOD(设计) -> OOP(编程); 用例图 / 类图(关联/泛华/依赖) / 部署图 / 顺序图(时序图) / 活动图 / 状态图

注释: 永远不要相信自己的理解能力 / 可读性第一, 效率第二 / 代码即文档
编程的本质, 就是对内存中数据的访问和修改

语法参考

java基本数据类型:

http://qiniu.daydaygo.top/java/basic-datatype.png
申明 long 类型: long num = 99999999999L;
二进制 / 八进制 / 十进制 / 十六进制
字符型: java 字符串使用 unicode 编码, char 使用单引号, string 使用双引号
计算机只能保存二进制, 字符集是用数字来表示字符, 如 ASCLL 中 65 -> A, 存储时存储64即可
浮点型: 需要精确表示一个浮点数, 可以考虑 BigDecimal 类 / 十进制 + 科学计数法 / 正无穷大 + 负无穷大 + 非数
数字使用下划线分隔: ob0000_0000_0000
大部分计算机允许分配的最小内存单位是字节, 所以 boolean 实际上占用 1 byte
自动类型转换: 小范围 -> 大范围
强制类型转换: 要小心 大范围 -> 小范围 的溢出问题
string 是一个典型的不可变类
常量池(constant pool): 类 / 方法 / 接口 中的常量, 字符串直接量
移位操作: 不会改变原数, 而是新生成数 / 相当于乘2或除2
你知道这条航线上的所有暗礁么? --不, 我只知道那条是深水航线
return 0;: 对的路只有一条, 错误的路有千万条
数组: 数据类型固定 / 长度固定 / 静态初始化 + 动态初始化 / foreach / 数组引用(比如指向对象) / 没有多维数组(其实就是用数组引用实现) / Arrays / 多核cpu支持
栈内存: 方法运行时, 使用的局部变量都保存在 栈内存 中, 当方法运行结束时, 清空 栈内存
堆内存: 程序运行时, 会有一个数据区用来保存运行所需的数据, 这个就是堆内存, 比如运行时创建的对象(创建对象通常开销都很大), 当一个对象没有任何应用变量引用它时, GC就会在适当的时候回收它

面向对象

Person p = new Person(): p为对象的引用变量, 存放在栈内存中, 对象为类的实例, 属性是需要使用内存存储的, 存放在对内存中
Person p2 = p: 对象可以有多个引用
this: 对象引用自身, 本质其实是类自身 属性/方法 间的依赖; 返回 this 可以 链式调用; 还可以代码复用哦
static: 本质上定义的属于类本身而非类实例(对象)的 属性/方法, 所以尽量分开2者的用法
变量: 类变量 / 实例变量 / 方法局部变量 / 代码块局部变量; setter / getter
方法的参数传递机制: 实际上是传递一个副本
形参个数可变: 被当作数组传入
递归: 方法调用自身 / 一定要向已知方向 / 比如遍历目录
方法重载: 同名 / 形参数量不同
包: 可以查考 php 命名空间来理解, 包名匹配路径名, 类名匹配文件名; package + import / import static(可以用来导入静态常量)

  • java常用包

-封装
private / default / protected / public 访问控制; 隐藏成员变量和实现细节, 暴露方法; 本质是对客观世界的模拟

  • 构造器
    与类同名; 必须含有构造器; java自动生成, 结构体为空; 为变量设置默认值
    对象在构造器执行前就产生了: 程序调用构造器 -> 系统为对象分配内存 -> 执行对象默认初始化 -> 执行构造器
    通常为 public, 可以通过访问控制来实现来限制创建该类的对象
    从 父类 -> 子类 的顺序执行构造器
    初始化块: 特殊的成员变量 / 在构造器之前执行

  • 继承
    extends, 继承实现了复用, 子类改变父类的变量形成多态, 单继承
    override: 重写(方法覆盖) | super: 使用父类被 override 的方法
    需要子类: 增加额外属性 / 增加独有行为方法
    instanceof: 判断继承关系; obj.getClass() == Person.Class(), 判断是否为同一个类
    继承会破坏封装

  • 多态
    BaseClass cTest = new SubClass(): 编译时为 BaseClass, 运行时为 SubClass
    强制类型转换: 基本类型 -> 数值类型; 引用类型 -> 继承关系

  • 组合
    将父类作为子类的属性, 从而避免使用继承
    is-a 与 has-a 的关系来区分使用 继承 还是 组合

  • 基本数据类型与包装类
    AutoBoxing <-> AutoUnboxing
    字符串 -> 基本数据类型: parseXxx(str) 或者 new Xxx(str)
    基本数据类型 -> 字符串: String.valueOf(num)
    Integer: 当数字在 -128~127时, java 会启用缓存机制 cache[i] = num
    toString(): 将类当字符串使用; 默认为 "类名 + @ + hashCode"; 重写来实现类的自我描述
    equals(): 和 == 比较; 重写来实现比较规则

singleton(单例)类: 单例模式
final: 成员变量必须现实指定初始值; 局部变量防止变量被重复赋值; 宏变量; 方法不可被 override; 不可有子类
缓存实例的不可变类: 简单使用 数组实现缓存(涉及到 查找 队列)

抽象类: 抽象方法; 有得有失 ->多了一个能力, 无法创建实例; 模板模式
接口: 契约精神; 成员变量自动为 public static; 规范和实现分离的设计哲学; 简单工厂模式; 命令模式
内部类: 更好的封装, 可以类似 闭包/匿名函数 来理解
lambda表达式: 缩写, 感觉很赞
枚举类

  • 对象与垃圾回收
    只负责内存中的对象, 不负责回收任何物理资源(db连接, 网络io 等)
    无法精确控制; 对象永久性失去应用 -> 系统在合适的时候回收
    回收之前调用finalize(), 此方法可以让对象 '复活', 取消回收
    引用: 创建之后 -> 可达状态 -> 可回复状态 -> 不可达状态 -> 垃圾回收
    强制垃圾回收: System.gc() + Runtime.getRuntime().gc()
    引用类型: 强引用(对象赋值); 软引用(内存足够时不会被回收, 常用于对内存敏感的程序); 弱引用(垃圾回收就会被清楚); 虚引用(必须和引用队列联合使用, 用于跟踪被垃圾回收的状态)

最好是经历过某种痛苦, 或者正在经历一种痛苦, 就会对设计模式有较深的感受

java 基础类库

工具类通常使用 s 作为后缀

  1. 运行java程序的参数: args
  2. Scanner: 获取键盘输入; 读取文件
  3. java 无法访问操作系统底层硬件设备, 需要借助C语言实现: java 申明 native 方法 -> 编译生成 .class 文件 -> javah 编译 .class 文件生成 .h 文件 -> 写一个 .cpp 方法实现 native 方法, 包含之前的 .h 文件 -> 将 .cpp 编译成动态链接库文件 -> 在java中调用生成的动态链接库文件
  4. 系统相关: System类代表当前java的运行平台; Runtime类代表java运行时环境
  5. Object 类: 所有 类/数组/枚举类 的父类; equals() / finalize() / getClass() / hashCode() / toString() / 控制线程 / clone(): 浅克隆, 不对引用类型成员变量进行克隆
  6. Objects 工具类: requireNotNull(obj), 用来对形参进行输入校验
  7. String(不可变类) / StringBuffer(字符序列可变, 线程安全) / StringBuilder(非线程安全, 性能略高)
  8. Math 类
  9. Random / ThreadLocalRandom / Math.random()
  10. BigDecimal(string val): java 在计算 float / double 时容易发生精度丢失(通病)
  11. 日期时间: Date(尽量不要使用) / Calendar(日期时间加减运算, 获取 年月日时分秒信息) / java.time.* / DateFormat / SimpleDateFormat / DateTimeFormatter
  12. 正则表达式: String / Pattern(不可变类, 可供多个并发线程安全使用 / Matcher
  13. 国际化&多语言: 属性资源文件 / 使用类替代 / Format 相关类

集合(Collection / Map)

hash: hash算法存在的意义就是快, 可以通过hash值快速定位数据存储在内存中的位置, 从而快速找到数据
所有内部基于数组的集合实现(如 ArrayList, ArrayDeque) 随机访问要比 Iterator 迭代访问性能要好
使用: 排序; 查找/替换; 同步控制 synchronizedXxx(), 包装成线程安全; 设置不可变集合

Set: 无序, 不可重复; 基本都是使用 HashSet / LinkedHashSet(使用链表维护元素次序, 遍历全部元素时将有很好的性能) / TreeSet(只能添加同一种类型的对象, 默认升序, 可以定制 Compare 实现降序) / EnumSet(以位向量形式存储) / HashSet + TreeSet + EnumSet 都是线程不安全的, 需要使用 Collections 的 syncchronizedSortedSet 来包装
List: 有序重复; ArrayList(线程不安全) / Vector(线程安全) -> Stack / ArrayDeque / LinkedList
Queue: PriorityQueue(优先级队列, 玩过算法应该都知道) / Deque(双端队列) / ArrayDeque
Map: 映射; java源码使用 value 全为 null 的 Map 实现 List; Hashtable(线程安全) / HashMap(线程不安全) / LinkedHashMap(双向链表维护) / Properties(用来读写属性文件, 包括 ini 文件) / SortedMap / TreeMap / WeakHashMap(弱引用) / IdentityHashMap(要求严格相等) / EnumMap

http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-8.1.png
http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-8.2.png
http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-8.3.png
Iterator: 迭代器, 用来遍历集合元素
Stream: 通用流接口, 支持串行和并行聚集操作

  • 别告诉我你知道 Hash
    对于 HashSet 及其子类而言, 它们采用 hash 算法来决定集合中的元素的存储位置, 并通过 hash 算法来h控制集合的大小; 对于 Hashtable / HashMap 及其子类, 使用 hash 算法决定其 key
    属性: capacity(容量) / initial capacity / size(当前记录的数量) / load factor(负载) = 'size/capacity', 轻负载的 hash 表具有冲突少, 适宜插入, 但是 iterator 迭代比较慢

http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-8.8.png

泛型 Generic

集合允许放置任何 Object 类型, 泛型就是为了防止类型滥用, 在使用前确定类型
可以为 任何类/接口 添加泛型声明
并不存在泛型类: 不会重新生成类, 不会改变类之间的关系, 而是限定类使用参数的数据类型

异常处理

传统的处理方式: 先使用 if 判断程序运行状态, 如果都正常, 再进入业务逻辑, 而 try{}catch{} 结构则是先业务逻辑, 然后根据现实再添加额外 catch
try -> 出现异常 -> throw, 抛出异常 -> java runtime 接收异常 -> 寻找处理该异常对象的 catch 块 -> catch 块处理, 即为 捕获异常, 如果无法捕获, runtime 终止, 程序直接退出

http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-10.2.png
捕获异常: 先小后大; 同时捕获多个异常
tyr: 自动关闭资源写法
finally: 垃圾回收只回收内存, 物理资源需要显式回收, 而将资源回收放在 try / catch 中都无法确定资源能被回收 / 除非调用了退出虚拟机的方法(System.exit(1)), 一定会被执行
Checked 异常: 没有完善错误处理的代码根本就不会被执行
catch-throw: 企业级应用经常使用, 后台记录异常的日志信息, 前台返回自定义提示信息给用户; 向用户隐藏原始异常信息
异常处理规则: 最小化代码混乱 / 捕获并保留诊断信息 / 通知合适的人员 / 采用合适的方式结束异常活动 / 不用使用异常来代替正常的业务逻辑判断

AWT && Swing

mysql 与 JDBC 编程

JDBC: 跨数据库

Annotation 注解

IO

random: 除了随机以外, 还有任意的意思, 所以 RAM (内存, random access memory) 可以理解了

File: 操作文件和目录
IO stream: 从 source 到 sink 的有序数据; 相对于 内存来确定输入输出
输入: InputStream / Reader
输出: OutStream / Writer
java IO 模型的优势: 使用 缓冲 提高效率; 操作便捷
如果不关闭输出流(close() 执行前会自动调用 flush()), 可能会导致缓冲区的内容没有 flush() 到输出源

http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-15.1.png
字节流 / 字符流: 如果使用 二进制数据, 使用 字节流; 字符流比字节流操作简单, 所以 java 提供了 字节流 -> 字符流 的方法
重定向
读写其他进程的数据: java 使用 runtime / exec() 可以执行其他程序, Process 类代表这些 子进程
RandomAccessFile: java io体系中功能最丰富的文件内容访问类; 只能读写文件
多线程网络下载工具(FlashGet)实现原来: 可以使用 RandomAccessFile 类来实现, 下载开始前创建2个文件, 一个和下载文件相同大小的空文件, 一个记录文件指针位置的文件
序列化: Serialize; 对象引用的序列化; 通过序列化算法获取对象的序列化编号; 第一次使用 writeObject() 获取序列化编号后就不会再次计算

  • nio
    Channel + Buffer(capacity / limit / position), 映射文件或文件的一段区域到内存中
    Charset
    fileLock: 高并发下还是推荐使用db来保存程序信息
    Files / Paths / FileVistor / WatchService(监控文件变化)

多线程

线程在多cpu下自动并行

一个任务(程序)通常就是一个进程, 进程运行时, 内部可能包含多个顺序执行流, 每个顺序执行流就是一个线程
进程(Process): 当一个程序运行进入内存后, 就变成了一个进程; 独立性(独立实体, 独立资源, 独立地址空间) + 动态性(生命周期, 各种不同形态) + 并发性(单个cpu上可以执行多个进程, 互相不会影响)
并行(parallel): 同一时刻多条指令在多个处理器上同时执行
并发(concurrency): 同一个时刻只有一条指令执行, 但是多个进程指令在短时间内快速轮换执行, 使得宏观上具有多个进程同时执行的效果
线程(Thread): 进程的组成部分, 拥有自己的 堆栈/计数器/局部变量, 但是不拥有系统资源, 和父进程的其他进程共享该进程的全部资源
多线程优势: 共享内存 / 文件句柄 / 其他进程应有的状态; 线程很容易实现相互之间通信; 创建线程代价比进程小得多, 因此实现高并发比多进程效率高
Thread / Runnable(定 target, 给线程起名) / Callable -> call()
线程生命周期: new -> runnable -> running -> blocked -> dead
直接调用 Thread 的 run() 而不是 start() 会导致子进程抢占主线程

http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-16.4.png
join(): 必须等待另一个线程完成
setDaemon(true): 设置 守护线程
sleep() / yield() -> 相同或者更高优先级的进程才可以执行 / setPriority()
线程安全: 线程切换具有不确定性, 也许进程在程序体还没有完全执行就切换到了其他线程, 导致出现线程安全问题 / 使用 syncchronized 添加同步锁
线程安全解决思路: 监控资源, 使用时添加锁
DDD(domain driven design): 领域驱动设计
同步锁 / 死锁
线程通信: 传统方式 -> wait() + notify() + notifyAll(); condition -> await() + signal() + signalAll(); BlockingQueue
线程组
线程池 / ForkJoinPool -> 任务拆分充分利用多cpu

网络编程

计算机网络: 资源共享; 信息传输+集中处理; 均衡符合+分布处理; 综合信息服务

http://7xq89b.com1.z0.glb.clouddn.com/crazy-java3-17.2.png
ip被分为 A(10) B(172) C(192) D E
ip(32位)来确认网络上的通信实体, 端口来确认提供服务的应用程序
端口(16位): 一个端口只能一个程序使用; 公认端口(<1024, 绑定特定服务) + 注册端口(<49152, 应用程序通常应该绑定在这个范围内) + 动态/私有(不建议使用这个范围内的端口)
InetAddress: 处理 IP 地址
URLDecoder / URLEncoder / URL / URLPermission
TCP/IP -> Socket -> 加入多线程 -> 记录用户信息(Map) -> 半关闭Socket(适用于Http场景) -> NIO -> AIO(NIO2.0)
UDP -> DatagramPacket(定点) -> MulticastSocket(广播)
代理服务器: Proxy / ProxySelector

类加载机制与反射

所有程序都运行在 JVM 中
类的加载: 系统需要将类的 .class 文件加入到内存; 允许预先加载; 对象是类的实例, 其实系统要使用类, 也是需要 实例化 类的, 系统为之生成一个对应的 Class 对象
类加载 -> 系统为之实例化一个对应的 Class 对象 -> 连接阶段(验证 + 准备 + 解析) -> 初始化(类变量 + 静态初始化块)
类初始化的时机
类加载机制: 全盘负责 + 父类委托 + 缓存机制

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

推荐阅读更多精彩内容