1. 数据类型

  • 基本数据类型

    • byte \$-2^7 ~ 2*7-1\$

    • short \$-2^15~2^15-1\$

    • int \$-2^31~2^31-1\$

    • long \$-2^63~2^63-1\$

    • boolean

    • char Unicode \$0~2^16-1\$

    • float IEEE754

    • double IEEE754

  • 引用数据类型

    • Class

    • Interface

    • Array

2. 位运算符

  • << 左移运算符, 向左移n位, 右边补0.

  • >> 带符号右移, 向右移n位, 左边补第1位的值.

  • >>> 无符号右移, 向右移n位, 左边补0.

3. 字符编码

3.1. ASCII

用0~127分别表示128个字符.
1个字节大小

3.2. Unicode

给每个字符分配一个16进制的数字编号, 数字编号范围从0x000000到0x10FFFF.
但是Unicode本身没有定数字编号到二进制之间的转换关系.

unicode

3.2.1. UTF-8

UTF-8 使用一至四个字节为每个字符编码
  • 对于单字节字符, 首位为0, 后面7位表示字符

  • 对于多字节字符, 第一个字节以n个1和一个0开头, 其他字节以10开头, 再从后往前补齐二进制位.

3.2.2. UTF-16

UTF-16 使用二或四个字节为每个字符编码
  • 存在一个起始字节序列, FFFE/FEFF 标识小端/大端.

  • Unicode码小于U+10000的,直接转换为UTF-16双字节序列.

  • 大于等于U+10000的, 先减去0x10000, 再分别分成10个比特位.
    高位前面用 110110 填充, 低位前面用 110111 填充.

3.2.3. UTF-32

UTF-32 使用四个字节为每个字符编码
  1. 存在一个起始字节序列, 0000FEFF/FFFE0000 分别标识大端/小端.

  2. 将Unicode码分成四个字节, 高位不足的补0.

字符 Unicode UTF-8 UTF-16 UTF-32

A

00000000,01000001

01000001

00000000,01000001

00000000,00000000,00000000,01000001

؆

00000110,00000110

11011000,10000110

00000110,00000110

00000000,00000000,00000110,00000110

01001110,00100101

11100100,10111000,10100101

01001110,00100101

00000000,00000000,01001110,00100101

𠀲

11011000,01000000,11011100,00110010

11110000,10100000,10000000,10110010

11011000,01000000,11011100,00110010

00000000,00000010,00000000,00110010

4. 浮点数

4.1. 浮点数的表示方法

\$V=(-1)^s*M*2^E\$

  • S: 符号位, 决定是正数还是负数, 1代表负数.

  • E: 阶码, 值是2的幂, 它的作用是对浮点数加权.

  • M: 尾数.

4.2. 浮点数的存储方法

一个浮点数被分为三部分存储:

  • s : 符号位标识正数还是负数.

  • exp : k位阶码字段, 与E相关.Bias=\$2^(k-1)-1\$

    • 单精度为8位.
      Bias=127.

    • 双精度为11位.
      Bias=1023.

  • frac : n位小数字段, 与M相关.

4.3. 浮点数的分类

4.3.1. 规范化浮点数

exp 部分不全为0或1.

E=exp-Bias.
M=frac+1. (规范化浮点数首位为1, 所以M=frac+1)

如 0.10111, 可以表示为 \$1.0111* 2^(-1)\$ , frac=0.0111, M=frac+1=1.0111

4.3.2. 非规范化浮点数

exp 部分全为0.

E=1-Bias, M=frac.

4.3.3. 无穷大

exp 部分全为1, frac 部分全为0.

4.3.4. NaN

exp 部分全为1, frac 部分不等于0.

5. 面向对象

5.1. 可见性

private < default < protected < public

  • private : 只能在类的内部访问.

  • default : 只能被同一个包中其他类访问.
    (子包也不能访问)

  • protected : 可以被子类或同一个包中其他类访问.

  • public : 可以被任意类访问.

5.2. 重载

重载指同一个类内方法名称相同, 但参数类型/声明的异常/返回值类型不同.

5.3. 重写

  • 参数列表必须相同.

  • 子类可以提升方法的可见性.

  • 子类抛出的checked异常必须与父类相同, 或是父类抛出checked异常的子类, 或者不抛.

  • 子类方法的返回值可以是父类返回值类型的子类.

5.4. 接口default方法判定

  • Class优先.

  • 子接口优先.

  • 无法确定需用 类名.super 显式调用.

Class#getDeclaredMethods不包含从父类继承过来的方法.

5.5. 内部类

5.5.1. 静态内部类

静态内部类可以访问外部类的private静态变量和方法, 但不可以访问外部类的实例变量或方法.

5.5.2. 成员内部类

  • 成员内部类可以访问外部类的实例变量和方法.

  • 成员内部类不可以自己定义静态变量和方法.

5.5.3. 匿名内部类

匿名内部类方法参数属于final, 不能修改值/引用.

6. 异常

6.1. Checked Exception

继承Exception但不是RuntimeException的异常类.
需要程序手动处理.

6.2. Unchecked Exception

继承RuntimeException/Error的异常类.
程序可以选择捕获处理, 也可以不处理.

7. 注解

7.1. 重复注解

@Repeatable(xxx.class) & getAnnotationsByType(xxx.class);

7.2. Retention

源码 字节码文件 运行时获取

Source

Class

Runtime

7.3. Target

  • Type: 类、接口、注解、枚举

  • Field: 字段

  • Method: 方法

  • Parameter: 方法参数

  • Constructor: 构造函数

  • Local_Variable: 局部变量

  • Annotation_Type: 只能用在注解上

  • Package: 包声明上

  • Type_Parameter: 类参数, 尚未参透

  • Type_Use: 用在任何声明&定义的类型处

8. 枚举

8.1. 枚举类方法

  • values() 返回所有枚举常量

  • valueOf(String) 返回名字对应的枚举常量

  • name() 返回枚举常量名字

  • oridinal() 返回枚举常量的序号

  • compareTo() 比较枚举常量的序号

8.2. EnumSet

  • EnumSet.allOf(Enum.class) 返回包含所有枚举常量的集合

  • EnumSet.rangOf(EnumA,EnumB) 返回A与B之间所有的枚举常量, 包括边界

8.3. EnumMap

  • EnumMap#entrySet 为空,forearch用不了, 只能手动put ==to fix==

9. 序列化

  1. serialVersionUID标识类的序列化的版本号,如果反序列化时当前类的版本号与序列化的二进制流对象的版本号不一致则会抛出异常.

  2. 序列化时会调用readObject方法,反序列化时会调用writeObject方法.

  3. 序列化再反序列化后静态成员变量值为最新的.

10. 泛型

  1. 上界通配符 <? extends T> 只能get到泛型边界类型

  2. 下界通配符 <? super T> 只能get到Object类型, add时只能传泛型边界的类型.

  3. 取不到一个类定义的泛型类型(T), 只能取其子类或父类具体的泛型类型(Long,String…​).

package me.jy.lang.generic;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;

/**
 * @author jy
 */
public class GenericDemo {

    public static void main(String[] args) {
        // A -> B -> C
        Example<? extends B> eba = new Example<A>();
        Example<? extends B> ebb = new Example<B>();
//        Example<? extends B> ebc = new Example<C>(); // error, C不是B的子类

//        Example<? super B> sba = new Example<A>(); // error, A不是B的父类
        Example<? super B> sbb = new Example<B>();
        Example<? super B> sbc = new Example<C>();

        List<? super B> superList = Arrays.asList(1, new C(), new B(), new A());
        Object s0 = superList.get(0); // get返回Object类型
        System.out.println(s0);
//        A s1 = (A) superList.get(0); // 编译通过, 但运行时抛出ClassCastException

        List<? extends C> extendsList = Arrays.asList(new A(), new B(), new C());
        C c = extendsList.get(0);
//        extendsList.add(new C()); // error, 无法add任何类型

        System.out.println(new SubExample().getGenericType());
    }

    private static class SubExample extends Example<Integer>{

    }

    private static class Example<T> {

        // 获取泛型类型
        public Type getGenericType(){
            ParameterizedType parameterizedType = (ParameterizedType) getClass().getGenericSuperclass();
            return parameterizedType.getActualTypeArguments()[0];
        }
    }

    private static class C {
    }

    private static class B extends C {
    }

    private static class A extends B {
    }
}

11. ClassLoader

  • loadClass 实现双亲委托模型

  • findClass 实现类文件读取

12. Stream

一个完整的操作是<数据来源,操作,回调函数>构成的三元组.
Stream中使用Stage的概念来描述一个完整的操作, 并用某种实例化后的PipelineHelper来代表Stage, 将具有先后顺序的各个Stage连到一起, 就构成了整个流水线.

12.1. 中间操作

  1. 无状态:

    1. unordered

    2. filter

    3. map

    4. mapToInt

    5. mapToLong

    6. mapToDouble

    7. flatMap

    8. flatMapToInt

    9. flatMapToLong

    10. flatMapToDouble

    11. peek

  2. 有状态

    1. distinct

    2. sorted

    3. limit

    4. skip

12.2. 结束操作

  1. 非短路操作

    1. forEach

    2. forEachOrdered

    3. toArray

    4. reduce

    5. collect

    6. max

    7. min

    8. count

  2. 短路操作

    1. anyMatch

    2. allMatch

    3. noneMatch

    4. findFirst

    5. findAny

13. JDBC

13.1. Statement

  • 同一个connection可以创建多个 Statement.

  • 在处理 ResultSet 的结果时也可以创建另外一个 Statement.

  • Statement 不是线程安全的.

  • 用完后需要close.

  • SQL语句中如果需要使用包含 ? 符号的函数可以使用 ?? 转义.

13.2. ResultSet

  • 在获取结果集前需要调用 next() 方法.

  • 使用 Statement 获取 ResultSet 后, 当前使用中的 ResultSet 会直接关闭.

  • 用完后需要close.

14. NIO

14.1. Channel

Channel代表程序和某一个文件描述符的连接, 可以是文件(FileChannel), 或者是套接字(DatagramChannel/SocketChannel/ServerSocketChannel).

14.1.1. Channel和Stream的区别

  • Stream只能是单向的, 分为InputStream和OutputStream, 而Channel可以使双向的.

  • Stream的read和write是阻塞的, 而Channel支持非阻塞模式.

14.2. Buffer

Buffer是一个存放基本类型(除了boolean)数据的容器, 拥有以下属性/方法:

  • capacity: Buffer总的容量.

  • position: 当前可以写入的位置.

  • limit: 能够写入的最后一个位置.

  • mark: 记录上一次读写开始的位置(position).

  • remaining(): 剩余可操作的个数.

  • flip(): (读模式) 将limit赋值为position的值, 再将position设置为0, 重置mark, 用于读取Buffer内容.

  • rewind(): 将position设置为0, 重置mark, 用于重新读取Buffer内容, 如读取同一个Buffer然后写入多个Channel时.

  • mark(): 将position赋值给mark, 记录一下当前position.

  • reset(): 重置position为上一次的position.

  • clear(): (写模式) 重置所有变量: position=0, mark=-1, limit=capacity.

  • compact(): 将position和limit中间的数据拷贝到Buffer开头, 然后将position指向这段数据的下一个位置.

14.3. Selector

Selector负责收集通道的事件.