Java OOP中的字符串篇

字符串的三大特征:

  • String 字符串常量
  • StringBuffer 字符串变量(线程安全)
  • StringBuilder 字符串变量(非线程安全)

一、定义

Java OOP中的字符串篇

查看 API 会发现,String、StringBuffer、StringBuilder 都实现了 CharSequence 接口,内部都是用一个char数组实现,虽然它们都与字符串相关,但是其处理机制不同。

  • String:是不可改变的量,也就是创建后就不能在修改了。
  • StringBuffer:是一个可变字符串序列,它与 String 一样,在内存中保存的都是一个有序的字符串序列(char 类型的数组),不同点是 StringBuffer 对象的值都是可变的。
  • StringBuilder:与 StringBuffer 类基本相同,都是可变字符换字符串序列,不同点是 StringBuffer 是线程安全的(支持多线程),StringBuilder 是线程不安全的(支持单线程)。

使用场景

使用 String 类的场景:在字符串不经常变化的场景中可以使用 String 类,例如常量的声明、少量的变量运算。

使用 StringBuffer 类的场景:在频繁进行字符串运算(如拼接、替换、删除等),并且运行在多线程环境中,则可以考虑使用 StringBuffer,例如 XML 解析、HTTP 参数解析和封装。

使用 StringBuilder 类的场景:在频繁进行字符串运算(如拼接、替换、和删除等),并且运行在单线程的环境中,则可以考虑使用 StringBuilder,如 SQL 语句的拼装、JSON 封装等。

分析

在性能方面,由于 String 类的操作是产生新的 String 对象,而 StringBuilder 和 StringBuffer 只是一个字符数组的扩容而已,所以 String 类的操作要远慢于 StringBuffer 和 StringBuilder。

简要的说, String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象, 因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象然后将指针指向新的 String 对象。所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC(垃圾回收) 就会开始工作,那速度是一定会相当慢的

而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在一般情况下我们推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。

而在某些特别情况下, String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比 StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的,例如下例:

String S1 = “This is only a" + “ simple" + “ test";
StringBuffer Sb = new StringBuilder(“This is only a").append(“ simple").append(“ test");

你会很惊讶的发现,生成 String S1 对象的速度简直太快了,而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM 的一个把戏,在 JVM 眼里,这个

String S1 = “This is only a" + “ simple" + “test";

其实就是:

String S1 = “This is only a simple test";

所以当然不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的 String 对象的话,速度就没那么快了,譬如:

String S2 = "This is only a";
String S3 = "simple";
String S4 = "test";
String S1 = S2 +S3 + S4;

这时候 JVM 会规规矩矩的按照原来的方式去做。因为每个变量都在内存中开辟了新的空间,最终指针指向的是字符串拼接后的那块地址。所以没有指针指向的空间就成了垃圾,GC在回收的时候就会影响性能。

对于上述的理解我们在对于字符串的创建上再来具体延伸一下,具体内容如下。

1.创建对象

对于java程序中的字符串直接常量,JVM 会使用一个字符串池来保存它们。当第一次使用某个字符串直接常量时,JVM会将它放入字符串池中进行缓存。在一般情况下,字符串池中的字符串对象不会被垃 圾回收。当程序再次需要使用该字符串时,无需重新创建一个新的字符串就可以直接让引用变量直接指向字符串中已有的字符串。而使用new操作创建的字符串对象不指向字符串池中的对象,但是可以使用intern()方法使其指向字符串池中的对象。

实例1:

String s1 = "abc";
//↑ 在字符串池创建了一个对象
String s2 = "abc";
//↑ 字符串pool已经存在对象“abc”(共享),所以创建0个对象,累计创建一个对象
System.out.println("s1 == s2 : "+(s1==s2));
//↑ true 指针指向同一个对象,
System.out.println("s1.equals(s2) : " + (s1.equals(s2)));
//↑ true 值相等(equals比较的是值不是指针)

实例2:

String s1 ="abc";
String s2 =new String("abc");
System.out.println(s1==s2);
//↑ false 没有指向同一地址. s2 new的是一块新的空间.值虽然相同但是地址不同.

实例3:

String s1 = new String("abc");
//↑ 创建了两个对象,一个存放在字符串池中,一个存在与堆区中;
//↑ 还有一个对象引用s1存放在栈中
String s2 = new String("abc");
//↑ 字符串池中已经存在“abc”对象,所以只在堆中创建了一个对象
System.out.println("s1 == s2 : "+(s1==s2));
//↑false s1和s2栈区的地址不同,指向堆区的不同地址;
System.out.println("s1.equals(s2) : "+(s1.equals(s2)));
//↑true s3和s4的值相同

实例4:

String s1 = "abc";
String s2 = new String("abc"); System.out.println("s1 + s2 :" + (s1 == s2));
//↑false 存放的地区多不同,一个栈区,一个堆区

实例5:

String s1 = "ab" + "cd";  //1个对象
String s2 = "abcd";
System.out.println("s1 = s2 : "+ (s1 == s2));
//* 在这里,"ab"和"cd"都是常量,实际上JVM在后台实现的是s1 = "abcd";因此s2的值等同于s1的值的时候,常量池不会开辟新空间,指针指向同一个地址而已.

实例6:

String a = "ray";
String b = a.concat("long");
String c = a+b;
System.out.println("a+b == c:" + (a+b == c));
//↑false a开辟一块空间。b相当于向a中+"long"这个值而已,其本身也同样是开辟了一块空间。a+b虽然值显示相同。但是a,b都属于不同的内存地址所以不等于c.
System.out.println(b); System.out.println("b == c :" + (b ==c));
//↑false  同上b的地址属于其本身,c的地址是a+b的地址所以不相等。

注释:.concat为字符串累加的一个方法,其用法同“+”的效果相同,性能上没有任何区别。

2. String 类中== 于 equlas的区别

==比较的是堆中字符串所指向的内存地址,而equlas是用来比较堆中字符串的值。

package com.java.demo_6;

public class StrTest2 {
public static void main(String[] args) {
    //案例1:
    String str1 = new String("str");
String str2 = new String("str");
System.out.println("==比较 :"+ (str1 == str2));
System.out.println("equal比较:"+ str1.equals(str2));        //案例2:
String str3 = "str1";
String str4 = "str1";
System.out.println("==比较 :"+ (str3 == str4));
System.out.println("equal比较:"+ str3.equals(str4)); } }

结果为:
 ==比较 :false
equal比较:true
==比较 :true
equal比较:true

根据打印的可以发现使用equal比较时无论是使用自动装箱来实例化还是用new来实例化,返回的都true,而用==则不一样了,自动装箱来实例化的返回的是true,而用new来

实例化的返回的确实false;先不急着解决为什么,先来了解下equals和==的区别,到时候就可以知道答案了

equals方法最初是在所有类的基类Object中进行定义的,源码是

 public boolean equals(Object obj) {
return (this == obj);
}

可以看出这里定义的equals与==是等效的,但上面的怎么还会不一样呢?
原因就是String类对equals进行了重写:

Java OOP中的字符串篇
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
Java OOP中的字符串篇

这里对equals重新需要注意五点:

1   自反性:对任意引用值X,x.equals(x)的返回值一定为true. 
2   对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true; 
3   传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true 
4   一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变 
5   非空性:任何非空的引用值X,x.equals(null)的返回值一定为false

经过重写后就跟==有本质的区别了:

equal:是用来比较两个对象内部的内容是否相等的,由于所有的类都是继承自java.lang.Object类的,所以如果没有对该方法进行覆盖的话,调用
的仍然是Object类中的方法,而Object中的equal方法返回的却是==的判断,因此,如果在没有进行该方法的覆盖后,调用该方法是没有
任何意义的。在java面向对象的处理中我们一般在javabean中都要选择重写equals方法,使用hibernate后,我们要生成数据库的映射文件与实体

类,这是我们就最好在实体类中进行equals方法的重写,重写时我们可以根据自己的定义来实现该方法只要遵守那五条原则,例如对于一个student类

我们定义只要在学号相同时我们就认为这两个对象时相等的;同时我们还要重写hashcode方法http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html
==:是用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。

3. 字符串方法

获取方法

•int length()获取字符串长度
•char charAt(int index)根据位置获取某个字符
•int indexOf(int ch) 返回的是ch在字符串中第一次出现的位置
•int indexOf(int ch,int fromIndex)从fromIndex指定位置开始,获取ch在字符串中第一次出现的位置
•int indexOf(String str)
•int indexOf(String str,int fromIndex)
•int lastIndexOf(int ch)

实例1( length()字符串长度)

package com.java.demo_6;

public class StrTest2 {
public static void main(String[] args) {
String str = "我是黑猫警长!";
int str1 = str.length();
System.out.println(str1); } }

结果为:7

注释:“我是黑猫警长!”这个字符串中,双引号中的字符串算上!号同7个字符,所以结果为7。而.length();返回的结果是整个字符串的长度值。

实例2(charAt(int index)根据位置获取某个字符)

package com.java.demo_6;

public class StrTest2 {
public static void main(String[] args) {
String str = "我是黑猫警长!";
System.out.println(str.charAt(3));//获取某一个字符
System.out.println(str.charAt(str.length() -1));//获取最后一个字符 } }

结果: (1) 输出的是“猫”。因为字符位是从0开始算起的,.charAt(3)指向的是第4个标致位,所以取的是“猫”。

   (2)输出的是 “!”号。因为.charAt()中输入的是str.length()-1所以代表字符串长度的最后一位的意思,所以取值为“!”号。

实例3(indexOf(int ch) 返回的是ch在字符串中第一次出现的位置)

package com.java.demo_6;

public class StrTest2 {
public static void main(String[] args) {
String str = "我是黑猫警长!我是黑猫警长!我是黑猫警长!";
int index = str.indexOf("!");
System.out.println(index);
} }

结果:6  。indexof(“!”); 查找的对象是“!” ,而“!”在整个字符串中出现的第一个位置为第6个下标。所以返回值为6.

实例4(indexOf(int ch,int fromIndex)从fromIndex指定位置开始,获取ch在字符串中第一次出现的位置)

package com.java.demo_6;

public class StrTest2 {
public static void main(String[] args) {
String str = "我是黑猫警长!我是黑猫警长!我是黑猫警长!";
int index1 = str.indexOf("黑", 6);
int index2 = str.indexOf("黑", 0);
System.out.println(index1);
System.out.println(index2); } }

结果:(1)输出结果为9.indexof(int ch,int fromIndex)的语法是ch为要查找的字符,fromIndex代表从哪里起始查找。因为输出的是6所以是从整个字符串中的第6个位置开始查找字符"黑"。而黑在整个字符串中的下标为9所以输出值为9.

   (2)输出结果为2.同上因为0是从第0个位置开始查找,所以查找的字符串在整个字符串中的下标为第2个位置所以输出值为2(再次强调字符串下标是从0开始起始的)

实例5(indexOf(String str))跟 (indexOf(int ch))

在查找的效果上没有什么不同。一个是查找一段字符串,一个是查找一个字符。但是不管你是查找字符串还是字符,查找的都是字符串,字符中的第一个元素的下标。只要查找到就结束,因此从输出上来看其实返回的结果都一样。都是为第一个元素位。

实例6( indexOf(String str,int fromIndex))跟(indexOf(int ch,int fromIndex))

同上的原理,查找的都是第一个字符串,字符的第一个下标位后结束。只不过fromIndex是只从哪里开始查找而已,其他跟上述没任何区别。

实例7(lastIndexOf(int ch))

package com.java.demo_6;

public class StrTest2 {
public static void main(String[] args) {
String str = "我是黑猫警长!我是黑猫警长!我是黑猫警长!"; int str1 = str.lastIndexOf("是");
System.out.println(str1);
} }

结果:15   .lastIndexof用法是从最后一位开始查找要查的字符或者字符串,只要查到就结束。其他 lastIndexof(int ch , formIndex)等用法不在重复同上。

注释:indexof的总结是获取的是查找字符串在整个字符串中的下标,而不是字符串的值本身。要想获取字符串的值要通过切割的方法来获取,请参考切割方法中subString的用法。
判断方法

•boolean contains(String str) 另一种判断方法:if(str.index(str)!=-1)

注释:判断一个字符串是否包含在另一个字符串中时使用。

实例1(contains(String str))返回值为True或者false

package com.java.demo_9;

public class test1 {

	public static void main(String[] args) {
String str1 = "最近推荐一款热门游戏 给你,名字叫做<阴阳师>.";
String str2 = "阴阳师";
String str3 = "茨木童子"; boolean result = str1.contains(str2);
boolean result1 = str1.contains(str3);
System.out.println(result);
System.out.println(result1); }
}

结果: result返回结果为True.result1返回结果为false.
•boolean startsWith(String str) and startsWith(prefix, toffset)

注释:startWith是判断如果参数所表示的字符序列是由该字符串所表示的字符序列的前缀,则返回true,否则为false。

实例2(startsWith(String str))

package com.java.demo_9;

public class test {

	public static void main(String[] args) {

		String str1 = "茨木童子御魂搭配:";
String str2 = "茨木童子最好搭配,4破式套装+2心眼(提高攻击加成)";
String str3 = "搭配"; System.out.println(str1.startsWith("茨"));
System.out.println(str1.startsWith("木"));
System.out.println(str1.startsWith("子", 3));
//System.out.println(str1.startsWith(prefix, toffset)); }
}

结果: (1)True (2) false (3) True

(1)str1字符串第一个字符是"茨"字所以匹配成功,返回True

(2)str1字符串第一个字符是“茨”,而我们search的字符是“木”,所以不匹配。返回结果为false。

(3)是从str1这个字符串中查找“子”字。但是后面定义toffset就是从哪里开始起始的意思。因为3正好是子的下标位,因此返回的是True.
•boolean endsWith(String str)

实例3(endsWith(String str))

注释:同startsWith相反,是从一个字符串的最末尾开始查找。参数可以输入变量也可以直接输入字符串。startsWith也是一样。

package com.java.demo_9;

public class test {

	public static void main(String[] args) {

		String str1 = "茨木童子御魂搭配:";
String str2 = "茨木童子最好搭配,4破式套装+2心眼(提高攻击加成)";
String str3 = "搭配";
String str4 = ":"; System.out.println(str1.endsWith(str3));
System.out.println(str1.endsWith(str4)); }
}

结果:

(1)返回值为false. (str1的最后一个字符为:号所以不匹配)

(2)返回值为True. (str4赋值的就是:号因此在str1末尾查找时匹配的也是:号,因此返回true)
•bolean isEmpty(String str)

注释:判断一个字符串是否为空。(这种说法不是很准确。因为字符串如果是null的话,不会返回。而是抛出异常)

实例4(isEmpty(String str))

package com.java.demo_9;

public class test1 {

	/**
* @param args
*/
public static void main(String[] args) {
String str = "今天星期五";
String str1 = "";
String str2 = null; System.out.println("字符串长度为 = " + str.length()); System.out.println("判断字符串是否为空 = " + str.isEmpty());
System.out.println("判断字符串是否为空 = " + str1.isEmpty());
System.out.println("判断字符串是否为空 = " + str2.isEmpty()); } }

结果:

(1)返回:5 因为使用的是.length()方法,是测试字符串长度的。因此返回值为字符串总下标数。

(2)返回值为true.因为str1中“”是代表空字符串。因此用.isEmpty()返回的结果为true.

(3)不会返回true或者false。会抛出下列异常。因此如果字符串为null的情况,要想判断字符串是否为空最好的方法是通过if语句来判断。if(str2 == null || str2.length()==0)后面返回true,false。

“Exception in thread "main" java.lang.NullPointerException“
    at com.java.demo_9.test1.main(test1.java:17)

※※•boolean equals(String str)

注释:对比2个字符串是否相等。也是字符串中比较常用的方法之一。

这里要强调一点的是,很多人在判断2个字符串是否相等时都习惯用==来判断。其实在java中.equals跟==的关系是有区别的。

==判断的其实是指向字符串的指针是否相等。而.equals判断的是2个字符串的值是否相等。所以要想判断值的时候就不能用==,一定要使用.equlas来进行判断。

实例4(equals(String str))

package com.java.demo_9;

public class test1 {

	public static void main(String[] args) {
String str1 = "星期五";
String str2 = "星期五";
String str3 = new String("星期五"); System.out.println("str1==str2:"+(str1.equals(str2)));
System.out.println("str1==str2:"+(str1==str2));
System.out.println("str1==str3:"+(str1==str3));
} }

结果:

(1) 返回结果为:str1==str2:true   分析:对比的是2个结果的值,很显然值相同所以返回true.
(2) 返回结果为:str1==str2:true   分析:这里涉及到一个常量池的概念。因为str1在赋值“星期五”的时候,已经分配了一块内存来存这些数据。而str2再出现相同的字符串时,系统首先会先去内存找是否有相同的字符串存在。如果有直接把指针指向之前被创建的字符串。如果没有就新开辟空间。因此这里在用==的时候指针其实是指向的同一块地址,因此返回值为true.
(3) 返回结果为:str1==str3:false  分析:str3是new出来的,而我们知道只要new了,就存在堆跟栈的概念(这里不重复提)。说明str3中的星期五是独立的。跟str2不同的是指针指向的是自己而不是之前创建相同的相同字符串。指针不同所以==在这里是不同的。因此返回结果为fasle.
※※•boolean equalsIgnoreCase(String str);

注释:不区分大小写的情况下来判断字符串是否一致。(在某种情况下这个用法更实用。比如说用来判断用户名的情况。要求不严格的情况下可以忽略大小写。当然判断密码的话另当别论。一定要用equals不要用equalsIgnoreCase)

实例5(equalslgnoreCase(String str))

package com.java.demo_9;

public class test1 {

	public static void main(String[] args) {
String str1 = "Friday";
String str2 = "friday"; System.out.println(str1.equals(str2));
System.out.println(str1.equalsIgnoreCase(str2)); } }

另外补充一点下面实例中str3的字符串明显前后有空格。如果直接对比肯定返回为false。去除空格用.trim方法。然后再跟.equalsIgnoreCase来判断的例子比较多。这里要注意对比的对象是谁对比谁。

因为有空格的是str3,因此我们首先要使用str3.trim()去除空格后再跟str1做对比。

实例6(.trim().equalslgnoreCase(String str))

package com.java.demo_9;

public class test1 {

	public static void main(String[] args) {
String str1 = "Friday";
String str2 = "friday";
String str3 = " friday "; System.out.println(str1.equals(str2));
System.out.println(str1.equalsIgnoreCase(str2));
System.out.println(str3.trim().equalsIgnoreCase(str1)); } }

转换方法

•将字符数组转换为字符串
注释:关于char数组跟String之间的关系请参考下列博客

http://blog.csdn.net/u010297957/article/details/48495791

构造函数

1.String(char[] chs)

2.String(char[] chs,offset,count)将字符数组中的一部分转成字符串。

静态方法

1.static String copyValueOf(char[] chs)

注释:用途是把cha[]数组中的每个字符拼接成字符串。

实例1(static String copyValueOf(char[] chs))

package com.java.demo_9;

public class test1 {

	public static void main(String[] args) {
char[] cha = {'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
String str = ""; /**
* 打印cha字符数组中的每个元素
*/
for(int i=0;i<cha.length;i++){
System.out.println(cha[i]);
}
System.out.println("++++++++++++++++++++++++++++++++++++++++++++");
/**
* 把cha字符数组转成字符串
*/
str = str.copyValueOf(cha);
System.out.println(str); System.out.println("++++++++++++++++++++++++++++++++++++++++++++"); str = str.copyValueOf(cha, 2, 6);
System.out.println(str);
} }

结果:

(1)返回的是每个cha数组中的每个元素。

(2)返回的是一个String 类型的字符串。内容把cha[]中的元素拼接成了字符串。

(3)copyValueof中的另一个用法String copyValueOf(char[] chs,int offset,int count),也就是下列2中的方法。具体情况请参考博客。

2.static String copyValueOf(char[] chs,int offset,int count)

注释:详情请参照博客:http://www.yiibai.com/java/java_string_copyvalueof.html

3.static String valueOf(char[] )

注释:这里的参数代表把字符转换为字符串,其实类型转换包括很多种。int,boolean,double等等都可以通过String valueOf()的方式进行转换,详细请参考下列博客。

参考:(1)http://blog.csdn.net/yuan444075705/article/details/11375969

   (2)http://www.runoob.com/java/java-string-valueof.html

这里指举一个案例

package com.java.demo_9;

public class test {
public static void main(String[] args) {
int a = 3;
String c = "今年"; System.out.println(c.contains(a));
//The method contains(CharSequence) in the type String is not applicable for the arguments (int)
//CharSequence a = 3; String b = String.valueOf(a);
System.out.println(b); System.out.println(c.contains(b));
} }

结果:

(1)System.out.println(c.contains(a));上述我们有讲过.contains是判断一个字符串是否包含在另一个字符串中的。当我们在使用.contains来对int类型的值做比较的时候语句会抛出异常。提示该方法包含(CharSequence)在字符串类型不适用于参数(int)。必须把int类型转换成CharSequence才可以。

(2)System.out.println(c.contains(b));当我们用.valueOf()把int转换为String后再通过.contains来判断的时候发现有返回值了。返回值必然为false,因为b字符串中没有3这个字符串。但是可以判断了说明我们用.valueOf已经把int类型转换成了String 类型。

4.static String valueOf(char[] chs,int offset,int count)
这个语句用法请参照上述博客,在此不再详细说明了。

•将字符串转换成字符数组
char[] toCharArray

实例2(char[] toCharArray)

package com.java.demo_9;

public class test {
public static void main(String[] args) {
/**
* char数组的创建以及输出
*/
char[] result = {'a','b','c','d'};
System.out.println(result); System.out.println("++++++++++++++++++++++++++++++++++++");
/**
* 字符串转数组后输出
*/
String str = "abc";
char[] arr = str.toCharArray();//通过String的.toCharArray()方法进行转换.
System.out.println(arr); } }

结果:通过上面案例可以看出System.out.println(arr);最终的输出是abc。我们看起来是字符数组连接好的呈现。其实内部还是[a,b,c]的方式进行排列的。这一点需要注意。

•将字符数组转换成字符串

实例3(String .copyValueOf()以及.valueOf())

package com.java.demo_9;

public class charChangetoString {
public static void main(String[] args) { char[] arr = {'a','b','c','d','e','f','g'}; //方法1:
String str = "";
str = str.copyValueOf(arr);
System.out.println(str); //方法2: String str1 = null;
str1 = str1.valueOf(arr);
System.out.println(str1); }
}

结果:当然方法很多。上面列举我们这次学过的2种方法。(1)是通过.copyValueOf的方式把字符数组中的元素copy到String类型的空字符串中。然后再打印。(2)直接通过.valueOf的方式进行类型转换成String,
•将字符串转换成字节数组
byte[] toBytes

注释:以后在数据传输过程中经常会遇到字节等的数据转换,下面的案例是String转Byte,以及Byte如何再转回String的简单案例。
实例4(byte[] toBytes)

package com.java.demo_9;

public class charChangetoString {
public static void main(String[] args) {
/**
* String 转 byte[]
*/
String str = "hello";
byte[] strbyte = str.getBytes(); for(int i=0;i<strbyte.length;i++){
System.out.println(strbyte[i]);
} /**
* byte[]转String
*/
byte [] a = {104,101,108,108,111};
String str1 = new String(a);
System.out.println(str1); /*
* byte转String(单一值)
*/ byte b = 101;
System.out.println(Byte.toString(b));
System.out.println(b + "");
System.out.println(new String(new byte[] {b})); }
}

结果:

(1)其实先把字符串拆分成了byte[]数组。然后通过str.getBytes()方法分别放到数组中。再通过for循环的方式打印它们的值。如果不用for循环打印出来的是乱码。

(2)是把byte数组中的元素,逐一转换成字符串。个人感觉这种方法比较好用。

(3)提供了3种转换方法。任何一种方法都可以。但是要注意的是,第一种跟第二种方法虽然转换成了字符串但是值还是byte本身。要想转换成字符串值最好通过第三种方法或者(2)种的方法。

替换方法

String replace(olderStr,newStr)

注释:字符串替换。olderStr为原有字符串值,newStr为替换后的字符串值。

实例4(String replace(olderStr,newStr))

package com.java.demo_9;

public class charChangetoString {
public static void main(String[] args) {
String str = "www.google.com";
System.out.println("修改前:" + str); String str1=null;
str1 = str.replaceAll("com","jp.com");
System.out.println("修改后:" + str1);
}
}

结果:上面的结果非常的显而易见,修改前的字符串为“www.google.com”。而通过.replaceAll(oldStr,newStr)转换后的值为“www.google.jp.com”

切割方法

String split(regex)

注释:通过split来进行字符串的分隔。但是这里要强调一点的是,java中的split并没有想象中的那么好用。因为它的部分字符要求不得跟ASIC码中的特殊字符相重。如果重复的话就不会取到我们想要的结果。通常在这种情况下需要通过\\转译符再加上要分隔对象来进行取值。但是这种方法只能解决80%的问题。但是大部分还是可以取到的。具体案件具体分析。那么接下来我们一起来看一下split的用法。具体内容可以参照下列博文。

实例5(String split(regex))

package com.java.demo_9;

public class charChangetoString {
public static void main(String[] args) { String str = "192.168.9.121";
System.out.println("原始数据:"+str);
System.out.println("+++++++++++++++++++++++++++++++++"); String []str1 = str.split("\\."); System.out.println("分割后打印数据:"+str1);
System.out.println("++++++++++++++++++++++++++++++++++"); for(int i=0;i<str1.length;i++){
System.out.println("for循环过后数据:"+str1[i]);
} }
}

结果:除了分隔符"++++"以外,System.out.println();打印出来的三段数据如下。

(1)原始数据。

(2)通过.split(“分隔符”)方法后直接打印的数据。这里可以看出打印出来的是个迭代器。并不能直观的看到里面的值。(这里需要注意一点的是:当我们通过split方法来对特殊符号.来进行分隔的时候必须加上\\转译符再加上点,例如(\\.)的方式来进行分隔。不然是没有数据的。这就是split方法不遍的地方)

(3)基于.split方法分隔后的数据然后再加上for循环来打印分隔后字符串数组中的每个元素。

更详细的方法解读请参照下列博客博文。

原始数据:192.168.9.121
+++++++++++++++++++++++++++++++++
分割后打印数据:[Ljava.lang.String;@c21495
++++++++++++++++++++++++++++++++++
for循环过后数据:192
for循环过后数据:168
for循环过后数据:9
for循环过后数据:121

博客:http://www.cnblogs.com/mingforyou/archive/2013/09/03/3299569.html

获取子串[编辑分类]

注释:这个也可以取字符串,但是你必须清楚的知道每个字符的下标后才方便于截取。beginIndex就是从起始位开始0就是第一个字符。endIndex顾名思义就是结束位。重点要说一下String subString(beginIndex,endIndex)。因为它是顾头不顾尾的,因此如果想要从一个字符串任意一位直接到末尾的话,直接用beginIndex就够了。如果想要精确截取字符串中的某一段字符的话,必须要清楚的知道起始位以及结束位的下标,然后才能精准的截取。一起来看一下下面的例子。

String subString(beginIndex)

String subString(beginIndex,endIndex)包含头不包含尾

实例6(String subString(beginIndex) 以及String subString(beginIndex,endIndex))

package com.java.demo_9;

public class charChangetoString {
public static void main(String[] args) { String str = "192.168.9.121"; String str1 = str.substring(0, 8);
System.out.println(str1); String str2 = "今天的天气不错!"; String str3 = str2.substring(3);
System.out.println(str3); String str4 = str2.substring(2, 5);
System.out.println(str4); String str5 = str2.substring(0, 9);
System.out.println(str5); }
}

结果:

(1)返回结果为:192.168.   分析:起始位为0,endIndex为8,按道理“192.168.9.121”中的第8位应该为9,那为什么只截取到了.而没包含9呢。这里要说明的是endIndex截取的其实是endIndex -1后的字符。而不是endIndex指向的字符。这点一定要注意!!
(2)返回结果为:天气不错!  分析:因为这里用到的是beginIndex的用法。只要指定开头位就可以了,然后一直截取到最后。最终得到的值就是天气不错!
(3)返回结果为:的天气       分析:这里用到的方法是beginIndex,endIndex方法。精确指定了要截取的位置下标。所以把这中间包含的字符串一并截取出来了。

(4)返回结果为下列异常:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 9
    at java.lang.String.substring(String.java:1935)
    at com.java.demo_9.charChangetoString.main(charChangetoString.java:20)

分析:今天的天气不错!总共加起来就8个字符。而我们的endIndex设定的为9超出了字符串的长度因此会抛出异常。另外起始位<0或者结束位>字符串长度都会抛出这个异常。

将字符串转换成大小写

String toUpperCase()

String toLowerCase()

注释:toUpperCase()是将字符串全部转换为大写。相反toLowerCase()是将字符串全部转换为小写。

实例7(String toUpperCase() 以及 String subString(beginIndex,endIndex))

package com.java.demo_9;

public class charChangetoString {
public static void main(String[] args) { /**
* 讲字符串全部转换为大写
*/
String str = "my name is liupeng. comefrom shandong yantai!";
String str1 = str.toUpperCase();
System.out.println(str1); /**
* 讲字符串全部转换为小写
*/
String str2 = str.toLowerCase();
System.out.println(str2); /**
* 字符串首字母大写
*/
str =str.replaceFirst(str.substring(0, 1),str.substring(0, 1).toUpperCase());
System.out.println(str); }
}

结果:

(1)返回值:MY NAME IS LIUPENG. COMEFROM SHANDONG YANTAI!
(2)返回值:my name is liupeng. comefrom shandong yantai!
(3)返回值:My name is liupeng. comefrom shandong yantai!  分析:先.replaceFirst方法来替换字符串,然后内部先通过.subString方法找到要替换字符串的下标。找到后再通过.toUpperCase()的方法进行转换。据说这种方法不太好。有更好的方法的大神们可以多多指导。谢谢。

另外添加一个案例:(一并替换相同的字符)

package com.java.demo_9;

public class tes {

	public static void main(String[] args) {
String a = "come,come,come"; String c = a.replaceAll("c", "C");
System.out.println(c); /*String b = a.replaceFirst(a.substring(0, 1), a.substring(0, 1).toUpperCase());
System.out.println(b); for(int i=0;i<a.length();i++){
if(a.contains("c")){
a=a.replaceAll("c", "C");
}
}
System.out.println(a);*/
} }

结果:返回值为:Come,Come,Come由此可以看出这个语句是替换指定的字符的。我只是用了replaceAll这个方法来直接替换了。这么做也有不要的地方,如果字符串中有c但是不是你指向替换指定的c而不想替换某个c的时候不适合用这个方法。

将字符串两端的空格去除

String trim()

实例7(String trim())

注释:这个在上面的案例中其实已经列举过了。在此不多加说明直接上案例。(作用:去除字符串前后空格用的。注意:字符串中间的空格是去除不了的。不要问为什么。。)

package com.java.demo_9;

public class tes {

	public static void main(String[] args) {
String str = " 今天天气不错呀! ";
System.out.println("修改前:"+str); String result = str.trim();
System.out.println("修改后:"+result);
} }

结果:(自己看差异)

(1)修改前:   今天天气不错呀!    
(2)修改后:今天天气不错呀!

对两个字符串进行自然顺序的比较

int compareTo(String str)

实例8(int compareTo(String str))

注释:返回一个int类型的数据。其比较规则是:拿出字符串的第一个字符与参数的第一个字符进行比较,如果两者不等,比较结束,返回两者的ascii差,即字符串的第一个字符减去参数的第一个字符的ascii码值。如果比较到最后结果全部相等的话,返回值为0。
这里有一点需要注意:如果两个字符串的长度不同,并且一个字符串与另一个字符串的前面N个字符相等,那么这个方法返回返回两个字符串长度之差。

package com.java.demo_9;

public class tes {

	public static void main(String[] args) {

		String str1 = "abac";
String str2 = "abac";
String str3 = "abad"; System.out.println(str1.compareTo(str2));
System.out.println(str1.compareTo(str3)); String str4 = "今天天气不错";
String str5 = "今天天气不错!!";
String str6 = "今天天气不错"; System.out.println(str4.compareTo(str5));
System.out.println(str4.compareTo(str6));
} }

结果:

(1)返回值为:0     对比结果相等因此返回0
(2)返回值为:-1    分析:因为abac跟abad之间最后一位c跟d比较缺少1位因此返回为-1。以此类推如果是abae返回-2,abaf返回-3  
(3)返回值为:-2    分析:最后2个字符明显多余对比的字符因此返回-2
(4)返回值为:0    对比结果相等因此返回0

字符串的用法实在很多,上述只是列举了最基础的一些方法,方便记忆。灵活应用才是王道。后续项目中遇到更复杂的会另外更新。

上一篇:MVVM架构~knockoutjs与MVC配合,实现列表的增删改功能


下一篇:在 case 语句中使用字符串-转