
马俊昌
写一本关于编程的书,是我大概15年前就有的一个想法,当时,我体会到了编程中数据结构的美妙和神奇,有一种收获的喜悦和分享的冲动。这种收获是我反复阅读教程十几遍,花大量时间上机练习调试得到的,这是一个比较痛苦的过程。我想,如果把我学到的知识更为清晰易懂地表达出来,其他人不就可以掌握编程容易一些,并体会到那种喜悦了吗?不过,当时感觉自己学识太浅,要学习的东西太多,想一想也就算了。
看这本书是因为想在校招入职之前好好学下 Java,粗略过了一遍后发现 ROI 实在是太低,大部分内容其实和 Go 差不多,但 Java 独特的部分讲的却一般,需要自己下来重新找别的资料学习。但也花了好几个小时看完,还是整理下。 ## 编程基础与二进制 - switch 语句在分支较多时会使用跳表,类似二分,时间复杂度更低。 - 三个点作为可变长度参数,类似 Go 中的语法糖。 - 计算机系统主要使用栈来存放函数调用过程中需要的数据,包括参数、返回地址,以及函数内定义的局部变量。 ## 面向对象 - 栈存放函数的局部变量,而堆存放动态分配的对象,还有一个内存区,存放类的信息,这个区在 Java 中称为方法区。 - 使用默认方法就可以在超多实现类的情况下给接口新增方法。 - 受检异常和未受检异常区别就是 Java 的对待方式,受检异常必须进行处理。同时父类是 RuntimeException 则是未受检异常,父类是 Exception 是受检异常。 - try 或 catch 中的 return 语句会在 finally 执行结束后才执行,同时 finally 中并不能修改返回值。避免在 finally 中使用 return 或抛出异常。 - hashCode 和 equals 方法联系密切,对两个对象,如果 equals 方法返回 true,则 hashCode 也必须一样。反之不要求 。 - String 类中提供了很多看似修改的方法,其实是通过创建新的 String 对象来实现的,原来的 String 对象不会被修改。 ## 泛型与容器 - Java 泛型底层就是 Object 强转。 - 泛型就是类型参数化,处理的数据类型不是固定的,而是可以作为参数传入。 - 通配符形式能做的类型参数形式都可以做,只是更简单,可读性更好。 - 在迭代过程中若想进行结构性变化则使用迭代器提供的方法,每次发生结构性变化的时候 modCount 都会增加,而每次迭代器操作的时候都会检查 expectedModCount 是否与 modCount 相同,这样就能检测出结构性变化。 - Java 8 对 HashMap 的实现进行了优化,在哈希冲突比较严重的情况下,即大量元素映射到同一个链表的情况下(具体是至少 8 个元素,且总的键值对个数至少是 64),Java 8 会将该链表转换为一个平衡的排序二叉树 (红黑树)。 - HashSet 内部就是一个 HashMap。 - TreeMap 使用红黑树实现,实现了去重和有序。 - 一个配置文件有一些键值对形式的配置项,但其中有一些键是重复的,希望保留最后一个值,但还是按原来的键顺序输出, LinkedHashMap 就是一个合适的数据结构。它可以保持插入顺序或访问顺序。 ## 文件 - 一般读写文件需要两次数据复制,比如读文件,需要先从硬盘复制到操作系统内核,再从内核复制到应用程序分配的内存中。操作系统运行所在的环境和应用程序是不一样的,操作系统所在的环境是内核态,应用程序是用户态,应用程序调用操作系统的功能,需要两次环境的切换,先从用户态切到内核态,再从内核态切到用户态。这种用户态/内核态的切换是有开销的,应尽量减少这种切换。 ## 并发 - 在 Java 中创建线程有两种方式:一种是继承 Thread;另外一种是实现 Runnable 接口。 - synchronized 实例方法实际保护的是同一个对象的方法调用,确保同时只能有一个线程执行 - 若只是保证内存可见性可以使用 volatile,更轻量级。 - ABA 是不是一个问题与程序的逻辑有关,一般不是问题。而如果确实有问题,解决方法是使用 AtomicStampedReference,在修改值的同时附加一个时间戳,只有值和时间戳都相同才进行修改。 - 关于 ThreadLocal,简单总结来说:1)ThreadLocal 使得每个线程对同一个变量有自己的独立副本,是实现线程安全、减少竞争的一种方案。2)ThreadLocal 经常用于存储上下文信息,避免在不同代码间来回传递,简化代码。3)每个线程都有一个 Map,调用 ThreadLocal 对象的 get/set 实际就是以 ThreadLocal 对象为键读写当前线程的该 Map。 - ConcurrentHashMap 采用分段锁技术,将数据分为多个段,而每个段有一个独立的锁,每一个段相当于一个独立的哈希表,分段的依据也是哈希值,无论是保存键值对还是根据键查找,都先根据键的哈希值映射到段,再在段对应的哈希表上进行操作。采用分段锁,可以大大提高并发度,多个段之间可以并行读写。看这本书是因为想在校招入职之前好好学下 Java,粗略过了一遍后发现 ROI 实在是太低,大部分内容其实和 Go 差不多,但 Java 独特的部分讲的却一般,需要自己下来重新找别的资料学习。但也花了好几个小时看完,还是整理下。 ## 编程基础与二进制 - switch 语句在分支较多时会使用跳表,类似二分,时间复杂度更低。 - 三个点作为可变长度参数,类似 Go 中的语法糖。 - 计算机系统主要使用栈来存放函数调用过程中需要的数据,包括参数、返回地址,以及函数内定义的局部变量。 ## 面向对象 - 栈存放函数的局部变量,而堆存放动态分配的对象,还有一个内存区,存放类的信息,这个区在 Java 中称为方法区。 - 使用默认方法就可以在超多实现类的情况下给接口新增方法。 - 受检异常和未受检异常区别就是 Java 的对待方式,受检异常必须进行处理。同时父类是 RuntimeException 则是未受检异常,父类是 Exception 是受检异常。 - try 或 catch 中的 return 语句会在 finally 执行结束后才执行,同时 finally 中并不能修改返回值。避免在 finally 中使用 return 或抛出异常。 - hashCode 和 equals 方法联系密切,对两个对象,如果 equals 方法返回 true,则 hashCode 也必须一样。反之不要求 。 - String 类中提供了很多看似修改的方法,其实是通过创建新的 String 对象来实现的,原来的 String 对象不会被修改。 ## 泛型与容器 - Java 泛型底层就是 Object 强转。 - 泛型就是类型参数化,处理的数据类型不是固定的,而是可以作为参数传入。 - 通配符形式能做的类型参数形式都可以做,只是更简单,可读性更好。 - 在迭代过程中若想进行结构性变化则使用迭代器提供的方法,每次发生结构性变化的时候 modCount 都会增加,而每次迭代器操作的时候都会检查 expectedModCount 是否与 modCount 相同,这样就能检测出结构性变化。 - Java 8 对 HashMap 的实现进行了优化,在哈希冲突比较严重的情况下,即大量元素映射到同一个链表的情况下(具体是至少 8 个元素,且总的键值对个数至少是 64),Java 8 会将该链表转换为一个平衡的排序二叉树 (红黑树)。 - HashSet 内部就是一个 HashMap。 - TreeMap 使用红黑树实现,实现了去重和有序。 - 一个配置文件有一些键值对形式的配置项,但其中有一些键是重复的,希望保留最后一个值,但还是按原来的键顺序输出, LinkedHashMap 就是一个合适的数据结构。它可以保持插入顺序或访问顺序。 ## 文件 - 一般读写文件需要两次数据复制,比如读文件,需要先从硬盘复制到操作系统内核,再从内核复制到应用程序分配的内存中。操作系统运行所在的环境和应用程序是不一样的,操作系统所在的环境是内核态,应用程序是用户态,应用程序调用操作系统的功能,需要两次环境的切换,先从用户态切到内核态,再从内核态切到用户态。这种用户态/内核态的切换是有开销的,应尽量减少这种切换。 ## 并发 - 在 Java 中创建线程有两种方式:一种是继承 Thread;另外一种是实现 Runnable 接口。 - synchronized 实例方法实际保护的是同一个对象的方法调用,确保同时只能有一个线程执行 - 若只是保证内存可见性可以使用 volatile,更轻量级。 - ABA 是不是一个问题与程序的逻辑有关,一般不是问题。而如果确实有问题,解决方法是使用 AtomicStampedReference,在修改值的同时附加一个时间戳,只有值和时间戳都相同才进行修改。 - 关于 ThreadLocal,简单总结来说:1)ThreadLocal 使得每个线程对同一个变量有自己的独立副本,是实现线程安全、减少竞争的一种方案。2)ThreadLocal 经常用于存储上下文信息,避免在不同代码间来回传递,简化代码。3)每个线程都有一个 Map,调用 ThreadLocal 对象的 get/set 实际就是以 ThreadLocal 对象为键读写当前线程的该 Map。 - ConcurrentHashMap 采用分段锁技术,将数据分为多个段,而每个段有一个独立的锁,每一个段相当于一个独立的哈希表,分段的依据也是哈希值,无论是保存键值对还是根据键查找,都先根据键的哈希值映射到段,再在段对应的哈希表上进行操作。采用分段锁,可以大大提高并发度,多个段之间可以并行读写。
阅读速度5000字/分钟 1、本书主题:Java教学 2、速读建议:工具书内容大同小异,会有很多重复性知识。已知的部分快速略过,未知的先做个标记。 >> 可汗学院的创始人是萨尔曼·可汗,他自己录制了3000多个短视频,主要教中小学生基础课。他为每门课程建立了知识地图,地图由知识点组成,知识点之间有依赖关系。每个知识点都有一个视频,每个视频10分钟左右,他的讲解清晰透彻,极受欢迎。 >> 变量就是给数据起名字,方便找不同的数据,它的值可以变,但含义不应变。 >> 抽象是相对于具体而言的,一般而言,具体类有直接对应的对象,而抽象类没有,它表达的是抽象概念,一般是具体类的比较上层的父类。比如,狗是具体对象,而动物则是抽象概念;樱桃是具体对象,而水果则是抽象概念;正方形是具体对象,而图形则是抽象概念。 >> 多维数组只是一个假象,只有一维数组,只是数组中的每个元素还可以是一个数组,这样就形成二维数组;如果其中每个元素还都是一个数组,那就是三维数组。
很好的一本书。适合刚工作1-3年的java工程师阅读 本科就是计算机专业的我,学java其实也有10年了,但是可以说是从入职现在的公司以来,才真正把自己当做一个java工程师。两年来,虽然也参与了不少项目,甚至有些项目是自己一个人写的。但写的大多数都是些业务逻辑,即使如此,也写的并不优雅整洁。什么设计模式,反射,泛型等几乎没怎么用过。所以其实对于自己的java是很不自信的。 通过这本书,算是查漏补缺一下,很多地方看的有点心急(也和手机端不方便阅读大段代码有关),流于蜻蜓点水了。但是即便如此,还是感觉收获了很多。比如: 对继承,接口的理解。字符集的分类与原理。反射,依赖注入容器,lambda表达式的运用等等。
这是一本讲java细节不错的书
这本书对于java的知识点介绍比较详细,特别适合工作了一段时间或者换工作的同学,查漏补缺、温故知新,对于初学者来说有点难度。关于容器那些章节介绍的尤为详细,结合数据结构与算法、夹杂一点设计模式,个人感觉尤为精彩。
Java这门语言之所以能够快速发展,与其丰富的类库和工具、开发效率、代码可读性、安全性、稳健性、可移植性、多线程处理能力有很大关系,选择了Java,就不必像C/C++那样经常要重复造轮子,很多框架可供选择,能够实现大部分功能,而且这些代码在不断优化。《Java编程的逻辑》这本书,不仅仅涉及到Java基础的部分,还有更加深入的内容。程序就是数据结构+算法,书中对Java的数据结构和算法进行了详细的介绍,对于常用的功能,作者先是提供一些可行的方案和思路,然后对算法的源码进行剖析,分析Java底层是怎么实现这些功能的,为什么要这样实现,怎么在已有类的基础上扩展功能。 技术只是工具,更重要的是思想和规则,比如: 1、用更多的时间研究问题本身,然后用更少的步骤去解决问题。 2、自顶向下设计,通用的算法,性能一般不是最优的。 3、复杂的功能,往往可以通过简单功能的组合或者重复去实现。 4、用时间换取空间或者用空间换取时间。 5、优先使用工具,而不是造轮子。 6、把一个大的问题拆分成一系列小的问题去解决。 要领悟Java的编程逻辑,就要有扎实的基本功,这本书可以作为Java技术指南来查阅,值得反复阅读,反复学习。
书很烂,写的像教科书一样,远远不及python从入门到实践,读到类的继承就已经读不下去了,我还买的是实体书,这本书也就是已经会用java的人用来查缺补漏,或者当工具书的,对于想用这本书入门的人来说实在是差得非常远,因为书中永远没有涉及现实使用的案例,读继承不知道为什么要继承,继承用来干啥的,读父类子类不知道用在哪,和所有的教科书一样,从定义到解析到例子,上来就是专业术语,不配合解析,1句话里恨不得塞10个专业名词,就是不说这个东西平时怎么用,在现实中为什么这么定义,是出于什么样的原因。我是看书看不下去了,专门下了个微信读书来写书评的。决定以后不会再买任何编程类的书了,直接从教学视频开始学就行了,买书是真没用
读的有点晚了 应该在工作半年后就读的 本书适合学完Java 并完成1个项目后阅读。本书对基础语法只是复习性的介绍,对Java的基础库原理有宏观的介绍,一步步引导,容易读懂,有助于以后深入学习Java库和框架
内容很多,每个点都结合具体代码讲解的很详细,可以当做一本字典吧,以后哪部分有问题可以翻一翻。
好棒,墙裂推荐,对于知道怎么做,却不知道为什么要这么做的程序员,最为有益