every step

JavaSE 总结

November 19, 2020 • ☕️☕️ 11 min read

这篇文章最初是看《Java 核心技术卷》所记的笔记,本来打算删除。但是最近又看到了极客时间的一套 Java 课程,加上正在整理 blog 于是在原文的基础上重写添加了一些内容。

Gosling:“语言是实现目标的工具,而不是目标本身。”

0.0 JAVA 优于 C++ 之处

  1. Java 清除了 C++ 中不常用到的东西,更为纯净。Java 单继承,而 C++ 多重继承。
  2. Java 更为健壮,与 C++ 相比,其指针模型消除重写内存和损坏数据的可能性。Java编译器可以检测到其他语言在运行时才能检测到到的问题。
  3. Java 数据类型的大小是固定的,如 int 型在任何编译器中都是32位,而 C++ 中 int 型的大小取决于操作系统,有可能是 16 位,有可能是 32 位,约束在于不能超过 longint 型, 不能小于 short int 型。

1996 年第一个 Java 版本发布,当时只有 211 个类与接口,而到了2014年 Java8 的发布就已经有了4240个类与接口。

XML是一种描述数据的方式,任何语言都可以处理XML数据,而Java 中的API对XML文件提供了很好的支持。

早期的Java并不开源,当Oracle收购sun之后,Java逐渐开源。

Java 区分大小写。

Java中Boolean 不能将 0 定义位false ,1 定义为真,而 c++ 可以混用。

1.0 关键字和标识符

1.1 标识符

  • 组成:由大小写英文字符,数字和下划线(_)组成,区分大小写,且不以数字开头的。
  • 使用:类名,方法名。
  • 注意:区分大小写!

关键字是保留字,有特殊含义!不能用来做其他用途。

关键字有:public,class,static,void,int …

1.2 注释

java注释分三种类型:

  1. // 注释内容(到本行末尾结束)
  2. /* 注释内容 */
  3. /** 注释内容*/ (可以生成文档)

2.0 数据类型

2.1 整数

  • byte: 1 byte (8 个 0/1 最高位为符号位),[-128,127]
  • short: 2 byte
  • int: 4 byte
  • long: 8 byte

2.2 浮点数

  • float: 4 byte
  • double: 8 byte

2.3 布尔和字符数据类型

  • boolean: 1 byte, true/false

Java中Boolean 只有两个值 true/false ,整型和布尔值之间不能互换。而 C++ 中可以将 0 定义为 false ,1 定义位 true 在 Java 中不可以这样用。

  • char: 2 byte
  • Unicode 和 Char

Unicode 的出现时为了统一不同编码,设计 Java 时采用 UTF-16 字符集,大概又六万多个位置。而很快六万多个位置都被中文,日文以及全世界语言的特殊符号填满了,此时位置不够用了。于是设计人员在此基础上又加了一个概念:码点。17个码点的出现,使得位置增为120万多个(也就是 6W * 17)。而在 Java 中 char 只是 UTF-16 的一个代码单元。

2.4 逻辑判断短路

A&&B 与 A&B 的区别 前者如果 A 为假继续判断 B 真假。 而后者判断到 A 为假时就不进行 B 的判断了,因为一假即假。

同理 || 与 | 两真才真。 求布尔值时会涉及短路。但计算值时不采用短路,两者都要计算。

3.0 优先级

  • 等号的优先级最低。(等待右边的运算才能进行赋值。)
  • 布尔运算符的优先级低于比较运算符。
  • 比较运算符的优先级比算术运算符低。

4.0 位运算

以 0 开头的整数为 8 进制。

例如: 05 是十进制下的 5,011 是十进制下的 9。

以 0x 开头的整数为 16 进制。

例如:0xF 是十进制下的 15, 0x11 是十进制的 17。

位移运算符:

  • 符号位不动,其余位右移动,符号位后补零,带符号右移动。

  • 符号位一起右移动,左边补零。

  • << 左移,右补零,左移动没有带符号的说法。

5.0 数据类型

Java 中数据类型可以分为基本数据类型引用数据类型

其中基本数据类型有 int,float 等。

引用数据类型指数组变量对象变量

new 可以创建出类的一个实例,放在内存的堆中。

6.0 重载 (OverLoad)

重载本质上是为了更大程度上的复用代码

当多个方法的代码功能相似但是略有差异之时,如果按照常规重复的写多个方法会导致代码严重重复。重载解决了这个问题。

代码的所有功能作为底层,重载是在此基础上修改调用底层方法,设定缺省值来修改输入来适配不同功能的需要。

重载的有限定要求,首先要明白什么是方法签名,方法签名方法名参数类型,注意返回值不属于方法签名。在一个类中方法签名可以唯一标识一个方法。

重载的要求是可以存在多个方法名,但是方法签名不可以重复。也就是重载的参数类型可以修改。

  1. 形参的个数
  2. 形参的顺序
  3. 形参的数据类型

这三个至少有一个是不同的。如果其他都相同,但函数的返回值不同,编译时会报错。

6.1 为什么方法的返回值不属于方法签名的一部分?

简单来说会导致掉用函数时产生二义性,也就是不知道要调用类中的哪个函数。

例子:如果返回值属于方法签名的一部分,对于两个相同名字且相同参数的方法,只是返回值不同时。

此时需要调用该方法,没有任何一个限定条件可以明确到底要调用哪个方法!因为标识该方法是通过方法名和参数来选定的,返回值并没有其到作用。

方法重载的返回值虽然可以不同,但是应当尽量一致!

7.0 构造方法

构造方法名字和类名一致,构造方法没有返回值,

如果没有显示的声明一个方法的构造方法,Java 或默认的声明一个无参的构造方法,该方法是一个空的方法。这也就是为什么 new 对象类名需要加括号的原因。

但是一旦显示的声明了一个构造方法,new 新方法时必须按照声明的参数来赋值,不然会报错!

构造方法返回值是对象的引用。

7.1 构造方法和重载

构造方法也可以重载,例如本来没有构造方法时使用默认的无参构造方法,写上有参的构造方法后如果在使用无参的方法来构造一个对象会报错!

此时可以重载一个无参的构造方法,这样就解决了报错问题。调用重载构造方法时不能使用成员变量,构造方法的目的是初始化对象,此时对象还未初始化完成,成员变量无法使用!

是 Java 内置的方法,构造方法是被该方法调用。

8.0 静态变量

命名规则:字母大写,字母之间的用下划线(_)衔接。

静态变量是类的组成,静态变量不随对象的变化而变化。也就是静态变量是独一份的,所有的对象访问的都是同一个静态变量。所以静态变量一旦发生改变,与之相关的引用都会受到影响。

8.1 静态方法

静态方法可以访问自己的静态变量和其他类的静态变量。

静态方法没有 this ,因为不属于某一个对象,可以直接通过类名访问。

静态方法也可以重载。

8.2 静态代码块

静态代码块必须在静态变量之后。

静态代码块和执行顺序的先后顺序有关,如果同一个变量被重复赋值,那么该值为最后一个所赋的值覆盖。

9.0 访问修饰符

如果缺省的话,可见范围是该包的内部。

可以将方法设置为 private ,通过 static 方法来调用该方法,在 static 设置参数范围合法检查之类的操作。

谨慎的使用 public !以 JDK 为例,如果后续版本将某个方法 public 修改为了 pirvate ,那么这个方法就无法使用了之前可以跑的代码在该版本上就不能使用了!也就是前后不兼容。

protect 对包内可见,对子类可见。

子类覆盖的父类的方法可见性可以提高,但是不能降低。

10.0 String

String 对象不可变!

String 的 length() 是方法不是属性。

StringBuilder 是可边的,可以在对象原来的地址上进行处理或修改 string 。

11.0 继承

组合也可以实现继承的功能,但是继承更像是二者的融合,而组合有所限制,二者并不完全等同。

super 调用父类的构造方法必须是子类构造方法的第一个语句。

12.0 final

final 修饰时不允许别人去扩展该类,也就是不能继承。

final 修饰成员变量时,声明变量时就需要赋值,不允许被覆盖。如果声明时没有被赋值可以在 static 块中被赋值,也是只能被赋值一次!

final 不能修饰构造方法,修饰了会导致构造方法不能被覆盖,事实上构造方法不能被覆盖很不合理!

final 修饰方法时,该方法不能被子类覆盖。

final 修饰引用时,该引用存储的内容是可边的,但是该引用的地址不变

总之, final 指向的”东西“不变,但是该“东西”中存的”东西“是可边的。

13.0 instanceof

instanceof 用于判断一个引用对象是否是某个类型或该类型的子类。

14.0 HashCode 和 equals

hashcode 可以唯一标识一个对象。

equals 相等则 hashcode 一定相等,反之不成立。

注意在字符串判断中 == 判断的是两个对象的地址,而 equals 则判断的是两个字符串对象中存储的值。

Java 在创建字符串时(该字符串不太长)会在一个临时的空间中存放,如果再次创建一个相同的字符串会直接从该取之前存放引用。所以在字符串比较短时可以用 == 来判断两个字符串的值是否相等。

在判断字符串值相等时最好还是用 equals 方法!

15.0 大数值

  • BigInteger 实现了不同的整数运算。
  • BigDecimal 实现了不同的浮点运算。
  • valueOf 使用静态的valueOf方法将数值转换为大数值。
  • add/subtract/multiply/divide/mod 分别对应和/差/积/商/取余

例:

        BigDecimal bigDecimal = new BigDecimal(100);
        BigDecimal bigDecimal1 = bigDecimal.add(bigDecimal);
        BigDecimal bigDecimal2  = bigDecimal.divide(bigDecimal);
        BigDecimal bigDecimal3 = bigDecimal.multiply(bigDecimal);
        BigDecimal bigDecimal4 = bigDecimal.subtract(bigDecimal);

16.0 Maven

包管理器,用户管理 Jar 包。

maven 分为服务器端和本地两部分。所有发布的 Jar 包都会发布在服务器端,而使用 Jar 包时需要从服务器端下载,为了避免每次都得下载可以将下载好的包放在本地仓库中。

每一个 Jar 包都是唯一的,而 maven 通过 group id,artifact id 和 version 三者可以唯一标识一个 Jar 包。

注意 Jar 包之间存在依赖,而 maven 在下载存在依赖的 Jar 包之时会自动的将涉及到的依赖下载。

17.0 JDK

17.1 JDK 和 JRE 的区别

JDK: Java Development Kit JRE: Java Running Environment

JRE是Java运行时的开发环境,而JDK则是Java 的开发工具包,JDK包含JRE。 如果只是运行java程序,装JRE即可,如果编写Java程序,装JDK。

18.0 异常

Error 和 Exception 的区别:后者是可以修复的,前者难以修复。