java中String类的用法

1、不变模式:java

一个字符串对象建立后它的值不能改变。
String str1="hello";//
建立一个对象hello,不会变;
System.out.println(str1);
str1+=" world!";
//两个字符串对象粘粘,系统其实建立了一个新的对象,把Str1的指向改了,指向新的对象;hello//变成了垃圾
System.out.println(str1);
//若是一直这样建立会影响系统的效率;要频繁的改变字符串对象的值就用StringBuffer来描述;
StringBuffer sb=new StringBuffer("[");
sb.append("hehe");
数组

sb.append("]");//append();不会制造垃圾,真正在改sb的值;
System.out.println(sb);
app

2、对象池jvm

首先要明白,Object obj = new Object();测试

obj是对象的引用,它位于栈中, new Object() 才是对象,它位于堆中。ui

能够这样理解obj是拴在氢气球上的绳子,new Object() 是氢气球,咱们经过对象的引用访问对象,就像咱们那着绳子氢气球才不会跑掉。spa

建立一个Stirng对象,主要就有如下两种方式:.net

java 代码线程

  1. String str1 = new String("abc");
  2. Stirng str2 = "abc";

虽然两个语句都是返回一个String对象的引用,可是jvm对二者的处理方式是不同的。对于第一种,jvm会立刻在heap中建立一个String对象,而后将该对象的引用返回给用户。对于第二种,jvm首先会在内部维护的strings pool中经过String equels 方法查找是对象池中是否存放有该String对象,若是有,则返回已有的String对象给用户,而不会在heap中从新建立一个新的String对象;若是对象池中没有该String对象,jvm则在heap中建立新的String对象,将其引用返回给用户,同时将该引用添加至strings pool中。注意:使用第一种方法建立对象时,jvm是不会主动把该对象放到strings pool里面的,除非程序调用 Stringintern方法。看下面的例子:设计

java 代码

  1. String str1 = new String("abc"); //jvm 在堆上建立一个String对象
  2. //jvm strings pool中找不到值为“abc”的字符串,所以
  3. //在堆上建立一个String对象,并将该对象的引用加入至strings pool
  4. //此时堆上有两个String对象
  5. Stirng str2 = "abc"; //并无建立对象,由于对象池里已经有"abc"
  6. if(str1 == str2){
  7. System.out.println("str1 == str2");
  8. }else{
  9. System.out.println("str1 != str2");
  10. }
  11. //打印结果是 str1 != str2,由于它们是堆上两个不一样的对象
  12. String str3 = "abc";
  13. //此时,jvm发现strings pool中已有“abc”对象了,由于“abc”equels “abc”
  14. //所以直接返回str2指向的对象给str3,也就是说str2str3是指向同一个对象的引用
  15. if(str2 == str3){
  16. System.out.println("str2 == str3");
  17. }else{
  18. System.out.println("str2 != str3");
  19. }
  20. //打印结果为 str2 == str3

3、String / StringBuffer / StringBuilder

String类是字符串常量,是不可更改的常量。而StringBuffer是字符串变量,它的对象是能够扩充和修改的。

StringBuffer sb=new StringBuffer("[");//建立StringBuffer对象
sb.append("hehe");//
hehe加入字符串,变成 "[hehe"

sb.append("]");//append();不会制造垃圾,真正在改sb的值;
System.out.println(sb);

String str = sb.toString();//"[hehe]",赋值给一个字符串对象str

StringBuilder,一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用做StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种状况很广泛)。若是可能,建议优先采用该类,由于在大多数实现中,它比 StringBuffer 要快。

StringBuilder sb=new StringBuilder("[");//建立StringBuilder对象
sb.append("hehe");//
hehe加入字符串,变成 "[hehe"

sb.append("]");//append();不会制造垃圾,真正在改sb的值;
System.out.println(sb);

String str = sb.toString();//"[hehe]",赋值给一个字符串对象str

4、String类中经常使用的方法

String 类包括的方法可用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串、建立字符串副本并将全部字符所有转换为大写或小写。不用去记,用到的时候查API,用的多了天然就熟悉了。

java.lang.String

char charAt (int index)

返回index所指定的字符

String concat(String str)

将两字符串链接

boolean endsWith(String str)

测试字符串是否以str结尾

boolean equals(Object obj)

比较两对象

char[] getBytes

将字符串转换成字符数组返回

char[] getBytes(String str)

将指定的字符串转成制服数组返回

boolean startsWith(String str)

测试字符串是否以str开始

int length()

返回字符串的长度

String replace(char old ,char new)

oldnew替代

char[] toCharArray

将字符串转换成字符数组

String toLowerCase()

将字符串内的字符改写成小写

String toUpperCase()

将字符串内的字符改写成大写

String valueOf(Boolean b)

将布尔方法b的内容用字符串表示

String valueOf(char ch)

将字符ch的内容用字符串表示

String valueOf(int index)

将数字index的内容用字符串表示

String valueOf(long l)

将长整数字l的内容用字符串表示

String substring(int1,int2)

取出字符串内第int1位置到int2的字符串

view plaincopy to clipboardprint?

  1. import java.util.Collections;
  2. import java.util.Comparator;
  3. import java.util.LinkedList;
  4. import java.util.List;
  5. public class StringUsage {
  6. // 几个欧不太用的方法。
  7. public static void main(String[] args) {
  8. // 判断字符串首/尾。
  9. String contentS = "test String again. test ";
  10. System.out.println(contentS);
  11. System.out.println("contentS.startsWith(\"test\")\t"
  12. + contentS.startsWith("test"));
  13. System.out.println("contentS.endsWith(\"test\")\t"
  14. + contentS.endsWith("test"));
  15. // 忽略大小写的字符串比较方法。
  16. System.out
  17. .println("contentS.compareToIgnoreCase(contentS.toUpperCase()))\t"
  18. + contentS.compareToIgnoreCase(contentS.toUpperCase()));
  19. // 不区分大小写的字符串比较。
  20. Comparator<String> cmprStr = String.CASE_INSENSITIVE_ORDER;
  21. List<String> lstStr = new LinkedList<String>();
  22. // 准备数据。
  23. lstStr.add("test");
  24. lstStr.add("Test");
  25. lstStr.add("tEst");
  26. lstStr.add("rest");
  27. lstStr.add("sest");
  28. // 不区分大小写的排序。
  29. Collections.sort(lstStr, cmprStr);
  30. System.out.println(lstStr);
  31. // 区分大小写的排序。
  32. Collections.sort(lstStr);
  33. System.out.println(lstStr);
  34. System.out.println("\ntest String.valueOf()");
  35. // valueOf 处理 null 对象的字符串转换。
  36. try {
  37. String ss = null;
  38. System.out.println(ss);
  39. System.out.println(String.valueOf(null)); // 比较奇怪的地方
  40. } catch (RuntimeException e1) {
  41. e1.printStackTrace();
  42. }
  43. BigDecimal db = null;
  44. try {
  45. System.out.println(((BigDecimal)db).toString());
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. }
  49. try {
  50. System.out.println(String.valueOf(db));
  51. } catch (Exception e) {
  52. e.printStackTrace();
  53. }
  54. db = new BigDecimal("100.00");
  55. try {
  56. System.out.println(((BigDecimal)db).toString());
  57. } catch (Exception e) {
  58. e.printStackTrace();
  59. }
  60. }
  61. }

5、SCJP题目

String a="Hello World!";
String b="Hello World!";
a=b? a
b是否相等? 为何?

String a=new String("Hello World!");
String b="Hello World!";
a=b? a
b是否相等 ? 为何?

解释:

1. 首先String不属于8种基本数据类型,String是一个对象。
由于对象的默认值是null,因此String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。

2. new String()
new String(“”)都是申明一个新的空字符串,是空串不是null

3. String str="kvill";

String str=new String (“kvill”);的区别:
在这里,咱们不谈堆,也不谈栈,只先简单引入常量池这个简单的概念。
常量池(constant pool)指的是在编译期被肯定,并被保存在已编译的.class文件中的
一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。
看例1
String s0="kvill";
String s1="kvill";
String s2="kv" + "ill";
System.out.println( s0==s1 );
System.out.println( s0==s2 );
结果为:
true
true
首先,咱们要知道Java会确保一个字符串常量只有一个拷贝。
由于例子中的s0s1中的”kvill”都是字符串常量,它们在编译期就被肯定了,因此
s0==s1
true;而”kv””ill”也都是字符串常量,当一个字符串由多个字符串常量连
接而成时,它本身确定也是字符串常量,因此s2也一样在编译期就被解析为一个字符串常量,因此s2也是常量池中”kvill”的一个引用。因此咱们得出s0==s1==s2;

new String() 建立的字符串不是常量,不能在编译期就肯定,因此new String()
建立的字符串不放入常量池中,它们有本身的地址空间。

看例2
String s0="kvill";
String s1=new String("kvill");
String s2="kv"+ new String("ill");
System.out.println( s0==s1 );
System.out.println( s0==s2 );
System.out.println( s1==s2 );
结果为:
false
false
false
2s0仍是常量池中”kvill”的应用,s1由于没法在编译期肯定,因此是运行时创
建的新对象”kvill”的引用,s2由于有后半部分new String(“ill”)因此也没法在编译
期肯定,因此也是一个新建立对象”kvill”的应用;明白了这些也就知道为什么得出此结果了。

4. String.intern()

再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,而且能够扩充。Stringintern()方法就是扩充常量池的一个方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,若是有,则返回其的引用,若是没有,则在常量池中增长一个Unicode等于str的字符串并返回它的引用;看例3就清楚了。

3
String s0= "kvill";
String s1=new String("kvill");
String s2=new String("kvill");
System.out.println( s0==s1 );
System.out.println( “**********” );
s1.intern();
s2=s2.intern(); //
把常量池中"kvill"的引用赋给s2
System.out.println( s0==s1);
System.out.println( s0==s1.intern() );
System.out.println( s0==s2 );
结果为:
false
**********
false //
虽然执行了s1.intern(),但它的返回值没有赋给s1
true //
说明s1.intern()返回的是常量池中”kvill”的引用
true


最后我再破除一个错误的理解:
有人说,使用String.intern()方法则能够将一个String类的保存到一个全局Strin
g
表中,若是具备相同值的Unicode字符串已经在这个表中,那么该方法返回表中已有字符串的地址,若是在表中没有相同值的字符串,则将本身的地址注册到表中若是我把他说的这个全局的String表理解为常量池的话,他的最后一句话,若是在表中没有相同值的字符串,则将本身的地址注册到表中是错的:

看例4
String s1=new String("kvill");
String s2=s1.intern();
System.out.println( s1==s1.intern() );
System.out.println( s1+" "+s2 );
System.out.println( s2==s1.intern() );
结果:
false
kvill kvill
true
在这个类中咱们没有声名一个"kvill"常量,因此s1.intern()new String("kvill")是不一样的,当咱们调用s1.intern()后就在常量池中新添加了一个"kvill"常量,原来的不在常量池中的"kvill"仍然存在,也就不是将本身的地址注册到常量池中了。
s1==s1.intern()
false说明原来的“kvill”仍然存在;
s2
如今为常量池中“kvill”的地址,因此有s2==s1.intern()true

5.
关于equals()==:

这个对于String简单来讲就是比较两字符串的Unicode序列是否至关,若是相等返回true;==是比较两字符串的地址是否相同,也就是是不是同一个字符串的引用。

6.
关于String是不可变的

这一说又要说不少,你们只要知道String的实例一旦生成就不会再改变了,好比说:
String str=”kv”+”ill”+” “+”ans”;
就是有4个字符串常量,首先”kv””ill”生成了”kvill”存在内存中,而后”kvill”又和” “ 生成 ”kvill “存在内存中,最后又和生成了”kvill ans”;并把这个字符串的地址赋给了str,就是由于String不可变产生了不少临时变量,这也就是为何建议用StringBuffer的缘由了,由于StringBuffer是可改变的

相关文章
相关标签/搜索