一、String类概述

1.String对象一旦创建就不能改变。

2.字符串常量池。

字符串常量池的特点:池中有则直接使用,池中没有则创建新的字符串常量。

例1:

  1. public class StringDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. StringDemo1();
  6.  
  7. }
  8. public static void StringDemo1()
  9. {
  10. String str1="abcd";
  11. String str2="abcd";
  12. System.out.println(str1==str2);
  13. }
  14. }

以上的代码运行结果为true。

原因分析:当运行到代码String str1="abcd";处,JAVA虚拟机会先检查字符串常量池中是有相同的字符串,如果有,则返回该对象的引用,否则,新创建一个字符串并返回该对象的引用。

运行到代码String str2="abcd";的时候,JAVA虚拟机发现字符串常量池中有相同的字符串,所以不再创建而是返回该对象的引用。

例2:

  1. public class StringDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. //StringDemo1();
  6. StringDemo2();
  7.  
  8. }
  9. public static void StringDemo2()
  10. {
  11. String str1="abcd";
  12. String str2=new String("abcd");
  13. System.out.println(str1==str2);
  14. }
  15. public static void StringDemo1()
  16. {
  17. String str1="abcd";
  18. String str2="abcd";
  19. System.out.println(str1==str2);
  20. }
  21. }

上述运行结果为false。

分析:运行完代码String str1="abcd";的时候,字符串常量池中将会含有一个值为abcd的字符串;执行到代码String str2=new String("abcd");时,进行了两个动作,因为使用new方法创建字符串对象的时候,所需要的构造方法中需要一个对象来创建新对象,所以,"abcd"就是一个动作,它将会在字符串常量池中寻找相同值的对象并返回该对象的引用。但是String类的构造方法中并没有直接使用该对象,而是将该对象先转换成一个字符数组,然后将该字符数组重新组装成一个字符串对象。这个过程可以通过查看源代码获得。因此使用==比较两个对象结果为false,因为它们并不是一个对象,它们的地址值不同。

例3:

  1. public class StringDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. //StringDemo1();
  6. //StringDemo2();
  7. StringDemo3();
  8.  
  9. }
  10. public static void StringDemo3()
  11. {
  12. String str1="abcd";
  13. String str2=new String("abcd");
  14. System.out.println(str1.equals(str2));
  15. }
  16. public static void StringDemo2()
  17. {
  18. String str1="abcd";
  19. String str2=new String("abcd");
  20. System.out.println(str1==str2);
  21. }
  22. public static void StringDemo1()
  23. {
  24. String str1="abcd";
  25. String str2="abcd";
  26. System.out.println(str1==str2);
  27. }
  28. }

该运行结果为true。

分析:先观察源代码:

  1. public boolean equals(Object anObject) {
  2. if (this == anObject) {
  3. return true;
  4. }
  5. if (anObject instanceof String) {
  6. String anotherString = (String)anObject;
  7. int n = value.length;
  8. if (n == anotherString.value.length) {
  9. char v1[] = value;
  10. char v2[] = anotherString.value;
  11. int i = 0;
  12. while (n-- != 0) {
  13. if (v1[i] != v2[i])
  14. return false;
  15. i++;
  16. }
  17. return true;
  18. }
  19. }
  20. return false;
  21. }

String类的equals方法复写了Object类的方法,因此它所接收的参数对象并不是String类型的,而是Object类型的,查看该源码,我们可以发现首先先比较两个对象的引用是否相同,如果相同,则返回true;这是合理的,毕竟如果两个对象的引用都相同,则两个对象一定是完全相同的。接下来,如果两个对象的引用不相同,则并不返回false,而是挨个比较两个字符串中的字符是否相同,如果比较完成之后完全相同,则返回true,否则返回false。我们最后得出结论,那就是该方法在String类中复写之后比较的是字符串内容是否相同,相同返回true,不同返回false。这里由于两个字符串内容相同,因此返回true。

例四:intern()方法。

  1. public class StringDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. //StringDemo1();
  6. //StringDemo2();
  7. //StringDemo3();
  8. //StringDemo4();
  9. //StringDemo5();
  10. StringDemo6();
  11. }
  12. public static void StringDemo6()
  13. {
  14. String str1=new String("abcd");
  15. String str2=str1.intern();
  16. String str3="abcd";
  17. System.out.println(str1==str2);
  18. System.out.println(str2==str3);
  19. }
  20. public static void StringDemo5()
  21. {
  22. char buf[]={'A','B','C','D','E'};
  23. String str=new String(buf);
  24. System.out.println(str);
  25. }
  26. public static void StringDemo4()
  27. {
  28. byte buf[]={65,66,67,68,69};
  29. String str=new String(buf);
  30. System.out.println(str);
  31. }
  32. public static void StringDemo3()
  33. {
  34. String str1="abcd";
  35. String str2=new String("abcd");
  36. System.out.println(str1.equals(str2));
  37. }
  38. public static void StringDemo2()
  39. {
  40. String str1="abcd";
  41. String str2=new String("abcd");
  42. System.out.println(str1==str2);
  43. }
  44. public static void StringDemo1()
  45. {
  46. String str1="abcd";
  47. String str2="abcd";
  48. System.out.println(str1==str2);
  49. }
  50. }

输出结果为两行:

false

true

分析:当String对象调用intern方法时,JAVA虚拟机就会到字符串常量池中寻找字符串常量并和当前字符串内容进行比较,如果值相同,则返回该字符串常量池中的常量的引用,否则创建一个新的常量并返回该常量的引用。执行String str1=new String("abcd");的时候,字符串常量池中已经有了该常量。执行String str2=str1.intern();时,由于已经有了该常量,所以会返回该常量的引用。同理,Stirng str3="abcd";时也是如此。所以会出现这样的结果。

3.String类的构造方法。

我们经常使用String str="xxxx";的形式创建字符串对象,貌似String str=new String("xxx");的形式就没有用了,其实不然,毕竟这种方式存在即合理,很多时候使用前一种方式并不能解决问题,我们还是要使用后一种方式创建字符串,特别是在需要将其它数据类型转换成字符串类型的时候。

其它数据类型主要包括字符数组和字节数组。

3.1字节数组转换成字符串。

  1. public class StringDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. //StringDemo1();
  6. //StringDemo2();
  7. //StringDemo3();
  8. StringDemo4();
  9.  
  10. }
  11. public static void StringDemo4()
  12. {
  13. byte buf[]={65,66,67,68,69};
  14. String str=new String(buf);
  15. System.out.println(str);
  16. }
  17. public static void StringDemo3()
  18. {
  19. String str1="abcd";
  20. String str2=new String("abcd");
  21. System.out.println(str1.equals(str2));
  22. }
  23. public static void StringDemo2()
  24. {
  25. String str1="abcd";
  26. String str2=new String("abcd");
  27. System.out.println(str1==str2);
  28. }
  29. public static void StringDemo1()
  30. {
  31. String str1="abcd";
  32. String str2="abcd";
  33. System.out.println(str1==str2);
  34. }
  35. }

运行结果为:ABCDE。

3.2字符数组转换成字符串。

  1. public class StringDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. //StringDemo1();
  6. //StringDemo2();
  7. //StringDemo3();
  8. //StringDemo4();
  9. StringDemo5();
  10.  
  11. }
  12. public static void StringDemo5()
  13. {
  14. char buf[]={'A','B','C','D','E'};
  15. String str=new String(buf);
  16. System.out.println(str);
  17. }
  18. public static void StringDemo4()
  19. {
  20. byte buf[]={65,66,67,68,69};
  21. String str=new String(buf);
  22. System.out.println(str);
  23. }
  24. public static void StringDemo3()
  25. {
  26. String str1="abcd";
  27. String str2=new String("abcd");
  28. System.out.println(str1.equals(str2));
  29. }
  30. public static void StringDemo2()
  31. {
  32. String str1="abcd";
  33. String str2=new String("abcd");
  34. System.out.println(str1==str2);
  35. }
  36. public static void StringDemo1()
  37. {
  38. String str1="abcd";
  39. String str2="abcd";
  40. System.out.println(str1==str2);
  41. }
  42. }

输出结果:ABCDE。

3.3其它构造方法。

String(byte[] bytes, int offset, int length);该方法将指定在offset处开始处的length长度范围内的字节转换成字符串。

String(char[] value, int offset, int count);该方法原理和上述相同。

3.4总结。

通过使用String类的构造方法可以实现字节数组和字符数组向String类对象的转换。

二、String类功能

1.获取。

1.1获取字符串字符的个数,即字符串长度。

int length();

1.2根据位置获取字符。
char charAt(int index);

1.3根据字符(字符串)获取在字符串中的位置。

自前向后找:
int indexOf(int ch);

int indexOf(int ch, int fromIndex);

int indexOf(String str);

int indexOf(String str, int fromIndex);

自后向前找:

int lastIndexOf(int ch);

int lastIndexOf(int ch, int fromIndex);

int lastIndexOf(String str);

int lastIndexOf(String str, int fromIndex);

查找的时候,应当注意不要越界,否则抛出异常。
如果没有查找到,通常返回-1,可以根据此判断字符或者字符串是否存在。

1.4 获取字符串中的一部分字符串。或者称为字串。

String substring(int beginIndex, int endIndex);
使用方法:subString,返回String,有两个参数,一个是beginIndex,一个是endIndex,截取的到是endIndex之前的一个字符。即beginIndex到endIndex-1。

String substring(int beginIndex) ;
重载方法有subString ,只有一个参数,表示从指定的位置开始,一直到字符串结尾。

2.转换。

2.1将字符串变成几部分。如果有这个功能将返回字符串数组。字符串切割。
String[] split(String regex, int limit);

用法举例:

String s="张三、李四、王五";
String []arr=s.split(",");
如果不是,而是.,则需要特殊处理,因为.是正则表达式中的特殊字符。转义\\.
切割动作涉及到正则表达式。

2.2将字符串变成字符数组。
Char[] toCharArray();

2.3将字符串变成字节数组。

Byte[] getBytes(String charsetName);
打碎成最小单位:字节。
用法举例:

String s="ab你";
byte []arr=str.getBytes();
输出的结果却是:英文字母变成数字输出,而中文则变成了两个负数。
中国的gb2312码最高位都是1,所以都是负数。

2.4字符串中的大小写转换。

String toUpperCase();将字符串中的小写字符转换成大写。

String toLowerCase();将字符串中的大写字符转换成小写字符。

2.5将字符串中的内容进行替换。
String replace(char oldChar, char newChar);
String replace(CharSequence target, CharSequence replacement);
CharSequence是String已经实现的接口。

2.6将字符串两端的空格去掉。
String trim();

2.7将字符串进行连接。
String concat(String str);
concat方法和+的作用差不多。
前者显得更加专业。

2.8value()方法。

此方法为String类的静态方法,参数为各种基本数据类型,作用是将基本数据类型转换成字符串。

3.判断。

3.1两个字符串内容是否相同?
boolean equals(Object anObject);
boolean equalsIgnoreCase(String anotherString)//忽略大小写进行比较,其实就是先转换成大写或者小写再进行比较。

3.2字符串中是否包含某个字符串?
boolean contains(CharSequence s);
其实是用indexOf方法也可以达到相同的目的。

3.3字符串是否以指定字符开头,是否以指定字符串结尾。

boolean endsWith(String suffix);

boolean startsWith(String prefix);

4.比较方法。

int compareTo(String anotherString);

int compareToIgnoreCase(String str) ;
按照字典序比较两个字符串。
基本数据类型使用的是比较运算符,而对象比较使用的是compareTo方法。

三、StringBuffer类。

StringBuffer类:
就是字符串缓冲区,是用于存储数据的容器。
数组也是存储数据的容器,它和StringBuffer的区别是什么?
1.长度可变
2.可以存储不同类型的数据进来。
3.最终要转成字符串才能使用。
4.可以对字符串进行修改。

该类的构造方法中的参数是整数的时候,指定了该缓冲区的初始容量大小;该类的构造方法是字符串时,将会构造一个StringBuffer对象,并将其内容初始化为和该字符串相同。

StringBuffer类的功能:

1.添加。

append方法。参数是基本数据类型,只有两种不行:byte和short不行,但是有int可以代替。
初始容量为16个字符。

  1. public class StringBufferDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. Demo1();
  6. }
  7. public static void Demo1()
  8. {
  9. StringBuffer sb=new StringBuffer();
  10. StringBuffer bs=sb.append(4);
  11. System.out.println(sb==bs);
  12. }
  13. }

运行结果为true。

分析:一个容器加入了一些东西以后该容器仍然是该容器,并没有变化,所以结果为true。

insert方法。该方法参数分为两部分,一部分是插入的位置,一部分是插入的内容。

  1. public class StringBufferDemo
  2. {
  3. public static void main(String args[])
  4. {
  5. //Demo1();
  6. Demo2();
  7. }
  8. public static void Demo2()
  9. {
  10. StringBuffer sb=new StringBuffer();
  11. sb.append("abba");
  12. sb.insert(2,"XXXX");
  13. System.out.println(sb);
  14. }
  15. public static void Demo1()
  16. {
  17. StringBuffer sb=new StringBuffer();
  18. StringBuffer bs=sb.append(4);
  19. System.out.println(sb==bs);
  20. }
  21. }

运行结果为:abXXXXba

2.删除。

方法:StringBuffer delete(int start, int end);

该方法包含头不包含尾。

StringBuffer deleteCharAt(int index);该方法删除指定位置的字符。

使用该方法可以清空缓冲区:sb.delete(0,sb.length());

清空缓冲区也可以使用sb=new StringBuffer();但是不推荐使用因为会浪费内存空间。

3.查找。

和String类几乎相同。

4.修改。

StringBuffer replace(int start, int end, String str);包含头不包含尾。该方法的参数个数和String相同,但是位置颠倒了。

void setCharAt(int index, char ch);该方法比较特殊,并没有返回StringBuffer对象。该方法将指定位置上的字符替换为指定字符。

void setLength(int newLength);在使用该方法时,如果设定的长度小于内容的长度,则会删除多余的部分。使用此方法可以达到清空StringBuffer对象的目的,但是不推荐使用。

StringBuffer reverse();反转字符串

四、StringBuilder类。

此类提供了一个与StringBuffer兼容的API。也就是功能用法一模一样。
这两个类有什么不同?
StringBuffer在jdk1.0就出现了,线程安全。
StringBuilder在jdk1.5才出现,线程不安全。

浅析StringBuffer类线程安全的原因:StringBuffer类中有append方法和delete方法,如果一个线程调用append方法,另一个线程同时调用delete方法,在不加同步锁的情况下,就会出现线程安全性问题。JDK1.0考虑的线程安全性多一点,所以加上了同步;使用同步使得线程更加安全,但是这样的好处仅仅在多线程编程中--如果是单线程,由于不会出现线程安全性问题,所以如果经常使用StringBuffer类的append方法和delete方法,就会极大的降低程序的执行效率,这是每次调用方法都必须判断锁造成的。

JDK1.5考虑到了这一点,所以将同步去掉,重新创建了一个类StringBuilder,这是考虑到程序执行效率之后的结果。

我们要知道JDK升级几乎只有三点原因:

1.简化书写

2.提高效率

3.增加安全性。

而StringBuilder类出现的目的正是为了提高效率,付出的代价就是不安全。

【JAVA中String、StringBuffer、StringBuilder类的使用】的更多相关文章

  1. JAVA中String和StringBuilder类的特点及使用

    转自:https://www.imooc.com/code/2202 仅做个人学习记录之用,侵删! 什么是 Java 中的字符串 在 Java 中,字符串被作为 String 类型的对象处理. Str ...

  2. java中 String StringBuffer StringBuilder的区别

    * String类是不可变类,只要对String进行修改,都会导致新的对象生成. * StringBuffer和StringBuilder都是可变类,任何对字符串的改变都不会产生新的对象. 在实际使用 ...

  3. java中String,StringBuffer,StringBuilder之间的区别

    文章转载自:http://www.cnblogs.com/frankliiu-java/archive/2010/07/05/1771537.html String是固定长度的字符串,如果要发生变化必 ...

  4. Java中String/StringBuffer/StringBuilder区别(转)

    1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String 2.String <(StringBuffer,StringBuild ...

  5. Java之String,StringBuffer,StringBuilder类

    在 java 语言中, 用来处理字符串的的类常用的有 3 个: String.StringBuffer.StringBuilder. 它们的异同点: 1) 都是 final 类, 都不允许被继承; 2 ...

  6. java中string , StringBuffer , StringBuilder 区别

    1.String String变量的值不能改变,如果要改变String变量的值,虚拟机首先会遍历方法区中的字符串常量,如果存在需要的值,则虚拟机直接把此常量值的地址分配给String变量,如果不存在这 ...

  7. 探秘Java中String、StringBuilder以及StringBuffer

    探秘Java中String.StringBuilder以及StringBuffer 相信String这个类是Java中使用得最频繁的类之一,并且又是各大公司面试喜欢问 到的地方,今天就来和大家一起学习 ...

  8. 重温java中的String,StringBuffer,StringBuilder类

    不论什么一个系统在开发的过程中, 相信都不会缺少对字符串的处理. 在 java 语言中, 用来处理字符串的的类经常使用的有 3 个: String.StringBuffer.StringBuilder ...

  9. java 中String与StringBuilder 效率

    之前印象中string与stringbuilder操作时,如果多次改变string就使用stringbuilder,效率会提高: 今天实际遇到了问题,亲身经历过之后,这性能不是一般的影响啊:不是同一个 ...

  10. Java中String,StringBuffer与StringBuilder的差别

    String 字符串常量: StringBuffer 字符串变量〈缓冲区〉(线程安全): StringBuilder 字符串变量〈缓冲区〉(非线程安全): 简要的说, String 类型和 Strin ...

随机推荐

  1. 18 TaskScheduler任务调度器抽象基类——Live555源码阅读(一)任务调度相关类

    这是Live555源码阅读的第二部分,包括了任务调度相关的三个类.任务调度是Live555源码中很重要的部分. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/ol ...

  2. ja

    import java.util.*; class animal{     void cry(){            }     void get_animal_name(){           ...

  3. git 忽略文件权限

    git config --add core.filemode false 发现.git/config 中新增了一行: [core] ... filemode = false ref: http://b ...

  4. discuz后台开发常用函数

    showsetting()表单显示 返回值:无 参数: $setname - 指定输出标题,如:setting_basic_bbname, 自动匹配描述文字为:setting_basic_bbname ...

  5. 【Eclipse】eclipse che 协作开发

    http://www.eclipse.org/che/ http://blog.csdn.net/ccfeng2008/article/details/50881024 http://www.osch ...

  6. 【leetcode】Gas Station

    Gas Station There are N gas stations along a circular route, where the amount of gas at station i is ...

  7. 二叉树节点个数题目[n0,n1,n2]

    若完全二叉树的节点个数为2N-1,则叶节点个数为()    A)N-1        B)2×N        C)2N-1        D)2N解析:    结点拥有的子树数为结点的度    证明 ...

  8. Struts2获取Session方法

    Struts2里面有三种方法可以获取request,最好使用ServletRequestAware接口通过IOC机制注入Request对象. 方法1:IOC方式action类实现SessionAwar ...

  9. ios 关于UIView 的multipleTouchEnabled 和 exclusiveTouch

    做项目时发现,在一个界面上的2个button竟然可以同时点击,依次push进去了2个 controller!我就产生了疑问,一个view的multipleTouchEnabled属性默认是false啊 ...

  10. 关于Intent ,Task, Activity的理解

    看到一篇好文章,待加工 http://hi.baidu.com/jieme1989/item/6e5f41d3f65be848ddf9beb9 第三篇 http://blog.csdn.net/luo ...