字符串和字符串池
一、字符串
1.字符串的创建
(1)直接创建:String s="Hello";
(2)new创建:String s=new String("Hello")
要注意空字符串和null是不相同的
public static void main(String[] args) { String s1=""; String s3=new String(); String s2=new String("");
String s4=null; System.out.println(s1.equals(s2)); //s1、s2相等都是空字符串 System.out.println(s2.equals(s3)); //s2、s3相等 System.out.println(s3.equals(s4)); //s1、s2、s3与s4不相等! }
除了new ("Hello")中的类型之外,还能有如下方式:
String s1="Hello1"; String s2=new String(s1); char []c={'H','e','l','l','o','2'}; String s3=new String(c); //但不能String s3=new String({'H','e','l','l','o'}); byte []b={'H','e','l','l','o','3'}; String s4=new String(b); StringBuffer sb=new StringBuffer(new String("Hell04")); String s5=new String(sb); StringBuilder sbu=new StringBuilder(new StringBuffer("Hello5")); String s6=new String(sbu); System.out.println(s1+s2+s3+s4+s5+s6);
可以看出还可以以byte[]、char[]、String、StringBuffer、StringBuilder均可作为String构造函数的参数。
(3)vauleOf()创建
普通数据类型 String s1=String.vauleOf(true);或者是int bl=54;String s1=String.vauleOf(bl);直接将其转换为String.
引用数据类型通过调用成员方法toString()来将对象转换为字符串。对于System.out.println(obj);若obj==null则会返回null。
Object o=null; System.out.println(o); //输出null字符串
System.out.println(o.toString()); //运行抛出异常java.lang.NullPointerException
否则等同于语句System.out.println(obj.toString());
//toString()方法
再来探讨一下toString()方法,如果调用它的是一个字符串对象包括String、StringBuffer、StringBuilder则会返回当前字符串,如果是基础数据的引用,例如Integer、Character、Boolean则会返回对应的int、char、boolean等对应的数据字符串。如果是其他类对象,重写toStirng()方法就不说了,但是未重写方法就会输出"包名.类名@哈希码十六进制"(此处包含数组)。
class A { } public class Strings { public static void main(String[] args) { A a=new A(); A a0=new A(); System.out.println(a.toString()); System.out.println(a0); } }
输出:
arraytest.A@70dea4e
arraytest.A@5c647e05
//System.out.println()方法
而我们常用的System.out.println()方法其实就是将参数转化为字符串,而主要方法就是(3)中的构造方法,若是基本类型,就使用vauleOf(),若是非null引用类型就调用toString(),若是null类型数据就返回null(null不能直接作为参数,只能是某对象指向null,然后打印此对象的形式);
class A { } class B { public String toString() { return "BB"; } } char []c={'H','e','l','l','o','2'}; //数组 StringBuffer sb=new StringBuffer(new String("Hell04")); //字符串对象 Integer i=9; //基本类型的包装类 boolean bl=false; //基本数据类型 Object o=null; //null A a=new A(); //非null无重写 B b=new B(); //非null有重写 System.out.println(c); //打印Hello2 System.out.println(c.toString()); //打印[C@70dea4e,地址 System.out.println(i); //9,调用toString() System.out.println(bl); //false,调用valueOf() System.out.println(o); //null,无法使用toString() System.out.println(a); //地址 System.out.println(b.toString()); //BB
值得一提的就是字符串数组,在直接打印时会输出字符串内容,但在调用toString()方法时会打印地址[C@70dea4e,而其余类型数组都会打印地址[就是包名,C就是类名?
(4)直接+
两个直接字符串相加。String s1="123"+"456"
字符串和其他相加时会采用和println相同的策略
byte []b={'H','e','l','l','o','3'};
Object o=null; String s1="123"+new Integer(456); String s2="123"+o; String s3="123"+false; String s4="123"+b; System.out.println(s1); //123456,调用toString() System.out.println(s2); //123null System.out.println(s3); //123false,调用valueOf() System.out.println(s4); //123[B@70dea4e,调用toString()
仍然来重点看一下字符数组,在+连接符下,会直接调用toString()从而返回其地址,不会访问其内容,编程与其他类型数组一样。
2.字符串的操作
(1)public String concat(String str)进行拼接操作,若str是空字符串,则还返回原来的引用。
public static void main(String []args) { String s1="123"; String s2="456"; System.out.println(s1); System.out.println(s1.hashCode()); s1=s1.concat(s2); System.out.println(s1); System.out.println(s1.hashCode()); }
输出:123
48690
123456
1450575459 可以看出若str不为空就会返回一个新的引用。
(2)String replace(char oldChar,char newChar)将所有oldChar字符替换为newChar,String toLowerCase()、String toUpperCase()转换大小写,String trim()去空白字符,对于这些方法来说若不改变原有字符串的,例如replace()不含oldChar,转换成小写的不含小写字符串,或不含空白字符等就不会修改原引用。String substring(int beginIndex)和String substring(int beginIndex,int endIndex)是截取从第beginIndex+1到结束的子字符串和从第beginIndex+1到nedIndex的子字符串。
(3)format()方法,先不赘述
(4)int length()返回长度,boolean isEmpty()返回是否为空,char charAt(int index)返回第index+1的字符;
int indexOf(int ch)查找ch第一次出现的位置,若不含此字符,返回-1,不要误以为写错了,确实是参数为int类型,这里指的是Unicode码。int indexOf(int ch,int fromIndex)功能相同但需要从大于等于fromIndex的下标(注意和第几个区分)开始查找。int indexOf(String str)前提是str是子字符串,返回第一个字符的下标,int indexOf(String str,int fromIndex)类似。
int lastIndexOf(int ch)、int lastIndexOf(String str)返回最后一个符合条件的字符下标、最后一个符合的字符串的第一个下标,int lastIndexOf(int ch,int fromIndex)和int lastIndexOf(String str,int fromIndex)返回小于等于fromIndex的最后一个下标或字符串的第一个下标。(语文不好(lll¬ω¬),还是上例子吧)
String s="abcabcdabcde"; System.out.println(s.indexOf('b')); //1 System.out.println(s.indexOf('b',1)); //1,Ifirst('b')=1>=1,返回1
System.out.println(s.indexOf('b',2)); //4,Ifirst('b')=1<1,寻早下一个b,Ifirst('b')=4>=1,返回4
System.out.println(s.indexOf("abc",0)); //0 System.out.println(s.indexOf("abc",1)); //3,判断abc字串首字符a字符下标和1的大小,若Ifirst('a')>=1,返回Ifirst('a'),否则找到下一个abc字符串再判断直到符合 System.out.println(s.indexOf("ab",-1)); //0,第二个参数小于0与等于0等价与没有第二个参数等价 System.out.println(s.lastIndexOf("ab")); //7 System.out.println(s.lastIndexOf('c',8)); //5,若Ilast('c')<=8,则返回Ilast('c'),可以看出9>8不符合,寻找下一个5符合 System.out.println(s.lastIndexOf("abc",7)); //7,先倒着找出“abc”字符串,然后判断Ilast('a')=7<=7,所有返回7 System.out.println(s.lastIndexOf("abc",29)); //7,任何大于字符串长度的第二参数与没有第二参数等价
其中的Ifirst('a')表示正向查找a字符符合条件的下标,Ilast自然是指逆序查找下标。
(5)字符串的比较int compareTo(String another) (参数不能是null???),返回值第一个不相同字符unicode码差值,若两一个字符串是另一字符串字串,返回字符串长度差值,若两串相同则返回0.此外还有int compareToIgnoreCase(String another)比较方法与其类似,但忽略掉大小写。
判断两字符串相等不能用等号==(后面长篇幅介绍)要用boolean equals(Object anObj)你没看错正是Object类型的参数,但你用其他对象做参数他返回false,即使是StringBuffer对象也一样,null可以作为参数但会永远返回false,因为调用此成员方法永远不会是null。boolean equalsIgnoreCase(String another)忽略大小写。
(6)将字符串转为基本类型parseXxx.例如转为double型 public static double parseDouble(String s) throws NumberFormatException 可以看出要想转换为double你的字符串必须要符合相应格式。但有一个例外parseBoolean除非字符串是“true”或“TRue”等返回true,其余均返回false,也就是说可以不符合格式。注:char类型可以直接由charAt方法获得。
转换为byte数组public byte[] getBytes()、转换为字节数组public char[] toCharAyyay()。
二、字符串池(重点)
(1)直接赋值:String s="123456";先查找字符串池中是否有该字符串,若没有则创建一个对象,并返回。若有此字符串直接返回。【创建1个对象】
(2)new创建:String s=new Stirng("123456");先查找字符串池中是否有该字符串,若有直接在堆中new一个对象并返回,没有就在字符串中先创建一个,然后再在堆中new一个返回。【创建2个对象】
(3)+连接两个字符串:String s="123"+"456";分别判断字符串“123”和"456"在字符串池中是否存在,若不存在就创建一个。然后判断连接后的字符"123456"在字符串池中是否存在,若不存在就创建。【3个对象】
(4)+连接对象和对象或连接对象和字符串:String s1="123";String s2=s1+"456"; String s3="456";String s4=s1+s3;具体情况有待证实,应该是先创建"123"对象(包括判断),然后创建“456”对象,…………
(5)new字符串对象或+连接:String s1="123456";String s2=new(s1); String s3="123";String s4=new String(s3+"456");
(6)intern()方法:若字符串池中有字符串直接返回,否则创建一个对象。
String s="123456"; String s1="123456"; String s2=new String("123456"); String s3="123"+"456"; String s4="123"; String s5=s4+"456"; String s6="456"; String s7=s4+s6; String s8=new String(s1); String s9=new String(s4+"456"); System.out.println(s1==s); //true System.out.println(s1==s2); //false System.out.println(s1==s3); //true System.out.println(s1==s5); //false System.out.println(s1==s7); //false System.out.println(s1==s8); //false System.out.println(s1==s9); //false System.out.println(s==s2.intern()); //true System.out.println(s2==s2.intern());//false System.out.println(s2.intern()==s5.intern());//true
可以总结一下,赋值字符串直接量和几个字符串直接量的连接和相同字符串的intern()返回值都是相等的,其余方法都是互不相等且与上述几种不相等。