Java String学习

如要转载请标明作者zjrodger和出处:http://blog.csdn.net/zjrodger/,谢谢微笑

笔记目录
(·)String类
    1 .String类的字符串最大特点
    2 .String类对象的“==”和“equals()”方法的应用。
    3 .一个对象和两个对象引发的思考—— String对象的内存机制
    4 .字符串切割
    5 .字符串大小写转换。
        (1)用Character类, 逐个转换字符串中的单个字符。
        (2)用String类,toUpperCase()和tuLowerCase()方法。
    6 .去除字符串首尾两端的多个空格。
    7 .去关于 子字符串的一些方法应用。
(·)StringBuffer类
    1. StringBuffer的特点
    2.什么时候使用StringBuffer
    3.StringBuffer的常用方法
        (1存储
        (2删除
        (3修改
        (4将缓冲区中指定数据存储到指定字符数组中
(·)String和StringBuffer的区别
    1. 从值是否可变的角度讲。
    2. 从效率的角度讲
(·)StringBuilder类
    1. StringBuffer类和StringBuilder类的区别
     2. Java API升级的三方面因素
(·)基本数据类型对象包装类
(·)String类和int/float类型之间的相互转换
    1. String型转化为 int型或 float型 
    2. int型或 float型转化为 String类型 







(·)String类
1 .String类的字符串最大特点 :一旦字符串对象被初始化,该对象就不可以被改变。
    String类所有的返回String类型的方法,都是新创建一个字符串,而不是返回原来的被修改的字符串,因为“String类的字符串最大特点 :一旦字符串对象被初始化,该对象就不可以被改变。
例如:
String s1 ="abc";
s1 = "def";
分析:
上述虽然s1的对象引用变化了,但是“abc”的这个对象本身并没有发生改变,变化的变量s1所指向的对象的引用。
在内存中的机制:
在内存中的“堆”中创建了一个“abc”字符串对象,并且将该对象在内存中的地址赋值给s1变量。之后,在“堆”中创建了另外一个“def”字符串对象,并且将该对象在内存中的地址赋值给s1变量,原来的“abc”对象本身并没有发生变化。

2 .String类对象的“==”和“equals()”方法的应用。
【代码示例】
  String s1 = new String("abc");
  String s2 = new String("abc");
  String s3 = "abc";
  String s4 = "abc";
  System.out.println("s1 == s2, True or False: "+(s1 == s2));
  System.out.println("s1.equals(s2), True or False: "+s1.equals(s2));
  System.out.println("s1 == s3, True or False: "+(s1 == s3));
  System.out.println("s3 == s4, True or False: "+(s3 == s4));
代码运行结果
s1 == s2, True or False:  false
s1.equals(s2), True or False:  true
s1 == s3, True or False:  false
s3 == s4, True or False:  true

【代码分析
(1)“s1 == s2”方法。
    比较的是s1和s2两个对象的“在内存中的 地址值”,因此 s1 == s2 ------> False。
(2)“s1.equals( s2 )”方法。
    String类复写了Object类中的equals()方法,String类的equals()方法的作用是比较两个字符串的“ 内容”是否相同,因此,s1.equals( s2 )   ------> True。
(3)“s1 == s3”方法。
    “s1 ”在内存中,只有一个对象。“ s2”在内存中,有两个对象。因此,s1 == s3, True or False:  false
(4)“s3 == s4”方法。
    当创建s3时,创建完之后的对象会被存储在在常量池中,当要创建s4时,系统自动检测到“abc”这个对象已经存在了,为了减少内存浪费,就将s3对象的地址引用赋值给s4了。


3 .一个对象和两个对象引发的思考—— String对象的内存机制
在“ String对象的内存机制”这章中的描述:原来在堆内存中还有块叫"字符串常量池"的专门存放字符串的小区域。String str = new String("java");在堆中创建了一个“java”对象,在字符串常量池中也创建了一个“java”对象。
-----------------
书上原话是:
       使用new创建字符串对象的步骤如下。
1. 首先在堆(不是常量池)中创建一个包含指定内容的字符串对象,并将字符串引用指向该对象。
2. 去字符串常量池中查看,是否有包含该内容的对象。
3. 若有,则将new出来的字符串对象与字符串常量池中内容相同的对象联系起来。
4. 若没有,则在字符串常量池中再创建一个包含该内容的字符串对象,并将堆中的对象与字符串常量池中新创建出来的对象联系起来。
------------
可以通过 public   String   intern() 方法来检测:普通堆中的字符串对象 对应的 字符串常量池中的对象。
public   String   intern() 方法:是将指定字符串对象在字符串常量池中对应对象的引用返回。
---------------
这样做的目的是为了:提高字符串的比较速度。
书中原话是这样说的:
       字符串特殊的内存机制带来的好处,即是:不管字符串多长,其比较速度都是一样的。因为在比较两个字符串内容是否相同时,不必真去考察内容,只需比较两个字符串联系的常量池中对象是否为同一个即可。这也就 将对内容的比较转化为对引用的比较,大大提高了速度。

【代码示例】
String str1="abc"; 
String str2="abc";
String str3="abc";
String str4=new String("abc");
String str5=new String("abc");

【代码分析
(1)“str1 ”在内存中,只有一个对象。
(2)str3”在内存中,有两个对象。
(3) 对于浅蓝色箭头,通过new操作产生一个字符串(“abc”)时,会先去常量池中查找是否有“abc”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此“abc”对象的拷贝对象,所以,对于String str=new String("abc"),如果常量池中原来没有"abc"则产生两个对象,否则产生一个对象
(4) 对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。
    而对于字符串来说,其对象的引用都是存储在栈中的,如果是编译期已经创建好(即指用双引号定义的)的就存储在常量池中,如果是运行期(new出来的对象)则存储在堆中。对于equals相等的字符串,在常量池中是只有一份的,在堆中则有多份 。

【参考文档】
(1)java中的堆、栈和常量池: http://blog.sina.com.cn/s/blog_798b04f90100ta67.html
(2)为什么String str = new String("java");是创建了两个对象?: http://hi.baidu.com/juedui0769/item/9e8c43e709139b266cabb87d
(3)String类的源代码。
(4)毕向东Java基础视频,第十三天,Java String。

4 .字符串切割
(1)split()方法
public String[] split(String regex)
【代码示例】
   String s1 = "Zhangsan,Lisi,Wangwu"; 
   String[] strSplit = s1.split(",");
   for(int i=0; i<strSplit.length; i++){
   System.out.println(strSplit[i]);
   }  
代码运行结果
Zhangsan
Lisi
Wangwu

5 .字符串大小写转换。
(1)用Character类, 逐个转换字符串中的单个字符。
package com.itheima;
import java.io.*;

/**
 * 编写程序,从键盘接收一个字符串,对字符串中的字母进行大小写互转
 *(大写字母转成小写,小写字母转成大写)。
 */

public class Test8 {
	
	public static void main(String[] args) {

		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(System.in));
			System.out.print("Enter some characters: ");
			String content = br.readLine();			
			System.out.println("You entered: "+content);
			System.out.println("The Length of the String: "+content.length());
			
			
			//下循环的作用:
			//1.取出字符串中的每一个字符。
			//2.判断给该字符,
			//(1)若该字符位于“A--Z”之间,则转化为小写,并输出;
			//(2)若该字符位于“a--z”之间,则转化为大写,并输出;
			//(3)若该字符即不位于“a--z”之间,也不位于“A--Z”之间,则不对该字符进行任何处理,直接输出。
			for(int index=0; index<content.length(); index++) {
				char element = content.charAt(index);
				if(element>='A' && element<='Z') {
					System.out.print(Character.toLowerCase(element));
				}
				else if(element>='a' && element<='z') {
					System.out.print(Character.toUpperCase(element));
				}
				else {
					System.out.print(element);
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (IOException e2) {
				e2.printStackTrace();
			}
		}
	}
}


(2)用String类,toUpperCase()和tuLowerCase()方法。
注意:一个字符串的全部字符都转化成大写,或者小写。

6 .去除字符串首尾两端的多个空格。
(1)方法:trim()
(2)用途:用trim()方法 过滤用户输入的用户名等信息,使其符合输入要求。
(3)实现自己的trim()方法。
package com.zjrodger;
/**
 * 作用:
 * //练习一:实现自己的trim()方法,去除字符串两端空格)。
 * **/

class MyStringClass{
	
	//练习一:去除字符串两端空格
	//(方法一): 将目标String转化成字符数组,再开始寻找。
	public static String myTrim01(String stringParam){
		
		char[] charArray = stringParam.toCharArray();
		
		//找到字符串开头部分,空格字符的结束索引。
		int leadingSpaceEndIndex = 0;
		//找到了字符串开头部分,最后一个空格的index。
		int index01=0;
		
		//找到字符串结尾部分,空格字符的开始索引。
		int trailingSpaceStartIndex = 0;	
		//找到了字符串结尾部分,最开始的一个空格的index。
		int index02=charArray.length-1;

		//开始从前向后,寻找开头部分,最后一个空格的索引值。
		while(index01 <= index02 && charArray[index01] == ' '){
			++index01;			
		}
		leadingSpaceEndIndex = index01-1;
		
		//开始从后向前,寻找结尾部分,最有一个空格的索引值。
		while(index02 >= index01 && charArray[index02] == ' '){
			--index02;
		}
		trailingSpaceStartIndex = index02; 
		
		return stringParam.substring(leadingSpaceEndIndex+1, trailingSpaceStartIndex+1);		
	}	

	
	//练习一:去除字符串两端空格
	//(方法二): 不用将目标String转化成字符数组,而是使用charAt(int index)方法。
	public static String myTrim02(String stringParam){
		
		//找到字符串开头部分,空格字符的结束索引。
		int leadingSpaceEndIndex = 0;
		
		//找到字符串结尾部分,空格字符的开始索引。
		int trailingSpaceStartIndex = stringParam.length()-1;	
		
		//开始从前向后,寻找开头部分,最后一个空格的索引值。
		while( (stringParam.charAt(leadingSpaceEndIndex)) ==' ' && leadingSpaceEndIndex<=trailingSpaceStartIndex){
			++leadingSpaceEndIndex;
		}
		
		//开始从后向前,寻找结尾部分,最有一个空格的索引值。
		while((stringParam.charAt(trailingSpaceStartIndex)) ==' ' && leadingSpaceEndIndex<=trailingSpaceStartIndex){
			--trailingSpaceStartIndex;
		}		
		
		return stringParam.substring(leadingSpaceEndIndex, trailingSpaceStartIndex+1);
	}
}

public class StringTest01 {

	public static void main(String[] args) {
		System.out.println("(   123 456 789   )");
		String str01 = MyStringClass.myTrim01("   123 456 789   ");
		System.out.println("str01.length = "+str01.length()+"  They are:("+str01+")");
		String str02 = MyStringClass.myTrim02("   123 456 789   ");
		System.out.println("str02.length = "+str02.length()+"  They are:("+str02+")");
		
	}
}



7 .去关于 子字符串的一些方法应用。
(1)仅仅判断存在(子字符串是否存在于主字符串中)的常用方法:contains(CharSequence s);
(2)即判断存在又能得到位置的方法:indexOf(),若不存在则会返回“-1”。
(3)实现寻找子字符串在主字符串中出现的次数。
package com.zjrodger;

/**
 * 作用:
 * 练习二:寻找子字符串在主字符串中出现的次数。
 * **/
class MyString{	
	public static int subStrCount(String mainStr, String subStr){
		int counter = 0;
		//方法一
//		while( (mainStr.indexOf(subStr)) != -1 ){
//			mainStr = mainStr.substring( mainStr.indexOf(subStr)+subStr.length(), mainStr.length());
//			System.out.println("mainStr = "+mainStr);
//			++counter;
//		}

		//方法二:好处,不用再截取子字符串了,不会在内存中产生额外的字符串对象。
		int fromIndex = 0;
		while( (mainStr.indexOf(subStr, fromIndex)) != -1 ){
			++counter;
			fromIndex = mainStr.indexOf(subStr, fromIndex)+subStr.length();
		}		
		
		return counter;
	}
}

public class MySubStrCount {
	public static void main(String[] args) {	
		String originalStr = "fjfkklsajfdjskkafjkddskkajlfk";		
		System.out.println("Original String: "+originalStr);
		int counter = MyString.subStrCount(originalStr, "kk");
		System.out.println("The occurance times of KK = "+counter);
	}
}





(·)StringBuffer类
1. StringBuffer的特点
StringBuffer是一个容器,该容器具有缓冲作用,StringBuffer缓冲区的特点:
①长度是可变的。
②可以直接操作多个数据类型。
③最终会通过toString()方法变成字符串。

2.什么时候使用StringBuffer
当有待存储的数据的个数,类型不确定时,应该使用具有缓冲去功能的容器StringBuffer来存储。

3.StringBuffer的常用方法
StringBuffer作为一个容器,若具有的功能:增删改查( CRUD—— Create  Read  Update  Delete)。
(1存储
1) StringBuffer append():将指定数据作为参数添加到已有数据结尾处。
2) StringBuffer insert(index, 数据):可以将数据参入到指定index位置。

(2删除
1) StringBuffer delete(int start, int end):将指定数据从缓冲区中删除(不包含end)。
2) 清空StringBuffer缓冲区的代码: delete(0, sbObj.length());
3) StringBuffer insert(index, 数据):可以将数据参入到指定index位置。

(3修改
1) StringBuffer replace(int start, int end, String str)
2) void sb.setCharAt(2,'K');

(4将缓冲区中指定数据存储到指定字符数组中
1) void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin);



(·)String和StringBuffer的区别
1. 从值是否可变的角度讲。
String一旦定义后其值就不能改变,而StringBuffer相当于一个装字符串的可变容器,可以对装的内容进行增删改查等操作。
    StringBuffer is A thread-safe, mutable sequence of characters. A string buffer is like a String, but can be modified. At any point in time it contains some particular sequence of characters, but the length and content of the sequence can be changed through certain method calls. 

2. 从效率的角度讲
StringBuffer的append方法比“+”高效。
字符串连接操作中StringBuffer的效率要比String高:
每次使用String的 "+",都是new了一个新的String 对象,而StringBuffer 的append()方法,都是在原有的对象上进行的操作,例如下列代码:
String str = new String("welcome to ");
str += "here";
    上述处理步骤实际上是通过建立一个StringBuffer,然后调用append(),最后,再将StringBuffer toSting()。
这样的话String的连接操作就比StringBuffer多出了一些附加操作,当然效率上要打折扣。
并且由于String 对象是不可变对象,每次操作Sting 都会重新建立新的对象来保存新的值,这样原来的对象就没用了,就要被垃圾回收,这也是要影响性能的。
因此,当需要对字符串进行多次修改时,最好用StringBuffer。


(·)StringBuilder类
1. StringBuffer类和StringBuilder类的区别
StringBuffer类是线程安全的,StringBuilder类是线程不安全的。
若是单线程的,应该使用StringBuilder类,因为其效率高。
若是多线程的,应该使用StringBuffer类,因为其线程安全。

2. Java API升级的三方面因素
(1) 或者升级后的API,效率提高。
(2) 或者升级后的API,线程安全性提高。
(3) 或者升级后的API,简化书写。

StringBuilder类比StringBuffer类更加新,因此,在开发时,若是单线程的,应该使用StringBuilder类,因为其效率高。



(·)基本数据类型对象包装类
基本数据类型对象包装类最常见的包装作用:用于“基本数据类型”和“字符串类型”之间进行转换。
基本数据类型转换成字符串。——参考下列笔记“ 2. int型或 float型转化为 String类型”
字符串转化成基本数据类型。——参考下列笔记“ 1. String型转化为 int型或 float型 ”



(·)String类和int/float类型之间的相互转换

1. String型转化为int型或float型 

(1)说明 

    parseInt(), parseFloat()函数,是由Integer对象Float对象提供的方法,它可以将其它类型(尤指字符串String类型)的数据转化为对应的Int类型和Float类型。


(2)String类型转化成int/float类型的代码示例:

2.1) 将字符串String转化为int类型的整数

方法一:

System.out.println("请输学生年龄:");

String age_string = br.readLine();

int age = Integer.parseInt(age_string);

 方法二:

Integer age = Integer.valueOf(age_string);

返回一个Integer类型的实例


2.2)将字符串String转化为float类型的整数

方法一:

System.out.println("请输体重:");

Float weight = Float.parseFloat(br.readLine());

方法二:

Float f = Float.valueOf(weight); 返回一个Floatl类型的实例


(3总结将String型转化为int型或float型的方法:

方法一:Integer/Float.pareseInt/Float(String xxx);

方法二:Integer.valueOf(String xxx);

 

 

2. int型或float型转化为String类型

(1)需求环境:

    比如生成一个int类型的随机数A,并要将其通过BufferedWriter写入到磁盘上的文件“f:\\a.txt”中去。但由于BufferedWriter中的write()方法的参数只能是char类型或者String类型的,所以在将这个随机数A写入到磁盘之前,必须将这个随机数转化为String类型;

    再比如,在上网时,在文本框中输入的数字,一般都是String类型的,都需要程序在后台自动将String类型的转化成整数类型的数据。

 

(2)具体的转化代码为:

String a = Intger.toString(A);


(3)总结将一个整型转化为字符型所要用到的方法

3.1)Integer.toString(int a)方法

3.2)在整型后边加上空字符就可以了—+””

3.3)使用String.valueOf(int xxx)方法,可以将整型xxx转化为相应的字符串类型

 




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值