Java字符串(笔记16)

Java字符串

一、String 类

public final class String {}   //前面的final 证明String类是不可继承的
字符串是常量;它们的值在创建之后不能更改

//常见例子
1、如何把字符数组转成字符串 
char [] c ={'中','国','人'} ;
String str=new String( c );  //用字符数组做为String类的构造函数的参数
2、如何把一个字符串转成字符数组
String str="这是一个字符串" 
char [] array =str.toCharArray();
3、如何把一个字符串转成字节数组
byte [] array =str.getBytes();  //请思考
  
字符串创建的两种方式
1) String str="abc" ; 
2) String str=new String("abc");
  
说明 
1) 用方式一创建的String ,它会先在常量池中查找,看看有没有abc这个常量,如果有,直接把str指向常量池中的abc,
如果没有,则在常量池中创建 abc 这个常量,再将str指向它 
String str="abc" ; 
String newStr="abc" 这两个操作,一共创建了一个对象(常量池中) 和两个引用 (str,newStr)

2) 用方式二创建的String ,相当于先做第一步(String str="abc") , 然后在堆上开辟一个内存空间,将 new String("abc")
后产生的实体放在堆上,然后再把str指向堆上的实体
String str=new String("abc") 执行以后,创建了两个对象内存上有两份实体(常量池中一份,堆上一份) ,一个引用,
也就是说,当有new String () 这样的操作的时候,不管是否曾经创建过这个String对象,一概要在堆上进行创建

二、字符串的比较

例1:字符串常量池的使用
String s0 = "abc"; 
String s1 = "abc"; 
System.out.println(s0==s1);   //s0 和 s1 都指向了同一个地址(常量池中的)

例2:String中 == 与equals的区别 
String s0 =new String ("abc"); 
String s1 =new String ("abc"); 
System.out.println(s0==s1); //false 
System.out.println(s0.equals(s1)); //true 因为String类重写了equals

例3:编译期确定  
String s0="helloworld"; 
String s1="helloworld"; 
String s2="hello" + "word";  //编译的时候,直接将它编译成了 helloworld
System.out.println( s0==s1 );  //true
System.out.println( s0==s2 );  //true

例4:编译期无法确定 
String s0="helloworld"; 
String s1=new String("helloworld"); 
String s2="hello" + new String("world"); 
System.out.println( s0==s1 ); //false , s0指向常量池,s1指向了堆
System.out.println( s0==s2 ); //false
System.out.println( s1==s2 ); //false

例5:编译期优化
String s0 = "a1"; 
String s1 = "a" + 1; 
System.out.println((s0 == s1)); //true
String s2 = "atrue"; 
String s3= "a" + true; 
System.out.println((s2 == s3)) //true
String s4 = "a3.4"; 
String s5 = "a" + 3.4; 
System.out.println((s4 == s5)); //true

例6 编译期无法确定
String s0 = "ab"; 
String s1 = "b"; 
String s2 = "a" + s1;   //程序不运行,编译器是无法确定 变量 s1的值的
System.out.println((s0 == s2));  //false
         
例7:编译期确定
String s0 = "ab"; 
final String s1 = "b";   
String s2 = "a" + s1;  
System.out.println((s0 == s2)); //true
   
//附例 回忆:
byte a=10;
byte b=5;
byte c=a+b;   //编译出错
final a=10;
final b=5;
byte c=a+b; //ok

三、String对象内存分析

//例一
String a = "abc"; ①  
String b = "abc"; ②  
分析:
①代码执行后在常量池(constant pool)中创建了一个值为abc的String对象,
②执行时,因为常量池中存在 "abc" 所以就不再创建新的String对象了。
    
//例二
String   c   =   new   String("xyz");①  
String   d   =   new   String("xyz");②  
分析:
①Class被加载时,"xyz" 被作为常量读入,在常量池(constant pool)里创建了一个共享的值为 "xyz" 的String对象;
然后当调用到new String("xyz")的时候,会在堆(heap)里创建这个new   String("xyz")对象;
②由于常量池(constant pool)中存在"xyz"所以不再创建"xyz",然后创建新的new String("xyz")。
    
//例三
String   s1   =   new   String("xyz");     //创建二个对象(常量池和堆中),一个引用    
String   s2   =   new   String("xyz");     //创建一个对象(堆中),并且以后每执行一次创建一个对象,一个引用   
String   s3   =   "abc";     //创建一个对象(常量池中),一个引用     
String   s4   =   "abc";     //不创建对象(共享上次常量池中的数据),只是创建一个新的引用s4)
    
//例四 
public class TestStr {  
public static void main(String[] args) {    
//以下两条语句创建了1个对象。"凤山"存储在字符串常量池中    
String str1 = "凤山";    
String str2 = "凤山";     
System.out.println(str1==str2);//true     
       
//以下两条语句创建了3个对象。"天峨",存储在字符串常量池中,两个new String()对象存储在堆内存中     
String str3 = new String("天峨");     
String str4 = new String("天峨");     
System.out.println(str3==str4);//false      
      
//以下两条语句创建了1个对象。9是存储在栈内存中   //这里所说的一个对象,是指的9 , i 和 j 则是对9的引用  
int i = 9;     
int j = 9;     
System.out.println(i==j);//true      
       
//由于没有了装箱,以下两条语句创建了2个对象。两个1对象存储在堆内存中    
Integer l1 = new Integer(1);    注意这里是没有装箱操作的
Integer k1 = new Integer(1);    
System.out.println(l1==k1);//false  
     
//以下两条语句创建了1个对象。1对象存储在栈内存中。自动装箱时对于值从127之间的值,使用一个实例。    
Integer l = 20;//装箱     
Integer k = 20;//装箱     
System.out.println(l==k);//true    
    
Integer i1 = 256;     //以下两条语句创建了2个对象。i1,i2变量存储在栈内存中,两个256对象存储在堆内存中   
Integer i2 = 256;     
System.out.println(i1==i2);//false  

四、String 类常见操作

//获取类操作
String str="春花秋月何时了,往事知多少?小楼昨夜又东风,故国不堪回首月明中";
1 这个字符串到底有多长 
str.length();
2 第4个字是什么  即根据索引获取字符    
str.charAt(3);  ->月
3 第一个逗号是第几个字符 即根据字符取索引 ( 取字符(或字符串)的位置) 
str.indexOf(',');  //可以接收字符型参数
str.indexOf(",");  //可以接收字符串型参数
str.indexOf("往事");
4 最后一个“月”字的索引
str.lastIndexOf("月"); //22
str.lastIndexOf('月');
5 是否含有“月明”  这个字符序列
str.contains("月明");
6 是不是以"春花"开头,是否以“月明中”结尾
str.startsWith("春花")  //true
str.endsWith("月明中");  //true
str.endsWith("秋月");  //false
7 判断这个串是否为空
str.isEmpty();
8 和另一个串相比是否相等
str.equals("另一个串");
str.equalsIgnoreCase("aaa")   //这个方法比较的时候不区分大小写
System.out.println(s1.toUpperCase().equals(s2.toUpperCase()));   //都变成大写以后再比

//例子  查询符合条件的文件 周老师教的,java相关的,第七课的
String [] fileList={"lession7://a.bmp","b,exe","lession7//周老师_01.java","d.doc","x.java","lession7//周老师_02.java"};
for (int i = 0; i < fileList.length; i++) {
String temp=fileList[i];
if(temp.startsWith("lession7")&&temp.contains("周老师")&&temp.endsWith(".java")){
System.out.println(temp);
}
}

//转换类操作
//字符数组转成字符串
--String(char[]) 
--String(char[] value, int offset, int count)  =>char [] array={ '广',  '阔', '天', '地' ,'大' ,'有', '作', '为' };
String str=new String(array,4,4); //从第四个开始,取4个,得到 大有做为
--stattic String copyValueOf(char[] data) 
--stattic String copyValueOf(char[] data, int offset, int count) 
--static String valueOf(char[]);    

//字符串转成数组 (字节数组,字符数组)
--char []  toCharArray()  //把字符串转成字符数组
--byte[] getBytes();  //把字符串转成字节数组
         
//基本数据类型,转成字符串
方式一   9 +""
方式二  String.valueOf(90); // => "90"
String.valueOf(true); // =>"true"
        
//切割替换类操作
-- String replace(CharSequence target,  CharSequence replacement)
str=str.replace("东风", "西风"); //有多少,换下来多少,前面的str= 不要忘写
str=str.replace(" ", "");  //把字符串中所有的空格都去掉

//例子-- String[] split
String str="1_45_69_10";
String [] array= str.split("_"); 

//例子 使用正则表达式进行拆分的
String str="aa245ac345b90saf43550";
String [] array= str.split("\\d+");   // \d 在正则表达式中代表数字,+代表这个数字可以有一到多个
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
结果  aa
ac
b
saf

//例子
String str=aaa.bbb.ccc.ddd 或 str= aaa|bbb|ccc|ddd 这样的字符串,如果按 . 或 |
拆分的时候,不要忘了加 \\进行转义,如下
String [] array=str.split("\\|");
 
-- String substring(int beginIndex)    
//例子
String str ="你们好";
str= str.substring(2);  //好  从指定的索引往后取
  
-- String substring(int beginIndex,  int endIndex) 
//从beginIndex 取到 endIndex  (含头不含尾)
String str ="一二三四五六";
str= str.substring(2,3);  //三
   
-- String toUpperCase();   //转大写
-- String toLowerCase();   //转小写 
-- String trim();  //去两端空格
-- int compareTo(String)

五、StringBuffer 和 StringBuilder 

StringBuffer 字符串缓冲区 ,它的内容可变,可以认为它是一个容器,这个容器中的内容是可变的 java.lang包中
存储
StringBuffer buff=new StringBuffer("中国");
等价于
StringBuffer buff=new StringBuffer();
buff.append("中国");

//例子
StringBuffer s1=new StringBuffer();
StringBuffer s2=s1.append("中国"); 
System.out.println(s1.toString());  //中国
System.out.println(s2.toString());  //中国
 
关于StringBuffer的效率问题
// 例一 使用String类
public static void main(String[] args) {
long begin= System.currentTimeMillis();
String str = "";
for (int i = 0; i < 10000; i++) {
str+=i;
}
long end= System.currentTimeMillis();
System.out.println("程序一共执持了 "+(end-begin) +" 毫秒");  //大约700左右
}
// 例二 使用StringBuffer
long begin= System.currentTimeMillis();
StringBuffer buf=new StringBuffer();
for (int i = 0; i < 100000; i++) {
buf.append(i);
}
long end= System.currentTimeMillis();
System.out.println("程序一共执持了 "+(end-begin) +" 毫秒");  //大约15ms
结果  StringBuffer的效率,远远高于String 

删除
StringBuffer delete(int start,  int end)  //清空缓冲区 sb.delete(0,sb.length())
StringBuffer deleteCharAt(int index)
 
获取
char charAt(int index)
int indexOf(String str)
int lastIndexOf(String str)
String subString(int index,int end)
从哪索引开始    到哪个索引               从数组的哪开始存
void getChars(int srcBegin,  int srcEnd,  char[] dst,   int dstBegin); 将缓冲区的数据存到指定的字符数组里 //buff.getChars(2, 3, c, 3);                                             

修改
StringBuffer replace(start,end,String)
void setCharAt(int index,char ch);
StringBuffer reverse();

StringBuilder jdk1.5 以后出现的 它的用法和StringBuffer 相同
区别   StringBuffer 线程安全(慢), StringBuilder 线程不安全(快)

六、BigDecimal类的应用

它是java.math包下的
Bigdecimal 的构造函数
BigDecimal(int)       创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
BigDecimal(long)    创建一个具有参数所指定长整数值的对象。
BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。 

常用方法
add(BigDecimal)        BigDecimal对象中的值相加,然后返回这个对象。
subtract(BigDecimal)  BigDecimal对象中的值相减,然后返回这个对象。
multiply(BigDecimal)  BigDecimal对象中的值相乘,然后返回这个对象。
divide(BigDecimal)     BigDecimal对象中的值相除,然后返回这个对象。
toString()                将BigDecimal对象的数值转换成字符串。
doubleValue()          将BigDecimal对象中的值以双精度数返回。
floatValue()             将BigDecimal对象中的值以单精度数返回。
longValue()             将BigDecimal对象中的值以长整数返回。
intValue()               将BigDecimal对象中的值以整数返回。

//例子
String x="34540560670495696";
String y="234356090450325823435";
BigDecimal a=new BigDecimal(x);
BigDecimal b=new BigDecimal(y);
BigDecimal result=a.multiply(b);
System.out.println(result);  //8094790760699656102236190010823435760
     
格式化及例子
由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,
可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。
以利用BigDecimal对货币和百分比格式化为例。
-- 首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,
-- 最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比

七、字符串工具类

见 StringUtils.java,对于Java工程开发人员而言是必备的了解内容

八、字符串相关记录

1 下面的语句执行后,内存中有几个对象
 String s1="小泉纯一狼"; 
 String s2=new String ("小泉纯一狼");   //2 个对象,一个在堆上,一个在常量池中
 System.out.println(s2==s1); //false
 
2.字符串的操作:
 写一个方法,实现字符串的反转,如:输入abc,输出cba
 写一个方法,实现字符串的替换,如:输入bbbwlirbbb,输出bbbhhtccc。
 
3 String 和 StringBuffer 的区别
JAVA平台提供了两个类:String和StringBuffer,它们可以储存和操作字符串,即包含多个字符的字符数据。
这个String类提供了数值不可改变的字符串。而这个StringBuffer类提供的字符串进行修改。
当你知道字符数据要改变的时候你就可以使用StringBuffer。典型地,你可以使用StringBuffers来动态构造字符数据。
另外,String实现了equals方法,new String(“abc”).equals(new String(“abc”)的结果为true,而StringBuffer没有实现 equals 方法,
所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的结果为false。

4 String s = "Hello"; s = s + "?world!"; 这两行代码执行后,原始的String对象中的内容到底变了没有  //没有

5 下面这条语句一共创建了多少个对象:String s="a"+"b"+"c"+"d";  //1个 编译期优化,直接编译成 String s="abcd"

6 如何把一段逗号分割的字符串转换成一个数组
 "aaa,b,cd,ef"   =>   "aaa,b,cd,ef" .split(",");  => String [] 类型
         

猜你喜欢

转载自blog.csdn.net/weixin_41205479/article/details/80172997