第十三章 字符串

[color=blue]不可变String[/color]
public class Immutable {
public static String upcase(String s) {
return s.toUpperCase();
}

public static void main(String[] args) {
String q = "howdy";
System.out.println(q);
String qq = upcase(q);
System.out.println(q);
System.out.println(qq);
}
}
Output:
howdy
howdy
HOWDY

[color=red]当把q传给upcase方法时,实际传递的是引用的一个拷贝。[/color]其实,每当把String对象作为方法的参数时,都会复制一份引用,而该引用所指的对象其实一直待在单一的物理位置上,从未动过。
回到upcase定义,传入其中的引用有了名字s,只有在upcase运行的时候,局部引用s才存在。一旦upcase结束,s就消失了。当然了,upcase的返回值,其实只是最终结果的引用和s不是一个引用。这足以说明,upcase返回的引用已经指向了一个新的对象,而原本的q则还在原地。
难道你真的希望改变其参数吗?对与一个方法而言,参数时为该方法提供信息的,而不是想让该方法改变自己的。

重载“+”与StringBuilder

String s = “abf” + “sadf” + “da” + 47;

调用javap –c Concatenation
看输出代码,我们可以得到:
编译器自动引入了java.lang.StringBuilder类。虽然我们在源代码中并没有使用StringBuilder类,但是编译器却自作主张地使用了它,因为它更高效。
在这个例子中,编译器创建了一个StringBuilder对象,用以构造最终的String,并为每个字符串调用一次StringBuilder的append方法,总计4次。最后调用toString生成结果。并存为s。
现在,也许你会觉得可以随意使用String对象,反正编译器会为你自动地优化性能。但是看下面两段代码:
public class Immutable {
public static String upcase(String[] fields) {
String result;
for(int i=0; i<10; i++) {
result += fields[i];
}
return result;
}

public static void main(String[] args) {
StringBuilder result = new StringBuilder();
for(int i=0; i<10; i++) {
result.append(fields[i]);
}
result.toString();
}
}


第一个每一次循环内部都会生成一个StringBuilder对象,但是最后这个代码只有一个。如果你要在toString方法中使用循环,那么最好自己创建一个StringBuilder对象,用它来构造最终的结果。

如果你想走捷径,例如append(a + “:” + b)那编译器就会掉入陷阱,从而为你另外创建一个StringBuilder对象来处理括号内的字符串操作。


如果你拿不准该用哪种方式,随时都可以用javap来分析你的程序。

StringBuilder提供了丰富而全面的方法,包括insert replace substring甚至reverse,但是最常用的还是append和toString还有delete方法。

Stringbuilder是java SE5引入的,在这之前java用的是StringBuffer。后者是线程安全的,因此开销也会大些。

[color=blue]格式化输出[/color]
public class SimpleFormat {
public static void main(String[] args) {
int x = 5;
double y = 5.332466;
System.out.println("Row 1: [" + x + " " + y + "]");
System.out.format("Row 1: [%d %f]\n", x, y);
System.out.printf("Row 1: [%d %f]\n", x, y);
}
}
Output:
Row 1: [5 5.332466]
Row 1: [5 5.332466]
Row 1: [5 5.332466]


[color=blue]Formatter类[/color]

在java中,所有新的格式化功能都由java.util.Formatter类处理。可以将Formatter看作一个翻译器,它将你的格式化字符串与数据翻译成需要的结果。当你创建一个Formatter对象的时候,需要向其构造器传递一些信息,告诉它最终的结果将向哪里输出:
import java.io.PrintStream;
import java.util.Formatter;

public class Turtle {
private String name;
private Formatter f;
public Turtle(String name, Formatter f) {
this.name = name;
this.f = f;
}
public void move(int x, int y) {
f.format("%s the turtle is at (%d,%d)\n", name, x, y);
}
public static void main(String[] args) {
PrintStream outAlias = System.out;
Turtle tommy = new Turtle("Tommy", new Formatter(System.out));
Turtle terry = new Turtle("terry", new Formatter(outAlias));
tommy.move(0, 0);
terry.move(4, 8);
}
}
Output:
Tommy the turtle is at (0,0)
terry the turtle is at (4,8)


[color=blue]格式化说明符[/color]

在插入数据时,如果想要控制空格与对齐,你需要更精细复杂的格式修饰符。一下是语法:
%[argument_index$][flags][width][.precision]conversion
% - 15 .5
共15位小数5位左对齐。
最常见的应用时控制一个域的最小尺寸,这可以通过指定width来实现。Formatter对象通过在必要时添加空格,来去日报一个域至少达到某个长度。在默认情况下,数据是右对齐,不过可以通过使用“-”标志来改变对齐方向。
与width相对的是precision,它用来指明最大尺寸。Width可以应用于各种类型的数据转换,并且其行为方式都一样。Precision则不然,不是所有类都可以使用,String的时候表示输出字符最大数量,而小数的时候,位数过多则舍入,少了就补零。所以无法应用于整数,如果应用则会发生异常。

[color=blue]Formatter转换[/color]

d 整数型 c Unicode字符
b Boolean值 s String
f 浮点数(十进制) e 浮点数(科学计数)
x整数(十六进制) h散列码(十六进制) % 字符“%”
程序中每个变量都使用了b转型,只要不是null转型都是true,即使是数字0转换结果依然是true。

[color=blue]String.format()[/color]

String.format()放回一个String对象。其实在String.format()内部,它也是创建一个Formatter对象,然后将你传入的参数转给该Formatter。不过,与其自己做这些事情,不如使用便捷的String.format()方法,何况这样的代码更清晰易读。

[color=blue]正则表示式[/color]

应用正则表达式的最简单的途径,就是利用String内建的功能。
public static void main(String[] args) {
System.out.println("-1234".matches("-?\\d+"));
}
Output:
True


String.split()还有一个重载的版本,它允许你限制字符串分割的次数。
String类自带的最后一个正则表达式工具是“替换”。你可以只替换正则表达式第一个匹配的子串,或是替换所有匹配的地方。

public static void main(String[] args) {
System.out.println(s.replaceFirst("f\\w+", "located"));
System.out.println(s.replaceAll("shrubbery|tree|herring", "banana"));
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值