Java编程思想之字符串
2017-08-15 16:49
429 查看
1 不可变String
String 对象是不可变的。String类中每一个看起来会修改String值的方法,实际上都是创建了一个全新的String对象,以包含修改后的字符串内容。而最初的String对象则丝毫未动。public class Immutable{ public static String upcase(String s){ return s.toUpperCase(); } public static void main(String[] args){ String q = "hello"; System.out.println(q); String qq = upcase(q); System.out.println(qq); System.out.println(q); } } /* 运行结果: hello HELLO hello */
当把q传给upcase()方法时,实际传递的是引用的一个拷贝。其实,每当把String对象作为方法的参数时,都会复制一份引用,而该引用所指的对象其实一直待在单一的物理位置上,从未动过。
upcase()返回的引用已经指向了一个新的对象,而原本的q则还在原地。
2 重载“+”与StringBuilder
* String对象具有只读特性,所以指向它的任何引用都不可能改变它的值。*不可变性会带来一定的效率问题。为String对象重载的“+”操作符就是一个例子。重载的意思是,一个操作符在应用于特定的类时,被赋予了特殊的意义(用于String的“+”与“+=”是Java中仅有的两个重载过的操作符)。
public class Concatenation{ public static void main(String[] args){ String mm = "mm"; String s = "1haha"+mm+"2ss"+55; System.out.println(s); } } /* *执行javap -c Concatenation 反编译以上代码 生成JVM字节码 */ /* public class Concatenation { public Concatenation(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: ldc #2 // String mm 2: astore_1 3: new #3 // class java/lang/StringBuilder 6: dup 7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V 10: ldc #5 // String 1haha 12: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)L 15: aload_1 16: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)L 19: ldc #7 // String 2ss 21: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)L 24: bipush 55 26: invokevirtual #8 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringB 29: invokevirtual #9 // Method java/lang/StringBuilder.toString:()Ljava/lang/String 32: astore_2 33: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream; 36: aload_2 37: invokevirtual #11 // Metho b9f5 d java/io/PrintStream.println:(Ljava/lang/String;)V 40: return } */
编译器自动引入了StringBuilder类。因为它更高效。显示地创建StringBuilder还允许你预先为其指定大小,可以避免多次重新分配缓冲。
StringBuilder re = new StringBuilder()
当你为一个类编写toString()方法时,如果字符串操作比较简单,那就可以信赖编译器,它为你合理地构造最终的字符串结果(使用“+”)。但是,如果你要在toString() 方法中使用循环,那么最好自己创建一个StringBuilder对象,用它来构造最终的结果。
3 无意识的递归
public class InfiniteRecursion{ public String toString(){ return "address:"+this+"\n"; //打印出对象的内存地址 出现异常 // return super.toString(); 应该使用Object.toString()方法打印对象的地址。 } }
这里发生了自动类型转换,由InfiniteRecursion类型转换成String类型。因为编译器看到一个String对象后面跟着一个”+“,而再后面的对象不是String,于是编译器试着将this转换成一个String——通过调用this上的toString()方法。于是就发生了递归调用(无法正常结束)。
4 String上的操作
//部分方法尝试,其余的大多数方法都能够通过名字判断其用意 public class StringMethodTest{ public static void main(String[] args){ String s = " hc hc "; char[] aChars = new char[10]; print("展示各类方法结果:"); print("trim: "+s.trim()); print("getChars:"); s.getChars(1,5,aChars,2); for(char aa : aChars){ System.out.print(aa); } System.out.println(); print("regionMatches: "+s.regionMatches(1," ha",0,2)); //部分匹配 该String的索引偏移量,另一个String及其索引偏移量,要比较的长度 print("replace: " +s.replace('c','h')); print("valueOf: "+s.valueOf(3)); print("intern: "+s.intern()); } public static void print(String s){ System.out.println(s); } } /*展示各类方法结果: trim: hc hc //只能删除两端的空白字符 getChars: aa hc aaaa //自动填充a regionMatches: true //部分匹配(应注意空白字符不能被忽略) replace: hh hh valueOf: 3 //返回一个表示参数内容的String intern: hc hc */
当需要改变字符串的内容时,String类的方法都会返回一个新的String对象。同时,如果内容没有发生改变,String的方法只是返回指向原对象的引用而已。这可以节约存储空间以及避免额外的开销。
5 格式化输出
5.1 printf()
printf("Row 1: [%d %f]\n",x,y); //使用特殊的占位符(称为格式修饰符)来表示数据将来的位置,还可插入格式化字符串的参数。
在插入数据时,如果想要控制空格与对齐,需要更精细的格式修饰符 ,以下是其抽象语法:
%[argument_index$][flags][width][.precision]conversion width 域的最小尺寸 默认数据是右对齐,可以是用"-"来改变对齐方向。 precision 最大尺寸 只能用于String和浮点数(默认是六位小数)。 举例:"%-10.5s" 占10个空格的位置,左对齐,只保留5个字符 String String.format("%2$d + %5d",1,2); 返回的是2+ 1。
5.2 System.out.format()和String.format()
System.out.format()与printf()是等价的。String.format()返回一个String对象,内部也是创建了一个Formatter对象。5.3 Formatter类
在Java中,所有新的格式化功能都由java.util.Formatter类处理。可以将Formatter看作是一个翻译器,它将你的格式化字符串与数据翻译成需要的结果。当你创建一个Formatter对象的时候,需要向构造器传递一些信息,告诉它最终的结果将向哪里输出:import java.util.*; //ellipsis Formatter f = new Formatter(System.out); f.format() //用法同上
类型转换字符: | |
---|---|
d 整数型(十进制) | e 浮点数(科学计数) |
c Unicode字符 | x 整数(十六进制) |
b Boolean值 | h 散列码(十六进制) |
s String | % 字符”%” |
f 浮点数(十进制) |
相关文章推荐
- Java编程思想_字符串
- JAVA编程思想---字符串操作
- java编程思想笔记--字符串部分一
- Java 编程思想13章--字符串
- 13字符串-Java编程思想
- JAVA编程思想学习总结:第十三章字符串
- java编程思想-字符串
- JAVA编程思想-第十三章 字符串
- 《Java 编程思想》004 switch对字符串支持的引申思考
- Java编程思想笔记——第十三章 字符串
- java编程思想笔记--字符串部分二
- Java编程思想-13字符串
- 2014年2月8日 java编程思想 String字符串学习 面试题目回顾
- 《Java 编程思想》第13章 字符串 笔记
- 读书笔记 JAVA编程思想 第13章 字符串
- 《Java 编程思想》--第十三章:字符串
- Java编程思想 第七章读书笔记
- java 编程思想第六章个人总结---访问权限控制
- java编程思想阅读笔记(六)异常处理
- java编程思想-第15章-泛型