1. 不可变String

String对象是不可变的,String类中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,例如:

public class Immutable {
  public static String upcase(String s) {
    return s.toUpperCase();
  }
  public static void main(String[] args) {
    String str1 = "String1";
    String str2 = upcase(str1);
    System.out.println(str1);
    System.out.println(str2);
  }
}

当把str1传给upcase()方法时,实际传递的是引用的一个拷贝。每当把String对象作为方法的参数时,都会复制一份引用。可以给一个String对象加任意多的别名,指向它的任何引用都不可能改变它的值。用于String的"+"与"+="是Java中仅有的两个重载过的操作符,而Java并不允许程序员重载任何操作符。操作符"+"可以用来连接String,例如:

String mango = "mango";
String s = "abc" + mango + "def" + 47;
System.out.println(s);


2. String操作

以下是String对象具备的一些基本方法:

方法
参数应用
length()

String中字符的个数
charAt()Int索引取得String索引位置上的char
getChars(), getBytes()复制部分起点和终点索引,目标数组,目标数组起始索引复制char或byte到目标数组
toCharArray()
生成一个char[]
equals(), equalsIgnoreCase()进行比较的String比较两个String内容是否相同
compareTo()进行比较的String按词典顺序比较String内容
contains()要搜索的CharSequenceString对象是否包含参数内容
contentEquals()进行比较的CharSequence或StringBufferString是否与参数内容完全一致
equalsIgnoreCase()进行比较的String忽略大小写比较内容
regionMatcher()该String的索引偏移量,另一个String及索引偏移量,比较长度所比较区域是否相等
startsWith()可能的起始StringString是否以此参数起始
endsWith()可能的后缀StringString是否以此参数做后缀
indexOf(), lastIndexOf()
char; char与起始索引; String; String与起始索引
String是否包含参数
substring()起始索引,终点坐标返回参数指定的新子字符串
concat()
要连接的String返回新的连接后的String对象
replace()要替换掉的字符,用来进行替换的新字符返回替换后的新String对象
toLowerCase toUpperCase()
返回改变大小写的新String对象
trim()
返回删除两端空白新String对象
valueOf()Object; char[]; boolean; char; int; long; float; double返回一个表示参数内容的String
intern()
为每个唯一字符序列生成引用


3. 格式化输出

在Java中,所有新的格式化功能都由java.util.Formatter类处理,它将格式化字符串与数据转译成需要的结果。当创建一个Formatter对象的时候,需要向其构造器传递一些信息,例如:

public class Test {
  private String s;
  private Formatter f;
  public Test(String s, Formatter f) {
    this.s = s;
    this.f = f;
  }
  public void move(int x, int y) {
    f.format("%s at (%d, %d)\n", s, x, y);
  }
  public static void main(String[] args) {
    Test t = new Test("Point", new Formatter(System.out));
    t.move(1, 2);
  }
}

所有的格式化文本都将输出到System.out,Formmatter的构造器经过重载可以接受多种输出目的地,不过最常用的还是PrintStream()、OutputStream和File。在插入数据时,如果想要控制空格与对齐,需要更精细复杂的格式修饰符,语法如下:

%[argument_index$][flags][witdh][.precision]conversion

最常见的是控制一个域的最小尺寸,可以通过指定width实现,Formatter对象通过在必要时添加空格,来确保一个域至少达到某个长度,默认是右对齐的,可以通过使用'-'标志来改变对齐方向。与width相对的是precision,它用来指明最大尺寸,在将precision应用于String时,它表示打印String时输出字符的最大数量,而在将precision应用于浮点数时,它表示小数部分要显示出来的位数。

下表包含了最常用的类型转换:





d整数型(十进制)e浮点数(科学计数)
cUnicode字符x整数(十六进制)
bBoolean值h散列码(十六进制)
sString%字符"%"
f浮点数(十进制)


4. 正则表达式

导入java.util.regex包,用static Pattern.compile()方法可以编译正则表达式,它根据String类型的正则表达式生成一个Pattern对象,再把想要检索的字符串传入Pattern对象的matcher()方法,生成一个Matcher对象,例如:

  public static void main(String[] args) {
    for(String arg : args) {
      Pattern p = Pattern.compile(arg);
      Matcher m = p.matcher(args[0]);
      while(m.find()) {
        System.out.println("Match " + m.group() + " at positions "
                           + m.start() + "-" + (m.end() - 1)); 
      }
    }
  }
}

Matcher.find()方法可用来查找多个匹配,find()像迭代器一样前向遍历输入字符串。

组是用括号划分的正则表达式,可以根据组的编号来引用某个组,例如A(B(C))D中有三个组:组0是ABCD,组1是BC,组2是C。Machter对象提供一系列方法用以获取组相关的相信:public int groupCount()返回该匹配器的模式中的分组数目,第0组不包括在内。public String group()返回前一次匹配操作的第0组(整个匹配)。public String group(int i)返回在前一次匹配操作期间指定的组号。

在匹配操作成功之后,start()返回先前匹配的起始位置的索引,而end()返回所匹配的最后字符的索引加一的值。匹配操作失败后,调用start()或end()将会产生IllegalStateException。

Pattern类的compile()方法还有另一个版本,它接受一个标记参数,以调整匹配的行为:

Pattern Pattern.compile(String regex, int flag)

其中的flag来自以下Pattern类中的常量:

编译标记
效果
Pattern.CANON_EQ两个字符当且权当它们的完全规范分解相匹配时,就认为它们是匹配的。
Pattern.CASE_INSENSITIVE(?i)允许模式匹配不必考虑大小写。
Pattern.COMMENTS(?x)忽略空格符,并且以#开始直到行末的注释也会被忽略掉。
Pattern.DOTALL(?s)在这个模式中,表达式"."匹配所有字符,包括行终结符。
Pattern.MULTILINE(?m)在多行模式下,表达式^和$分别匹配一行的开始和结束。^还匹配输入字符串的开始,而$还匹配输入字符串的结尾。
Pattern.UNICODE_CASE(?u)当指定这个标记并开户CASE_INSENSITIVE时,大小写不敏感的匹配将按照与Unicode标准相一致的方式进行。
Pattern.UNIX_LINES(?d)在.、^和$中,只识别行终结符\n。