《Java核心技术》读书笔记

《Java核心技术》读书笔记
wshunli《Java核心技术》读书笔记
前面阅读了《Java 编程思想》,可能是水平不够吧,感觉读起来很吃力,这次拿 《Java核心技术》 复习下。
《JAVA编程思想》 和 《JAVA核心技术Ⅰ》 看哪本? - 知乎
https://www.zhihu.com/question/29745861
这次就不再那么详细地记录了。
第一章 Java 程序设计概述
主要介绍了 Java 程序的平台:Java SE、Java EE、Java ME 及 Java 发展简史。
第二章 Java 程序设计环境
主要介绍了 Java 环境的搭建以及常用命令行工具。
javac Main.java |
javac 是 Java 编译器,将 Main.java 源代码编译为 Main.class ;
java 启动 Java 虚拟机,虚拟机执行 class 文件中的字节码。
然后介绍了 图形化应用程序 和用于浏览器的 applet 技术。
第三章 Java 的基本程序设计结构
Hello World
package com.wshunli; |
还是得记住这段的,得能手写出来。
基本数据类型
Java 语言提供了八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型。
1、整形
| 类型 | 字节 | 取值范围 | 封装器类 |
|---|---|---|---|
| byte | 1 | -128(-2^7)~ 127(2^7-1) | Byte |
| short | 2 | -32768(-2^15)~ 32767(2^15 - 1) | Short |
| int | 4 | -2,147,483,648(-2^31)~ 2,147,483,647(2^31 - 1) | Integer |
| long | 8 | -9,223,372,036,854,775,808(-2^63)~ 9,223,372,036,854,775,807(2^63 -1) | Long |
long 长整型数值有一个后缀 L 或 l ( 如 0L )
2、浮点型
| 类型 | 字节 | 取值范围 | 封装器类 |
|---|---|---|---|
| float | 4 | 大约 ± 3.402 823 47E+38F (有效位数为6 ~ 7 位) | Float |
| double | 8 | 大约 ± 1.797 693 134 862 315 70E+308 (有效位数为15 位) | Double |
float 浮点型数值有一个后缀 F 或 f ( 如 0.0f )
double 双精度型数值有一个后缀 D 或 d ( 如 0.0d )
3、字符类型
在 Java 中,char 类型描述了 UTF-16 编码中的一个代码单元。
4、布尔型
boolean ( 布尔)类型有两个值: false 和true,用来判定逻辑条件。
整型值和布尔值之间不能进行相互转换。
变量
变量的声明及初始化,不区分变量的声明与定义。
int vacationDays; |
1、常量
在 Java 中, 利用关键字 final 指示常量。
final double CM_PER_INCH = 2.54; |
关键字 final 表示这个变量只能被赋值一次。习惯上,常量名使用全大写。
浅谈Java中的final关键字 - 平凡希 - 博客园
https://www.cnblogs.com/xiaoxi/p/6392154.html
2、类常量、静态常量
static 关键字用来声明独立于对象的静态变量,无论一个类实例化多少对象,它的静态变量只有一份拷贝。
public static final double CM_PER_INCH = 2.54; |
可以在一个类或者其他类中的多个方法中使用。
运算符
Java 中的数据是通过使用操作符来操作的。
- 赋值操作符
- 算术操作符
- 关系操作符
- 逻辑操作符
- 按位操作符
- 其他操作符
1、常用的数学计算函数
JAVA Math 类的数学计算函数 - CSDN博客
https://blog.csdn.net/antares_santalen/article/details/52451807
2、数值类型之间的转换
Java 中数值类型之间的转换方式有两种:一是自动类型转换,另一种是强制类型转换。
自动类型转换:
实线表示无信息丢失的转换,虚线表示可能有精度丢失的转换。
如果两个操作数中有一个是 double 、float 、long 类型,别一个操作数就会转换为相同类型。
否则,两个操作数都将被转换为 int 类型。
强制类型转换 的格式是在需要转型的数据前加上“( )”,然后在括号内加入需要转化的数据类型。
有的数据经过转型运算后,精度会丢失,而有的会更加精确。
字符串
字符串也是相当重要的概念,Java 字符串就是 Unicode 字符序列。
1、Java String 的静态方法
static String valueOf(Object obj) |
2、Java String 的主要实例方法
// 获取子串 |
涉及到内容也比较多,官方 API 文档:
https://docs.oracle.com/javase/10/docs/api/java/lang/String.html
3、构建字符串
直接使用字符串拼接效率比较低,因为每次连接字符串, 都会构建一个新的 String 对象,既耗时, 又浪费空间。
可以使用 StringBuilder 避免这个问题:
StringBuilder builder = new StringBuilder(); |
参考 API 文档:
https://docs.oracle.com/javase/10/docs/api/java/lang/StringBuffer.html
https://docs.oracle.com/javase/10/docs/api/java/lang/StringBuilder.html
String、StringBuffer 和 StringBuilder 的区别:
首先说运行速度,或者说是执行速度,在这方面运行速度快慢为:StringBuilder > StringBuffer > String;
其次在线程安全上,StringBuilder 是线程不安全的,而 StringBuffer 是线程安全的。
- String:适用于少量的字符串操作的情况
- StringBuilder:适用于单线程下在字符缓冲区进行大量操作的情况
- StringBuffer:适用多线程下在字符缓冲区进行大量操作的情况
Java中的String,StringBuilder,StringBuffer三者的区别 - 酥风 - 博客园
https://www.cnblogs.com/su-feng/p/6659064.html
输入输出
1、读取控制台输入,也经常用到,使用 Scanner 类。
Scanner scanner = new Scanner(System.in); |
2、格式化输出
使用 System.out.printf() 格式化输出:
System.out.printf("%,.2f", 10000.0 / 3); |
用于 printf 的转换符。
3、文件的输入输出
try { |
流程控制
主要介绍条件语句和循环结构控制流程。
大数值
如果基本的整数和浮点数精度不能够满足需求, 那么可以使用 java.math 包中的两个很有用的类: BigInteger 和 BigDecimal 。这两个类可以处理包含任意长度数字序列的数值。
BigInteger 类实现了任意精度的整数运算, BigDecimal 实现了任意精度的浮点数运算。
数组
数组是一种数据结构, 用来存储同一类型值的集合。
1、匿名数组:
int[] smallPrimes = {2, 3, 5, 7, 11, 13}; |
2、数组拷贝
数组变量拷贝直接赋值即可,这样两个变量将引用同一数组。
如果希望将一个数组的所有值拷贝到一个新的数组中去,就要使用 Arrays 类的 copyOf 方法。
int[] copyOfSmallPrimes = Arrays.copyOf(smallPrimes, smallPrimes.length); |
3、数组排序
要想对数值型数组进行排序, 可以使用 Arrays 类中的 sort 方法:
Arrays.sort(smallPrimes); |
4、命令行参数
每一个Java 应用程序都有一个带 String arg[] 参数的 main 方法。
这个参数表明 main 方法将接收一个字符串数组, 也就是命令行参数。
例如:
public class Message { |
运行时输入如下命令:
java Message -g cruel world |
结果:
Goodbye,cruel world! |
5、多维数组
6、不规则数组
第四章 对象与类
1、类、对象及类之间的关系。
类之间常见的关系:依赖(“ uses-a ”)、聚合(“ has-a ”)、继承(“ is-a ”)
2、预定义类和用户自定义类。
3、静态域和静态方法
4、方法参数
Java 程序设计语言总是采用按值调用。(引用调用表示方法接收的是调用者提供的变量地址。)
也就是说, 方法得到的是所有参数值的一个拷贝,方法结束就丢弃该拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
然而,方法参数共有两种类型:基本数据类型、对象引用。
对于基本数据类型,方法只是获得参数值的拷贝,无法修改实参的值;
对于对象的引用,方法同样得到对象引用的拷贝,该拷贝和对象引用同时引用同一对象,则可以修改对象的状态。
private static void swap(Employee x, Employee y) { |
结果 对象 a 和 b 并未交换,只是交换了各自引用的拷贝,方法结束就丢弃了。
总结:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)。
- 一个方法可以改变一个对象参数的状态。
- 一个方法不能让对象参数引用一个新的对象。
5、对象构造
主要介绍了类的构造方法、初始化顺序以及初始化块、对象析构的概念。
6、包和类的路径
7、文档注释
第五章 继承
类、超类和子类
主要介绍了子类和父类之间的关系,方法的覆盖,多态,抽象类相关内容等。
1、对象包装器与自动装箱
基本数据类型都有一个与之对应的类。
Integer、Long、Float、Double、Short、Byte、Character 、Void 和 Boolean 。
2、枚举类
public enum Size { SMALL, MEDIUM, LARGE, EXTRAJARGE }; |
3、泛型数组列表
其实就是 java 集合的相关内容,主要是 ArrayList 。
Object 所有类的超类
Object 类是 Java 中所有类的始祖, 在 Java 中每个类都是由它扩展而来的。
1、equals 方法
Object 类中的 equals 方法用于检测一个对象是否等于另外一个对象。
在 Object 类中,这个方法将判断两个对象是否具有相同的引用。
2、hashCode 方法
散列码( hash code ) 是由对象导出的一个整型值。散列码是没有规律的。
如果x 和y 是两个不同的对象, x.hashCode( ) 与y.hashCode( ) 基本上不会相同。
Java hashCode() 和 equals()的若干问题解答 - 如果天空不死 - 博客园
http://www.cnblogs.com/skywang12345/p/3324958.html
3、toString 方法
在 Object 中还有一个重要的方法, 就是 toString 方法, 它用于返回表示对象值的字符串。
参数数量可变的方法
在参数列表中 Object… 参数类型与 Object[] 完全一样。
public static double max(double... values) { |
反射
反射库 ( reflection library ) 提供了一个非常丰富且精心设计的工具集, 以便编写能够动态操纵 Java 代码的程序。
1、Class 类
在程序运行期间,Java 运行时系统始终为所有的对象维护一个被称为运行时的类型标识。
这个信息跟踪着每个对象所属的类。保存这些信息的类被称为 Class 。
获取 Class 对象有三种方法:
Employee employee = new Employee(); |
可以使用 Class 的方法获取相关信息,如使用 newlnstance( ) 可以用来动态地创建一个类的实例:
try { |
2、利用反射分析类的能力
在 java.lang.reflect 包中有三个类 Field、Method 和 Constructor 分别用于描述类的域、方法和构造器。
三个类中都有 getName 、getType 、getModifiers 方法,分别返回 名字、返回类型、及标识符。
Field[] fields = Integer.class.getFields(); |
Class 类中的 getFields、getMethods 和 getConstructors 方法将分别返回类提供的 public 域、方法和构造器数组, 其中包括超类的公有成员。
Class 类的 getDeclareFields、getDeclareMethods 和 getDeclaredConstructors 方法将分别返回类中声明的全部域、方法和构造器, 其中包括私有和受保护成员,但不包括超类的成员。
3、在运行时使用反射分析对象
在运行时使用反射分析对象方法主要是使用 Field 等的 get、set 方法。
Employee employee = new Employee("wshunli", 15); |
4、调用任意方法
反射机制允许调用任意方法。在 Method 类中有一个 invoke 方法, 它允许调用包装在当前 Method 对象中的方法。
invoke 方法的签名是:
Object invoke(Object obj, Object... args) |
第一个参数为实例对象,静态方法可以设置为 null;
第二个参数为方法得参数;
返回值需完成类型转换。
try { |
第六章 接口、lambda 表达式与内部类
接口及其示例
1、接口的概念及特点
在 Java 程序设计语言中, 接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式进行定义。
public interface Comparable { |
接口的特点:
Java 单继承,只能继承一个(抽象)类,单个类可以实现多个接口;
Java 强类型语言,接口可以保证接口的实现类都实现了接口的方法。
接口中的成员函数默认为 public ,成员变量默认设置成 public static final ;
接口不能包含静态方法和实例对象(在 Java SE 8 以前),但能包含静态成员变量(默认为常量)。
2、静态方法
在 Java SE 8 中,允许在接口中增加静态方法。
public interface Path { |
3、默认方法及其冲突
可以为接口方法提供一个默认实现。必须用 default 修饰符标记这样一个方法。
public interface Comparable<T> { |
使用默认方法,接口的实现类就不必实现该方法了。
如果先在一个接口中将一个方法定义为默认方法, 然后又在超类或另一个接口中定义了同样的方法。
解决默认方法冲突:
超类优先。如果超类提供了一个具体方法, 同名而且有相同参数类型的默认方法会被忽略。
接口冲突。如果一个超接口提供了一个默认方法, 另一个接口提供了一个同名而且参数类型(不论是否是默认参数)相同的方法, 必须覆盖这个方法来解决冲突。
以上为两个接口的命名冲突,
对于继承一个超类又同时实现一个接口的类,并且超类和接口存在相同的方法,只会考虑超类方法。
lambda 表达式
以前也知道这个概念,书上说得有点绕。
Lambda 表达式有何用处?如何使用? - Sevenvidia的回答 - 知乎
https://www.zhihu.com/question/20125256/answer/324121308
Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
Java8 lambda表达式10个示例 - ImportNew
http://www.importnew.com/16436.html
Lambda 表达式本身就是一个接口的实现。
内部类
内部类( inner class ) 是定义在另一个类中的类。
- 内部类方法可以访问该类定义所在的作用域中的数据, 包括私有的数据。
- 内部类可以对同一个包中的其他类隐藏起来。
- 当想要定义一个回调函数且不想编写大量代码时,使用匿名(anonymous) 内部类比较便捷。
1、使用内部类访问对象状态
2、内部类的特殊语法
outerObject.this.para; |
3、局部内部类、匿名内部类、静态内部类
代理
利用代理可以在运行时创建一个实现了一组给定接口的新类。
说说 JAVA 代理模式 - ImportNew
http://www.importnew.com/26116.html
这里主要讲的是动态代理
// 抽象角色 |
要想创建一个代理对象, 需要使用 Proxy 类的 newProxylnstance 方法。这个方法有三个参数:
- 一个类加栽器( class loader)。
- 一个 Class 对象数组, 每个元素都是需要实现的接口。
- 一个调用处理器。
第七章 异常、断言和日志
对于异常情况,Java 使用一种称为异常处理( exception handing) 的错误捕获机制处理。
异常
1、处理错误
在 Java 程序设计语言中, 异常对象都是派生于 Throwable 类的一个实例。
异常可分为 Error 、Exception 两类。
Error 描述了 Java 运行时系统的内部错误和资源耗尽错误。应用程序不应该抛出这种类型的对象。
Exception 又分解为两个分支:一个分支派生于 RuntimeException ,由程序错误导致的异常; 另一个分支包含其他异常,程序本身没有问题,但由于像 I/O 错误这类问题导致的异常。
Java 语言规范将派生于 Error 类或 RuntimeException 类的所有异常称为非受查( unchecked ) 异常, 所有其他的异常称为受查 ( checked ) 异常。这
2、抛出异常
一个方法必须声明所有可能抛出的受查异常, 而非受查异常要么不可控制 ( Error),要么就应该避免发生 ( RuntimeException )。
《Java编程思想》读书笔记(五) | CirGIS
https://www.wshunli.com/posts/b6f25079.html
4、捕获异常
如果某个异常发生的时候没有在任何地方进行捕获,那程序就会终止执行,并在控制台上打印出异常信息, 其中包括异常的类型和堆栈的内容。
使用断言
编写代码时,我们总是会做出一些假设,断言就是用于在代码中捕捉这些假设。
断言可以有两种形式:
1.assert Expression1
2.assert Expression1:Expression2
当执行代码时,使用 -ea 选项使断言有效,也可以使用 -da 选项使断言无效(默认为无效)。
记录日志
要生成简单的日志记录,可以使用全局日志记录器(global logger) 并调用其 info 方法:
Logger.getGlobal().info("start record log"); |
日志的级别:SEVERE (highest value)、WARNING、INFO、CONFIG、FINE、FINER、FINEST (lowest value)
public class LoggerDemo { |
然后介绍了日志的配置、本地化、处理器、过滤器、格式化器等。
第八章 泛型程序设计
泛型程序设计 ( Generic programming ) 意味着编写的代码可以被很多不同类型的对象所重用。
1、为什么要使用泛型程序设计
类型参数,其中 String 为类型参数:
ArrayList<String> list = new ArrayList<>(); |
类型参数的魅力在于:使得程序具有更好的可读性和安全性。
2、泛型类 ( generic class ) 就是具有一个或多个类型变量的类。
public class Holder1<T, U> { |
在 Java 库中, 使用变量 E 表示集合的元素类型, K 和 V 分别表示表的关键字与值的类型。
T ( 需要时还可以用临近的字母 U 和 S ) 表示 “任意类型”。
类型变量的限定:
class Holder2<T extends Comparable> { |
表示 T 应该是绑定类型的子类型。T 和绑定类型可以是类, 也可以是接口,均使用 extends 关键字。
3、泛型方法
public <T> void f(T x) { |
4、泛型代码和虚拟机
虚拟机没有泛型类型对象 — 所有对象都属于普通类。
类型擦除:在虚拟机中,擦除类型变量, 并替换为限定类型 ( 无限定的变量用 Object )。
后面讲了泛型的约束和局限性。
5、通配符类型
通配符类型中,允许类型参数变化。
Pair<? extends Employee> |
通配符的超类型限定:
通配符限定与类型变量限定十分类似,但是,还有一个附加的能力, 即可以指定一个超类型限定, 如下所亦:
Pair<? super Employee> |
无限定通配符:
Pair<?> |
第九章 集合
Java 集合框架
在 Java 类库中,集合类的基本接口是 Collection 接口。
很重要的接口 迭代器 Iterator
public interface Iterator<E> { |
应该将 Java 迭代器认为是位于两个元素之间。当调用 next 时, 迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。
《Java编程思想》读书笔记(四) | CirGIS
https://www.wshunli.com/posts/d96c953e.html
Java 集合
java集合类 - java开发者 - SegmentFault 思否
https://segmentfault.com/a/1190000008522388
由浅入深理解java集合(一)——集合框架 Collection、Map - 简书
https://www.jianshu.com/p/589d58033841
40个Java集合面试问题和答案 - ImportNew
http://www.importnew.com/15980.html
第十章到十三章
只要介绍使用图形用户界面的 Java 程序,这里就不看了。
第十四章 并发
这部分大概地看了下,后面再看本书仔细学习。











