一 String常用类 类
String 类 称为不可变字符序列,(源码中修饰符为private final);
StringBuilder类 可变字符序列,线程不安全(源码中有append方法)
Stringbuffer类 可变字符序列,线程安全(synchronized:源码中的线程保护关键字)
1 String类的赋值方法:
(1): 直接赋值: String str1=“whvo”;
此处“whov” 是常量,直接放进常量池(在jdk1.7之后常量池放在了堆中)
(2):调用构造器: String str2=new String(“nihk”);
此处常量池内并没有“nihk”,而是直接将字符串传值给了String 构造方法作为参数,直接放到value的数组中去。 但是如果调用intern方法,会在常量池中创建nihk的引用(如果常量池中已存在nihk这个常量,则会指向它,)
两种赋值方法的内存分析如图: (只要是常量,一律放到常量池中去)
2:特殊赋值内存分析:
String str3=new String(“he”)+new String("llo"); 创建三个对象, String str4=new String("he")+"llo"; 创建两个对象,第一个是he,第二个是hello,str4指向第二个对象; String str5= "abcd"+"ef" // str5直接在编译时等于abcdef,并且将abcdef存在常量池中; String str6="abcde";// 同上 str6=str6+“f”;// 编译时知道str6+f=abcdef,因为常量池中已经存在abcdef,所以直接指向abcdef 同时,本例也体现了String的不可变性,是通 过开辟新的内存指向来改变原来的的值
3:intern()方法(jdk1.8中):
intern():如果在常量池当中没有字符串的引用,那么就会生成一个在常量池当中的引用,相反:则不生成
public static void main(String [] args){
String string=new String("abcd")+new String("efg"); // 在堆中产生三个对象,string只指向合并后生成的那个"abcdefg"对象;
String str2="abcdefg"; // 在常量池中找,没有“abcdefg”,所以生成一个此常量对象,str2指向此对象
string.intern(); // 在常量池中找,已经存在“abcdefg”这个常量对象,故不生成引用
System.out.println(string==str2); // >>>>>>>> false // 两个对象的地址不一样,故false
}
public static void main(String [] args){
String string=new String("he")+new String("llo"); // 在堆中产生三个对象,string只指向合并后生成的那个"hello"对象;
string.intern(); // 在常量池中找,没有“hello”这个常量对象,所以生成常量引用,和堆中那个对象的地址相同
String str2="hello"; // 常量池中已经存在这个常量对象的引用,所以str2指向这个引用,所以str2也指向string对象
System.out.println(string==str2); // >>>>>>>> 地址一样,内容一样,所以true
}
4:改变String 字符串的原理:
String类本身 是不可变字符序列,要想改变他的值,内存上是重新指向新的内存地址,在底层源码中,实际上是将先创建一个Stringbuilder对象,然后调用Stringbuilder对象的append()方法将字符串添加进去
String str1="abcdef";
String str5="";
StringBuilder builder =new StringBuilder("abcd"); // 此方法可以避免产生多余对象,只需要产生一个SrteingBuilder对象;
for( int i=0;i<str1.length();i++) {
builder.append(str1.charAt(i));
str5=builder.toString(); // 将StringBuilder 类型的字符串调用toString()方法传给String类型的字符串st2;
}
5: String类中的常用方法:
String a=new String("abcd");
String b=new String("abcd");
System.out.println(a.charAt(2));//截取目标字符串中下标为2的字符
char[] str4=new char[10]; //首先建立char类型的字符数组对象
"abscsdfsf".getChars(2, 6, str4, 0);//截取目标字符串中下标从2开始到6之前(包括2不包括6)的字符存在str4中
System.out.println(str4);
String str5="get out".substring(4,7 ); //仍然是截取目标字符串的方法,
System.out.println(str5);
System.out.println(a.equals(b));//只比较内容是否相等
System.out.println(a==b);//除了比较内容还比较对象地址,所以false
String str1="def";
String str2="def";
System.out.println(str1.equals(str2));
System.out.println(str1==str2);
System.out.println(str1.indexOf('f'));//索引,返回第一个f的下标,如果字符串中没有索要检索的字符,将返回-1;
System.out.println("abcadas".lastIndexOf(a));//索引,返回最后一个a下标
String str3= str2.replace('e','a');//替换,将e用a替换并放到新的字符串str3中去
System.out.println(str3);
System.out.println("ABC".equalsIgnoreCase("abc"));//忽略大小写比较字符串内容是否相等
System.out.println("AbCd".toLowerCase());//变为小写
System.out.println("AbCd".toUpperCase());//变为大写
char[] array="goodbay mylover".toCharArray();//将字符串转换成字符数组
for(int i=0;i<array.length;i++) {
System.out.print(array[i]);
}