String类:
class StringDemo { public static void main(String[] args) { /* String s=new String(); String s=""; //以上两句话均创建空串 */ String s1="abc";//s1是一个类类型(引用)变量,"abc"是一个对象 //字符串最大特点:一旦被初始化就不可以被改变.(指的是该字符串对象) //s1="haha";//改变的是s1引用变量的指向 String s2=new String("abc"); //s1和s2有什么区别? //s1在内存中有一个对象 //s2在内存中有两个对象(new和"abc") /* new String("abc"): 通过new产生一个字符串(假设为”abc”)时, 会先去常量池中查找是否已经有了”abc”对象, 如果没有则在常量池中创建一个此字符串对象, 然后堆中再创建一个常量池中此"abc”对象的拷贝对象。 */ System.out.println(s1==s2);//s1,s2指向不同对象,对象内存地址不同 System.out.println(s1.equals(s2));//String类中复写了Object类中的equals方法 //该方法用于判断两个字符串是否相同(比较的是内容) } }/*
字符串存放在常量池(其中有数组存放字符)
abc存放在数组中
efg同理
abf会找到a b f拼成一个新的字符串.
*/
/*
常量存储在常量池,常量池也在方法区中
*/
关于常量池:http://baike.baidu.com/view/8680346.htmclass StringDemo { public static void main(String[] args) { String s1="abc"; String s2=new String("abc"); String s3="abc"; System.out.println(s1==s2);//false 用new String()创建的字符串不是常量, //不能在编译期就确定,所以new String() 创建的字符串不放入常量池中, //它们有自己的地址空间。 System.out.println(s1==s3);//true 因为"abc"对象已存在,存放在常量池 //且不能改变,节约内存->s1,s3指向同一个对象 //"abc"字符串常量在编译时期已经确定 } }
String类中常用的方法归纳:
/* String类适用于描述字符串事物. 那么它就提供了多个方法对字符串进行操作 常见的操作有?(API文档) "abcd" 1.获取. 1.1 字符串中包含的字符数->字符串长度 int length():获取长度 1.2 根据位置获取位置上的某个字符 char charAt(int index) 1.3 根据字符获取该字符的位置 int indexOf(int ch):返回的是ch在字符串中第一次出现的位置 //传入的为ASCII码 int indexOf(int ch,int fromIndex):从指定fromIndex位置开始,获取ch在字符串中的位置 int indexOf(String str, int fromIndex): 从指定fromIndex位置开始,返回指定子字符串(str)在此字符串中第一次出现的位置. int lastIndexOf(int ch):反向索引一个字符出现的位置 2.判断. 2.1 字符串中是否包含某一个子串 boolean contains(CharSequence); 特殊之处: indexOf(str):可以索引str第一次出现的位置.如果没有找到返回-1. 所以,也可以用于对指定判断是否包含 该方法既可以判断,又可以获取出现的位置 if(str.indexof("aa")!=-1) 2.2 字符串中是否有内容(空串) boolean isEmpty():原理就是判断长度是否为0 2.3 字符串是否以指定内容开头 boolean startsWith(str); 2.4 字符串是否以指定内容结尾 boolean endsWith(str); 2.5 判断字符串内容是否相同(不忽略大小写).复写了Object类中的equals方法 boolean equals(Object anObject); 2.6 判断内容是否相同,并忽略大小写 boolean equalsIgnoreCase(String str); 3.转换 3.1 将字符数组转成字符串 构造函数: String(char[]) String(char[],int offset,int count):当字符串足够长,知道该字符/字符串在靠后位置 //count
参数指定子数组的长度,将字符数组中的一部分转成字符串 静态函数: static String copyValueOf(char[]); static String copyValueOf(char[] data,int offset,int count) static String valueOf(char[]) ※3.2 将字符串转成字符数组 char[] toCharArray();//直接调用 "abcde".toCharArray(); 3.3 将字节数组转成字符串 String(byte[] bytes) 3.4 将字符串转成字节数组 byte[] getBytes(); 3.5 将基本数据类型转成字符串 static String valueOf(int); //3+"";等价于String.valueOf(3);->很麻烦 特殊:字符串和字节数组在转换过程中,是可以指定编码表的 */ class StringMethodDemo { //获取子串 public static void method_sub() { String s="abcdef"; sop(s.substring(2));//cdef sop(s.substring(2,4));//cd //2->4实际上是2->3 //如果利用substring获取整个字符串s.substring(2,s.length()); } //切割示例 public static void method_split() { String s="zhangsan.lisi.wangwu"; String[] arr=s.split("\\.");//.比较特殊 for(int i=0;i<3;++i) sop(arr[i]); /* zhangsan lisi wangwu */ } //替换示例 public static void method_replace() { String s="hello java"; String s1=s.replace('a','n');//字符串一经初始化不可改变,"hello,java"依然存在 sop("s="+s);// s=hello java //如果替换的字符不存在,返回的为原串 sop("s1="+s1);//s1=hello jnvn sop("hello java".replace("java","world"));//hello world } //转换示例 public static void method_trans() { char[] arr={'a','b','c','d','e','f'}; //char[] arr="abcdef";会报不兼容的类型 char[]与String String s=new String(arr); String s2=new String(arr,1,4); sop("s="+s);//abcdef sop("s2="+s2);//bcde } //判断示例 public static void methodIf() { String str="ArrayDemo.java"; //判断文件名称是否是Array单词开头 sop(str.startsWith("Array"));//true //判断文件名称是否是.java文件 sop(str.endsWith(".java"));//true //判断文件是否包含Demo sop(str.contains(".java"));//true } //索引示例 public static void main(String[] args) { String str="abcdefakpf"; sop(str.length());//10 sop(str.charAt(4));//当访问到字符串不存在的角标时会 //e //发生StringIndexOutOfBoundsException. sop(str.indexOf("akps",3));//如果没有找到返回-1(字符和字符串均是) //返回字符串首个字符位置 sop(str.lastIndexOf('a'));//从后往前索引,效率较高 //6 methodIf(); method_trans(); method_replace(); method_split(); method_sub(); } public static void sop(Object obj)//1.5版本后新特性(装箱)基本数据类型提升 { System.out.println(obj); //最终是obj所指向的对象调用 该对象所属类的toString()方法 } } /* 4.替换 String replace(char oldchar,char newchar); 它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。 String replace(CharSequence target, CharSequence replacement) 5.切割 String[] split(String regex);//已指定字符串切割 6.子串,获取字符串的一部分 String substring(begin);//从指定位置至结尾 String substring(begin,end);//包含头不包含尾 */
/* 7转换,去除空格,比较 7.1 将字符串转成大写或小写. String toUpperCase(); String toLowerCase(); 7.2 将字符串两端(开头和结尾)的多个空格去除. String trime(); 7.3 对两个字符串进行自然顺序的比较 int compareTo(string); */ class StringMethodDemo2 { public static void method_7() { String s=" Hello Java "; sop(s.toLowerCase()); sop(s.toUpperCase()); sop(s.trim()); String s1="a1d"; String s2="aac"; sop(s1.compareTo(s2));//'1'-'a'->49-97=-48 //该比较不忽略大小写 } public static void main(String[] args) { method_7(); } public static void sop(Object obj) { System.out.println(obj); } }
StringBuffer类与StringBuilder类:
package stringbuffer; /* StringBuffer是字符串缓冲区 是一个容器 1.而且长度是可变化的,数组一经分配固定的. 2.可以直接操作多个数据类型,而数组只能操作一种 3.最终通过toString变成字符串.
StringBuffer
上的主要操作是append
和insert
方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append
方法始终将这些字符添加到缓冲区的末端;而insert
方法则在指定的点添加字符。例如,如果
z
引用一个当前内容为 "start
" 的字符串缓冲区对象,则此方法调用z.append("le")
会使字符串缓冲区包含 "startle
",而z.insert(4, "le")
将更改字符串缓冲区,使之包含 "starlet
"。1.存储. StringBuffer append():将指定数据(int,boolean,String,Object...)作为参数添加到已有数据结尾处. StringBuffer insert(index,数据):可以将数据插入到指定index位置. 2.删除 StringBuffer delete(start,end):删除缓冲区中的数据,包含start,不包含end StringBuffer deleteCharAt(int Index) 3.获取(类似字符串操作) char charAt(int) int indexOf(String) int lastIndexOf(String) String substring(int start,int end); 4.修改 StringBuffer replace(start,end,String)//包含头不包含尾 void setCharAt(int index,char ch) //注意以上返回类型 5.反转 StringBuffer reverse(); 6.void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将缓冲区中数据复制到指定字符数组中 String中也有 */ class StringBufferDemo { public static void method_getChars() { StringBuffer sb=new StringBuffer("abcdef"); char[] ch=new char[6]; sb.getChars(1,4,ch,2); for(int i=0;i<ch.length;++i) System.out.println("ch["+i+"]="+ch[i]); /* ch[0]= ch[1]= ch[2]=b ch[3]=c ch[4]=d ch[5]= */ } //修改 public static void method_update() { StringBuffer sb=new StringBuffer("abcde"); sb.replace(1,4,"java");//包含头不包含尾->ajavae sb.setCharAt(2,'h');//ajhvae sop(sb.toString()); } //删除示例 public static void method_del() { StringBuffer sb=new StringBuffer("abcde"); sb.delete(1,3);//包含头不包含尾 //ade //清空缓冲区 //sb.delete(0,sb.length());//删除所有 sb.delete(2,2);//依然是原串 //ade sb.deleteCharAt(2);//删除单个字符 //ad sop(sb.toString()); } //添加示例 public static void method_add() { StringBuffer sb=new StringBuffer(); sb.append("abc").append(true).append(12);//方法调用链 //abctrue12 sb.insert(1,"qq"); //一直在操作同一个对象sb //aqqbctrue12 sop(sb.toString()); } public static void main(String[] args) { method_getChars(); method_update(); method_del(); method_add(); } public static void sop(String str) { System.out.println(str); } } /* toString()复写了Object中的: public String toString() 返回此序列(StringBuffer中的序列)中数据的字符串表示形式。 分配一个新的 String 对象,并将它初始化, 以包含当前由此对象表示的字符串序列。 然后返回此 String。对此序列的后续更改不影响该 String 的内容. */ /* StringBuffer与StringBulider JDK1.5 版本以后出现了StringBuilder StringBuffer是线程同步 StringBuilder是线程不同步 单线程情况下->判断锁->StringBuffer效率低于StringBuilder 将 StringBuilder 的实例用于多个线程是不安全的。 如果需要这样的同步,则建议使用 StringBuffer。 JDK升级三个因素: 1.提高效率 2.提高安全性 3.简化书写 */
String方法经典练习:
package stringtest; //1.模拟一个trime方法,去除字符串两端的空格 class Trime { public static String newTrime(String str) { int start=0,end=str.length()-1; //从头至尾扫描,直至出现非空格为止 while(start<=end&&str.charAt(start)==' ')//第一个条件防止全是空格 ++start; //start<=end条件必须放在前面,因为当start>end时 //JVM无法取值判断->StringIndexOutOfBoundsException //从尾至头扫描 while(start<=end&&str.charAt(end)==' ')//当str全为空格,start为end+1,该循环不再执行 --end; return str.substring(start,end+1); } public static void main(String[] args) { String s=" ab c "; System.out.println(s+"\n"+newTrime(s)); } } //2.讲一个字符串进行反转.将字符串中指定部分进行反转 // 例如:"abcdefg" // "abfedcg" cdef->fedc class StrReverse { //功能细分(注意这个思想) public static void swap(char[] ch,int x,int y) { char temp; temp=ch[x]; ch[x]=ch[y]; ch[y]=temp; } //反转 public static void reverse(char[] ch,int start,int end) { for( ;start<end-1;++start,--end)//start=end无需交换 例如:cdefg->都指向e swap(ch,start,end-1); //end-1一般包含头不包含尾 } public static String StrReverse(String str,int start,int end) { //将字符数组->变成字符串 char[] ch=str.toCharArray(); //反转 reverse(ch,start,end); //将字符串->字符数组 //return String.copyValueOf(ch); return String.valueOf(ch); //return new String(ch); } //全部翻转 public static String StrReverse(String str) { return StrReverse(str,0,str.length()); } public static void main(String[] args) { String s="abcdefg"; System.out.println(s+"\n"+StrReverse(s)+"\n"+StrReverse(s,0,2)); } } //3.获取一个字符串在另一个字符串中出现的次数. /* 算法思想: 用indexOf从指定位置开始索引看字符串是否存在 */ class StrStr { public static int getCount(String strA,String strB) { int count=0,strBLength=strB.length(),strALength=strA.length(); int pos=0; //利用indexOf找寻子串位置 while((pos=strA.indexOf(strB,pos))!=-1) { ++count; pos+=strBLength;//从下个位置索取 } return count; } public static void main(String[] args) { String s1="abcdefgdehfcdefghdef",s2="def"; System.out.println(getCount(s1,s2)); } } //※4.获取两个字符串中最大相同子串. /* 算法思想: 假设有A,B两个串, 对于B串: ①A.contains(B)==true 返回 否则转② ②B.length()-1,尾指针-1,首指针-尾指针之间的字符串,是否被A包含,包含返回 不包含,首指针++,尾指针++->判断尾指针<=B.length()-1->大于则B.length()-1长度 的子串索引完毕 ③B.length()-2,重复②直至B.length()>0 (画示意图) */ class MaxSubstring { public static String maxSubstr(String strA,String strB) { //产生一个问题,如果strB为长串那么循环次数将非常大 //因此在遍历前确定谁长谁短->减少循环次数 String str,maxStr=strA,minStr=strB; if(strB.length()>strA.length()) { maxStr=strB; minStr=StrA; } int length=minStr.length(); for(int i=length;i>0;--i)//控制子串长度 for(int start=0,end=i;end!=length+1;++start,++end)//对相同长度子串进行查找 { str=minStr.substring(start,end); if(maxStr.contains(str))//或者使用if(strA.indexOf(str)!=-1) return str; } return ""; } public static void main(String[] args) { System.out.println(maxSubstr("abcdefgh","defgh")); } }
关于第四个练习:画个示意图
基本数据类型对象包装类:
/* 基本数据类型对象包装类 例如:整数有多种表现形式(十进制,十六进制..) 整数变成对象,功能封装,操作方便. 也就是说把对整数操作的一些方法封装成类 基本 类 byte Byte short Short int Integer boolean Boolean float Float double Double char Character 基本数据类型对象包装类的最常见作用 就是用于基本数据类型和字符串类型之间做转换 1.基本数据类型->转成字符串 基本数据类型+""基本数据类型.toString(基本数据类型) 如:Integer.toString(34);//将整数34->"34" 2.字符串->基本数据类型 基本数据类型 a=类.parseXxx(String); double a=Double.parseDouble("3.14"); Boolean b=Boolean.parseBoolean("true"); 或 Integer i=new Integer("123");//通过构造函数 int number=i.intValue();//123 3.十进制转成其他进制 Integer.toBinaryString(int)//返回String Integer.toHexString(int) Integer.toOctalString(int)
Integer.toString(数据,指定基数) 4.其它进制转为十进制 Integer.parseInt("1011",2); */ class IntegerDemo { public static void sop(String str) { System.out.println(str); } public static void main(String[] args) { sop("int max "+Integer.MAX_VALUE); //讲一个字符串转成整数(double,long等同理) int num=Integer.parseInt("123"); sop("num="+(num+4));//num=127 //转换 sop(Integer.toBinaryString(10));//1010 sop("1010十进制: "+Integer.parseInt("1010",2));//10 sop(Integer.toString(20,2));//10100 } }
JDK1.5版本新特性:
/* JDK 1.5出现的新特性 */ class IntegerDemo2 { public static void method() { Integer i1=new Integer(12);//也可以传入十六进制/八进制 Integer i2=new Integer("12"); System.out.println(i1==i2);//false,两个对象内存地址不同 System.out.println(i1.equals(i2));//true 12==12 } public static void main(String[] args) { method(); Integer i=new Integer(4); Integer x=4;//4等价于Integer.valueOf(4)隐式转换 //自动装箱 //x=null; //x可以取null,那么下面x=x+2运行失败,nullPointerException x=x+2;//x+2:x 进行自行拆箱.变成int 和2进行加法运算 //再将和装箱赋给x //实际上x=Integer.valueOf(x.intValue()+2); Integer y1=127; Integer y2=127; System.out.println("x==y: "+(y1==y2)); /* 注意:结果为true. 因为a和b指向了同一个Integer对象 因为数值在byte范围内容,对于新特性,如果该数值已存在,则不会在 开辟新空间 */ } } /* 有助于理解: 在Integer.java中 private final int value; 构造函数: public Integer(int value) { this.value = value; } public Integer(String s) throws NumberFormatException { this.value = parseInt(s, 10); } //equals方法: public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; } //intValue方法: intValue(){ return value; } //valueOf方法(装箱调用) public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } */
分析拆箱装箱一篇很不错的博文:http://blog.csdn.net/jairuschan/article/details/7513045
最后解析下:
/* public static void sop(Object obj)//1.5版本后新特性(装箱)基本数据类型提升 { System.out.println(obj); //最终是obj所指向的对象调用 该对象所属类的toString()方法 } 解析:如果传入int型的值相当于->obj=new Integer(int ) 多态 System.out.println(obj)内部是怎么执行的? ①查看java.io.PrintStream中的println方法 void println(Object x): 打印 Object,然后终止该行。 此方法首先调用 String.valueOf(x) 获取打印对象的字符串值 ②查看java.lang下的String类valueOf方法: public static String valueOf(Object obj) 如果参数为 null,则字符串等于 "null";否则, 返回 obj.toString() 的值 也就是: 如果obj=new Integer(int )->也就是调用Integer类中的toString方法 ③Integer类中的toString: 将该参数转换为有符号的十进制表示形式,并以字符串的形式返回它 ->最终转换成字符串 */