Java编程思想笔记0x04

字符串

不可变String

  • String对象是不可变的。String类中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象。
  • 对于一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己。

重载“+”与StringBuilder

  • 重载:一个操作符在应用于特定的类时,赋予其特定的含义。
  • 在Java中,用于String++=是仅有的两个重载过的操作符,不允许程序员重载任何操作符。
  • Java编译器会自动优化String操作并使用StringBuilder,因为其高效,但是并不是所有的状况都会被优化。因此在需要大量操作String时使用StringBuilder是明智的选择。

无意识递归

  • 如果在toString()方法中使用this指针与其它字符串拼接,试图打印对象的地址,那么会引起无限的递归调用。[因为编译器试图把this指针转换为String类型,而转换的方法就是调用this.toString()。正确的做法是调用父类的toString(),即super.toString()

格式化输出

System.out.format()

  • 类似于C语言中的printf(),接受一个简单的格式化字符串以及一串参数。

Formatter类

  • 创建Formatter对象时需要向构造器中传入输出目标,例如System.out。使用时调用Formatter对象的format()方法。

格式化说明符

  • 抽象语法:%[argument_index$][flags][width][.precision]conversion
  • width:控制一个域的最小尺寸,在有必要时添加空格,来确保一个域至少达到某个长度。可以用于各种类型的数据转换。默认情况下数据是右对齐,可以使用-来改变对齐方向。
  • precision:指明数据的最大尺寸。不能用于所有的数据类型转换,例如整数类型,并且应用于不同的数据类型转换时意义也不同。应用于String时表示打印String时输出的字符的最大数量;应用于浮点数时,表示小数部分要显示的位数(默认是6位),多则舍入,少则补0。

Formatter转换

  • 常用的类型转换:
类型转换字符 含义
d 整数型(十进制)
c Unicode字符
b Boolean值
s String
f 浮点数(十进制)
e 浮点数(科学计数)
x 整数(十六进制)
h 散列码(十六进制)
% 字符”%”
  • 关于b转换,对于boolean基本类型和Boolean对象,其转换结果就是truefalse;对于其它类型的参数,只要其不为null,那么转换结果就是true,即使是数字0,转换结果依然是true

正则表达式

基本构造

字符 含义
B 指定字符B
\xhh 十六进制值为0xhh的字符
\uhhhh 十六进制表示为0xhhhh的Unicode字符
\t 制表符Tab
\n 换行符
\r 回车
\f 换页
\e 转义(Escape)
字符类 含义
. 任意字符
[abc] 包含a、b、c的任何字符,同 a|b|c
[^abc] 除了a、b、c的任何字符(否定)
[a-zA-Z] 从a到z或从A到Z的任何字符
\s 空白符(空格、Tab、换行、换页和回车)
\S 非空白符
\d 数字,同[0-9]
\D 非数字,[^0-9]
\w 词字符,[a-zA-Z0-9]
\W 非词字符,[^\w]
逻辑操作符 含义
XY Y跟在X后面
X|Y X或Y
(X) 捕获组,可以在表达式中使用\i来引用第i个捕获
边界匹配符 含义
^ 一行的开始
$ 一行的结束
\b 词的边界
\B 非词的边界
\G 前一个匹配的结束

量词

  • 量词描述了一个模式吸收输入文本的方式
  • 贪婪型:一次性地读入整个字符串,如果无法完成匹配就去掉最右边的一个字符再匹配,直到找到匹配的字符串或字符串的长度为0为止。它的宗旨是读尽可能多的字符,所以当读到第一个匹配时就立刻返回。
  • 厌恶型:立刻进入匹配,如果无法匹配则多读一个字符串,直到匹配成功或者字符串读完。它尽量减少了匹配到的字符串,但同样读到第一个匹配的就返回。
  • 占有型:仅匹配一次,失败不会再次尝试。

Pattern和Matcher

  • 正则表达式对象:位于java.util.regex包中,使用Pattern.compile()编译正则表达式,并返回一个Pattern对象。使用Pattern对象的matcher()方法检索一个字符串,会得到一个Matcher对象。

  • Pattern对象的split()方法可以从匹配了正则表达式的地方分割输入的字符串,返回分割后的子字符串String数组。

  • Matcher对象的find()方法可用来在CharSequence中查找多个匹配

  • 组:是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为0便是整个正则表达式,组号1表示第一对括号括起来的组。

  • Matcher对象中有许多关于组的方法:

方法名 用途
int groupCount() 返回Matcher对象中组数,不包含第0组
String group() 返回前一次匹配的第0组
String group(int i) 返回前一次匹配的指定组号,如果匹配成功但是指定的组没有匹配输入字符串的任何部分则返回null
int start(int group) 返回前一次匹配操作中寻找到的组的起始索引
int end(int group) 返回前一次匹配操作中寻找到的组的最后一个字符索引加1的值

替换

方法名 用途
String replaceFirst(String replacement) replacement替换掉第一个匹配成功的部分
String replaceAll(String replacement) replacement替换所有匹配成功的部分
Matcher appendReplacement(StringBuffer sb, String replacement) 1. 先将不匹配的地方放入sb中,即从上次读取的位置开始,到本次start() - 1;2. 将replacement放入sb中;3. 将读取位置改为end()
StringBuffer appendTail(StringBuffer sb) 在多次使用appendReplacement()方法后,使用此方法将把剩余部分的字符串直接放入sb

reset()

  • reset()可以将现有的Matcher对象应用于一个新的字符序列。

扫描输入

Scanner定界符

  • 默认情况下,Scanner对象使用空白字符对输入进行分词。使用Scanner对象的useDelimiter()并输入正则表达式作为参数可以修改成自定义的定界符。

用正则表达式扫描

  • Scanner对象的hasNext()next()方法都支持输入一个Pattern对象,找到下一个匹配该模式的部分,调用match()就能获得匹配结果。如果正则表达式中有定界符,将永远不会匹配成功。
Author: SinLapis
Link: http://sinlapis.github.io/2019/06/30/Java编程思想笔记0x04/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.