# 用户和程序交互

  • 运行 Java 程序的参数 运行 Java 程序时在类名后紧跟一个或多个字符串(多个字符串之间以空格隔开),JVM 就会把这些字符串依次赋给 args 数组元素

  • Console 控制台

    // java.io.Console
    // 通过调用 System.console() 方法获得该类唯一的实例
    Console console = System.console();
    // 从控制台读取单行文本
    String line = console.readLine();
    
    1
    2
    3
    4
    5
  • 使用 Scanner 获取键盘输入

    // java.util.Scanner
    // System.in 代表标准输入,即键盘输入
    Scanner sc = new Scanner(System.in);
    // 返回输入源中下一行的字符串
    String line = sc.nextLine();
    
    1
    2
    3
    4
    5

# 系统相关

# System

  • 类方法
    1. void arraycopy(Object src, int srcPos, Object dest, int destPos, int length):从 源数组 src 的 srcPos 位置 复制元素到 目标数组 dest 的 destPos 位置,复制的数组元素的个数为 length
    2. long currentTimeMillis():获取系统当前时间(毫秒)(距离 1970 年 1 月 1 日 00:00:00 GMT)
    3. Properties getProperties():获取当前的系统属性
    4. String getProperty(String key):获取指定键指示的系统属性
    5. int identityHashCode(Object x):返回给定对象的哈希码
    6. void exit(int status):终止 JVM(非 0 的状态码表示异常终止)(底层调用 Runtime 类中的方法)
    7. void gc():运行 GC(底层调用 Runtime 类中的方法)

# Runtime

  • 类方法
    Runtime getRuntime():获取与当前 Java 应用程序相关的运行时对象(单例模式)

  • 实例方法

    1. Process exec(String command):在单独的进程中执行指定的字符串命令,返回一个新的 Process 对象
    2. void exit(int status):终止 JVM(非 0 的状态码表示异常终止)
    3. void gc():运行 GC
    4. void addShutdownHook(Thread hook):注册虚拟机关闭钩子(一个已初始化但尚未启动的线程)
    5. int availableProcessors():返回虚拟机可用处理器的数目

# Object 类

  • Object 是所有类、数组、枚举类的父类,所有对象(包括数组)都实现这个类的方法

  • Object 类的常见方法

  1. protected void finalize():在对象被垃圾收集前调用此方法

  2. Class getClass():返回当前对象的运行时类型(该方法使用了 final 修饰,不能被覆写)

  3. int hashCode():native 方法,返回当前对象的 hashCode 值,hashCode 决定了对象在哈希表中的存储位置

  4. boolean equals(Object obj):判断指定对象与该对象是否相等

    • equals 方法,判断标准和 == 相同,都是比较对象的引用地址
    • 如果需要比较对象的内容,子类应该覆盖 equals 方法
    • 基本数据类型只能使用 == 比较
  5. String toString():返回该对象的字符串表示

    • System.out.println(obj); // 等价于 System.out.println(obj.toString());
    • toString 方法,返回“运行时类名@十六进制 hashCode 值”字符串
    • 如果需要打印对象的内容,子类应该覆盖 toString 方法
  6. Object clone():创建并返回此对象的一个副本,使用此对象相应字段的内容初始化副本的所有字段(浅克隆)

    浅克隆——只克隆该对象的所有成员变量值,不会对引用类型的成员变量值所引用的对象进行克隆

    自定义类实现“克隆”的步骤:1. 实现 Cloneable 接口(一个标记性的接口);2. 实现父类 Object 的 clone() 方法,通过 super.clone(); 调用 Object 实现的 clone() 方法来得到该对象的副本(无需调用构造器),并返回该副本

  7. wait()notify()notifyAll()(这些方法都使用了 final 修饰,不能被覆写)

# 字符串

  • 本质:char[] value
  • CharSequence 接口常用的三个实现类:String StringBuffer StringBuilder
  • 分类
    1. String 类创建的、字符序列不可变的的字符串对象
    2. StringBuffer 类或 StringBuilder 类创建的、字符序列可变的字符串对象

# String

  • String 是最终类、不可变类,final char[] value

  • 注意:String 重写了 equals()、hashCode() 方法

  • 对象的创建

    // 1):直接赋一个字符串直接量(包括可以在编译时不用访问普通变量或调用方法就可以计算出来的字符串值):先在常量池创建 "ABCD"(若常量池已存在 "ABCD",则不再创建),str1 再引用
    String str1 = "ABCD";  // 等同于 String str1 = "AB" + "CD"; (编译器优化)
    // 直接使用双引号声明出来的两个 String 对象指向常量池中的相同字符串
    str1 == "ABCD"; // true
    
    // 2):通过构造器创建:先在常量池创建 "ABCD"(若常量池已存在 "ABCD",则不再创建),再调用 String 类的构造器在堆空间创建一个 String 对象并引用常量池中的 "ABCD",str2 再引用 String 对象
    String str2 = new String("ABCD");
    str2 == "ABCD"; // false
    str2.intern() == "ABCD"; // true
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  • 字符串非空:引用不能为空(null)且内容不能为空("")

    // 判断字符串非空
    public static boolean hasLength(String str) {
        return str != null && str.trim().length() > 0;
        // return str != null && !"".equals(str.trim());
        // return str != null && !str.trim().isEmpty();
    }
    
    1
    2
    3
    4
    5
    6
  • 从 Java 7 开始,switch 也支持操作 String 类型的字符串对象
    底层使用了 hashCode() 来进行 switch,然后通过 equals() 方法进行验证

  • 在 Java 中,通过使用 "+" 符号来串联字符串时,实际上底层会转成通过 StringBuilder 实例的 append() 方法来实现

  • 字符串常量池是一个固定容量的 Map,如果容量太小(默认 -XX:StringTableSize=60013)、字符串太多时,每一个桶中的字符串数量会非常多,搜索起来会很慢

# 常用方法

  1. 常用构造器
    String(byte[] bytes, int offset, int length, String charsetName):使用指定的字符集将 byte[] 数组从 offset 开始、长度为 length 的子数组解码成字符串(构造器声明上抛出了异常)
    String(char[] value, int offset, int count):将字符数组从 offset 开始、长度为 count 的字符元素连缀成字符串
  2. String 转数组
    byte[] getBytes():使用平台的默认字符集将此 String 编码为 byte 数组
    byte[] getBytes(String charsetName):使用指定的字符集将此 String 编码为 byte 数组(方法声明上抛出了异常)
    char[] toCharArray():将字符串转换为 char 数组
  3. 获取字符串信息(StringBuilder 类中也有)
    int length():返回该字符串的长度
    char charAt(int index):返回指定索引处的 char 值
    int indexOf(String str):返回子串在该字符串中第一次出现处的索引
    int lastIndexOf(String str):返回子串在该字符串中最后一次出现处的索引
    boolean isEmpty():当且仅当 length() 为 0 时返回 true
  4. 字符串比较判断
    boolean equals(Object anObject):字符串比较,当指定对象不为 null,且类型为 String,字符序列相等时,结果才为 true
    boolean equalsIgnoreCase(String anotherString):字符串比较,忽略大小写
    boolean contentEquals(CharSequence cs):字符串比较,当它们包含的字符序列相同时返回 true
  5. 字符串大小写转换
    String toUpperCase():把当前字符串转换为大写
    String toLowerCase():把当前字符串转换为小写
  6. 其它
    boolean startsWith(String prefix):判断此字符串是否以指定的前缀开始
    boolean endsWith(String suffix):判断此字符串是否以指定的后缀结束
    String substring(int start, int end):返回该字符串的一个子串 [start, end)(StringBuilder 类中也有)
    String trim():返回移除了前导和尾部空白的子串
    String replace(CharSequence target, CharSequence replacement):将该字符串中所有的 target 子串替换成 replacement
    intern():如果在常量池中已经包含一个等于此 String 对象的字符串,则返回在常量池中的引用;否则,将此 String 对象添加到常量池中,再返回在常量池中的引用(jdk1.7 将字符串常量池从方法区中移到了中,所以如果在常量池找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用
    IntStream chars()List<Character> characterList = "StringToList".chars().mapToObj(c -> (char) c).collect(Collectors.toList());
  7. 类方法
    String valueOf(X x):将基本类型值转换为字符串
    String valueOf(Object obj)如果参数为 null,则字符串等于 "null";否则,返回 obj.toString() 的值
    String format(String format, Object... args):使用指定的格式字符串(包含格式说明符,语法%[argument_index$][flags][width][.precision]conversion,如 %s%1$tY-%<tm-%<td %<tH:%<tM:%<tS)和参数返回一个格式化字符串
    String join(CharSequence delimiter, CharSequence... elements):用一个分隔符将多个字符串连接起来
    String join(CharSequence delimiter, Iterable<? extends CharSequence> elements):用一个分隔符将集合中的字符串元素连接起来

# StringBuffer 和 StringBuilder

  • StringBuffer 和 StringBuilder 都可以创建字符序列可变的字符串对象,功能方法相同的,都是最终类,但 value 没有使用 final 修饰
  • StringBuffer 类使用了 synchronized 修饰符,线程安全;
  • StringBuilder 类没有使用 synchronized 修饰符,性能更高,但线程不安全(建议使用 StringBuilder
  • 两个属性:length(字符序列的长度)和 capacity(容量)
  • 注意:StringBuffer 和 StringBuilder 都没有重写 equal() 方法、hashCode() 方法
  1. 对象的创建
    new StringBuilder():创建一个不带字符,初始容量为 16 个字符的字符串缓冲区 new char[16]
    new StringBuilder(int capacity):创建一个不带字符,指定初始容量的字符串缓冲区
    new StringBuilder(String str):构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容

  2. 常用方法
    StringBuilder append(Object obj)追加任意类型数据,return this; 追加 "null"
    StringBuilder deleteCharAt(int index)删除字符串中指定位置的字符
    StringBuilder insert(int offset, Object obj):将 Object 参数的字符串表示形式插入此字符序列中
    StringBuilder reverse():字符序列反转
    String toString():返回此序列中数据的字符串表示形式
    void setLength(int newLength):设置字符序列的长度(如果 newLength 参数小于当前长度,则长度将更改为指定的长度,如果 newLength 参数大于或等于当前长度,则将追加有效的 null 字符,使长度满足 newLength 参数)

# StringJoiner

  • 构造器
    StringJoiner(CharSequence delimiter)
    StringJoiner(CharSequence delimiter, CharSequence prefix, CharSequence suffix)

  • 实例方法
    StringJoiner add(CharSequence newElement):注意如果 newElement 是 null,则添加 "null"
    int length()
    StringJoiner merge(StringJoiner other)
    StringJoiner setEmptyValue(CharSequence emptyValue)
    String toString():等于 toString().length()

# 数学

# Math

  • 基本数学运算,如初等指数、对数、平方根和三角函数等,随机数(都是类方法)
    1. 常量字段:E、PI
    2. double random():返回带正号的 double 值(伪随机数),[0.0, 1.0)
    3. int min(int a, int b):返回两个数的较小值
    4. int max(int a, int b):返回两个数的较大值
    5. int toIntExact(long value):将 long 值转换为 int 值
    6. int addExact(int x, int y)
    7. int subtractExact(int x, int y)
    8. int multiplyExact(int x, int y)
    9. long round(double a)int round(float a):执行标准舍入,将数值四舍五入为最接近的整数
    10. double ceil(double a):执行向上舍入,将数值向上舍入为最接近的 double 值
    11. double floor(double a):执行向下舍入,将数值向下舍入为最接近的 double 值

# BigDecimal

  • java.math 包中

  • 不可变的、任意精度的有符号十进制数,用于处理金钱和精度要求高的数据

  • BigDecimal 有 scale 和 precision 的概念,scale 表示小数点右边的位数,而 precision 表示精度,即有效数字的长度

  • 全局静态常量:ZERO、ONE、TEN、ROUND_HALF_UP(对应于 RoundingMode.HALF_UP)

  • 常用实例方法

    1. BigDecimal divide(BigDecimal divisor):返回一个 BigDecimal,其值为 (this / divisor),如果无法表示准确的商值,则抛出 ArithmeticException
    2. BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode):返回一个 BigDecimal,其值为 (this / divisor),要保留的小数位数 scale,舍入模式 roundingMode(如 RoundingMode.HALF_UP 表示四舍五入)
    3. BigDecimal setScale(int newScale, RoundingMode roundingMode), BigDecimal setScale(int newScale, int roundingMode):返回一个 BigDecimal,要保留的小数位数 newScale,舍入模式 roundingMode
    4. BigDecimal stripTrailingZeros():返回的 BigDecimal,其数值上等于此小数,但从该表示形式移除所有尾部零
  • 注意事项

    1. 使用 BigDecimal 表示和计算浮点数,且务必使用字符串的构造方法来初始化 BigDecimal
    2. 浮点数的字符串格式化也要通过 BigDecimal 进行(使用其 setScale 方法指定舍入的位数和方式)
    3. 只比较 BigDecimal 的 value,应使用 compareTo 方法(使用 equals 方法会同时比较 value 和 scale)
// double 准确转换 BigDecimal
BigDecimal dividend1 = new BigDecimal(Double.toString(0.9));
BigDecimal dividend2 = BigDecimal.valueOf(0.9);

// float 准确转换 BigDecimal
new BigDecimal(Float.toString(0.9f));
// BigDecimal.valueOf(0.9f); // 不能准确转换
// 注意:val 不能为 float,否则 float 转 double 时会丢失精度
// valueOf 方法内部执行了 Double 的 toString,而 Double 的 toString 按 double 的实际能表达的精度对尾数进行了截断
public static BigDecimal valueOf(double val) {
    return new BigDecimal(Double.toString(val));
}

// 比较大小
dividend1.compareTo(dividend2); // 结果为 0 时表示相等
new BigDecimal("1.0").equals(new BigDecimal("1")); // false
new BigDecimal("1.0").compareTo(new BigDecimal("1")) == 0; // true

// String 准确转换 BigDecimal,可能会抛出 NumberFormatException
BigDecimal divisor = new BigDecimal("0.7");

// 如果无法表示准确的商值,则抛出 ArithmeticException
// BigDecimal result = dividend1.divide(divisor);
BigDecimal result = dividend1.divide(divisor, 2, RoundingMode.HALF_UP); // 1.29
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# BigInteger

  • java.math 包中
  • 不可变的、任意精度的整数

数值运算时要小心溢出问题,溢出后不会出现异常,但得到的计算结果是完全错误的,应考虑使用 Math.xxxExact 方法来进行运算,在溢出时能抛出异常,或者对于可能会出现溢出的大数运算使用 BigInteger

# 随机数

# Random

  • 使用种子创建随机数生成器,生成下一个伪随机数
  • 构造器
    1. Random():使用默认的种子创建一个随机数生成器对象(以当前系统时间作为种子)
    2. Random(long seed)
  • 实例方法
    int nextInt():返回一个伪随机整数,[0, int 最大值),类似还有返回 long、float [0.0, 1.0)、double [0.0, 1.0)、boolean 的方法
    int nextInt(int n):返回一个伪随机数,[0, n)
    IntStream ints(int randomNumberOrigin, int randomNumberBound)
    IntStream ints(long streamSize, int randomNumberOrigin, int randomNumberBound):返回一个流,生成 streamSize 个 [randomNumberOrigin, randomNumberBound) 范围内的 int 值

# ThreadLocalRandom

  • Java 7 新增的 Random 的子类,相对于 Random 可以减少多线程资源竞争,保证了线程的安全性

  • 其构造器是缺省访问权限

  • 类方法
    ThreadLocalRandom current()获取当前类对象

  • 实例方法
    int nextInt(int least, int bound):返回一个伪随机数,[least, bound),类似还有返回 long、double 的方法

# UUID

  • 结合机器的网卡、当地时间、一个随即数来生成 UUID(通用唯一标识符),UUID 是一个 128 位的值,一般用 16 进制表示

  • 类方法
    UUID randomUUID()获取 UUID 对象

  • 实例方法
    String toString():返回表示此 UUID 的 String 对象,格式为:(8 个字符)-(4 个字符)-(4 个字符)-(4 个字符)-(12 个字符),字符范围:0~9,a~f

# 日期、时间

# Date

  • java.util 包中,表示特定的瞬间,精确到毫秒
  • Date 中保存的是 UTC 时间,UTC 是以原子钟为基础的统一时间,不以太阳参照计时,并无时区划分
  • 构造器:Date()、Date(long date)
  • 类方法
    Date from(Instant instant):从 Instant 对象获取一个 Date 的实例
  • 实例方法
    1. String toLocaleString():返回此日期的字符串表示形式(使用默认时区、语言环境约定)(已过时)
    2. long getTime():返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此对象表示的毫秒数
    3. boolean equals(Object obj):比较两个日期的相等性
    4. boolean after(Date when):判断此日期是否在指定日期之后
    5. boolean before(Date when):判断此日期是否在指定日期之前
  • 注意:new Date(new Date().toString())new Date() 表示的时间可能不同,因为 CST 可以为 4 个不同时区的缩写
  • jdk1.8 的应用可以使用 Instant(代表一个具体的时刻)代替 Date

# Calendar(抽象类)

  • java.util 包中

  • int 类型的静态常量:YEAR, MONTH(第一个月为 0), DAY_OF_MONTH 或 DATE, DAY_OF_WEEK, HOUR_OF_DAY, MINUTE, SECOND

  • 类方法
    Calendar getInstance():基于当前时间,使用默认时区和语言环境获取一个 Calendar 对象

  • 实例方法

    1. int get(int field):返回指定日历字段的值
    2. void set(int field, int value):将给定的日历字段设置为给定值
    3. void add(int field, int amount):根据日历的规则,为指定的日历字段添加或减去指定的时间量
    4. Date getTime():返回一个表示此 Calendar 时间值的 Date 对象
    5. void setTime(Date date):使用给定的 Date 设置此 Calendar 的时间
    6. boolean after(Object when):判断此 Calendar 表示的时间是否在指定 Object 表示的时间之后
    7. boolean before(Object when):判断此 Calendar 表示的时间是否在指定 Object 表示的时间之前
    8. boolean equals(Object obj)
  • jdk1.8 的应用可以使用 LocalDateTime(代表不带时区的日期、时间)代替 Calendar

# 格式化

  • java.text 包
  • Format,java.text 包中,一个用于格式化语言环境敏感的信息(如日期、消息和数字)的抽象基类
  • 已知子类:DateFormat、MessageFormat、NumberFormat

# MessageFormat

  • 线程安全
  • 类方法:String format(String pattern , Object... arguments):返回后面的多个参数值填充前面的 pattern 字符串,其中 pattern 是一个带占位符的字符串

# NumberFormat(抽象类)

  • 格式化(format)和解析(parse)数值
  • 线程不安全
通用数值格式器 整数格式器 百分数格式器 货币格式器
获取 NumberFormat
实例的类方法
getInstance()
getNumberInstance()
getIntegerInstance() getPercentInstance() getCurrencyInstance()
groupingUsed true true true true
maximumIntegerDigits 2147483647 2147483647 2147483647 2147483647
minimumIntegerDigits 1 1 1 1
maximumFractionDigits 3 0 0 2
minimumFractionDigits 0 0 0 2
parseIntegerOnly false true false false
RoundingMode HALF_EVEN HALF_EVEN HALF_EVEN HALF_EVEN
Currency 当前默认语言环境 当前默认语言环境 当前默认语言环境 当前默认语言环境

默认获取的是当前默认语言环境的数字格式器,也可以在调用获取方法时传入指定的 Locale,如 Locale.CHINA

  • 实例方法: String format(double number)、String format(long number):格式化数值
    void setGroupingUsed(boolean newValue):设置此格式中是否使用分组
    void setMaximumIntegerDigits(int newValue):设置数的整数部分所允许的最大位数
    void setMinimumIntegerDigits(int newValue):设置数的整数部分所允许的最小位数
    void setMaximumFractionDigits(int newValue):设置数的小数部分所允许的最大位数
    void setMinimumFractionDigits(int newValue):设置数的小数部分所允许的最小位数
    void setParseIntegerOnly(boolean value):设置数是否应该仅作为整数进行解析
    void setRoundingMode(RoundingMode roundingMode):设置在此 NumberFormat 中使用的 RoundingMode
    void setCurrency(Currency currency): 设置格式化货币值时此数值格式使用的货币

# DateFormat / SimpleDateFormat

  • 格式化(format)和解析(parse)日期或时间
  • jdk1.8 的应用可以使用 DateTimeFormatter(时间格式器)代替 DateFormat、SimpleDateFormat

# DateFormat(抽象类)

  • int 类型的全局静态常量:SHORT、MEDIUM、LONG、FULL(分别表示四种样式)

  • 类方法:

    1. DateFormat getInstance()获取使用 SHORT 风格的默认日期格式器
    2. DateFormat getDateTimeInstance(int dateStyle, int timeStyle)获取日期使用 dateStyle 风格、时间使用 timeStyle 风格的日期/时间格式器
  • 实例方法

    1. String format(Date date):将 Date 格式化为日期/时间字符串
    2. Date parse(String source):解析字符串的文本,生成 Date(该方法声明抛出了 ParseException 异常)

# SimpleDateFormat

  • DateFormat 的子类,支持自定义日期-时间格式
  • SimpleDateFormat、DateFormat 都是线程不安全的类
  • SimpleDateFormat 继承 DateFormat 类,DateFormat 类中维护了一个 Calendar 实例,Calendar 实例被用来计算日期-时间字段和时间实例,既被用于 format 方法也被用于 parse 方法(The Calendar instance used for calculating the date-time fields and the instant of time. This field is used for both formatting and parsing.)

日期和时间模式字母

  • 构造器:SimpleDateFormat()、SimpleDateFormat(String pattern)

  • 实例方法

    1. void applyPattern(String pattern):将给定模式字符串应用于此日期格式,如 "yyyy-MM-dd E HH:mm:ss" 2017-10-07 星期六 17:55:54
    2. 从类 DateFormat 继承的方法:String format(Date date), Date parse(String source)

# 正则表达式 (opens new window)

  • 正则表达式(regex)是一个强大的字符串处理工具,主要用于匹配判断、分割操作、替换操作(网络爬虫)等
  • 教程 (opens new window)
  • 在正则表达式中有特殊含义的符号 \ + * ^ . ? $ | ( ) [ ] { }
  • 由于 Java 字符串中反斜杠本身需要转义,因此两个反斜杠(\)实际上相当于一个(前一个用于转义)
// Java 的转义字符包括
\b  \t  \n  \f  \r  \"  \'  \\
1
2

正则表达式

# String 类中的相关方法

  1. boolean matches(String regex):判断该字符串是否匹配给定的正则表达式,如手机号码:"^[1][3456789][0-9]{9}$""^1[3-9]\\d{9}$"(第一个反斜线表示转义)
  2. String replaceAll(String regex, String replacement):将该字符串中所有匹配 regex 的子串替换成 replacement
  3. String[] split(String regex):以 regex 作为分隔符(有特殊含义的符号需转义),把该字符串分割成多个子串,结尾空字符串会被丢弃

正则表达式匹配效率较低,尽量使用字符串匹配操作,即 org.apache.commons.lang3.StringUtils#replace()org.apache.commons.lang3.StringUtils#split()

# Pattern 和 Matcher

// 将一个正则表达式编译成 Pattern 对象(线程安全,不要在方法体内定义)
Pattern p = Pattern.compile("a*b");
// 使用 Pattern 对象执行匹配,创建 Matcher 对象(线程不安全)
Matcher m = p.matcher("aaaaab");
boolean b = m.matches(); // 返回 true

// 等效于上面的三条语句
boolean b = Pattern.matches("a*b", "aaaaab");

Pattern p = Pattern.compile("cat");
Matcher m = p.matcher("one cat two cats in the yard");
StringBuffer sb = new StringBuffer();
while (m.find()) {
    m.appendReplacement(sb, "dog");
}
m.appendTail(sb);
System.out.println(sb.toString()); // one dog two dogs in the yard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Updated at: 2021-11-11 20:59:49