String对象创建后则不能被修改,是不可变的,所谓的修改其实是创建了新的对象,所指向的内存空间不同。如
下图所示:
运行结果:
结合上面的代码,关于字符串必须要了解的:
1)通过String s1="爱慕课"; 声明了一个字符串对象, s1存放了到字符串对象的引用,在内存中的存放引用关系如
下图所示:
然后通过s1="欢迎来到:"+s1; 改变了字符串s1 ,其实质是创建了新的字符串对象,变量s1指向了新创建的字符
串对象,如下图所示:
2)一旦一个字符串在内存中创建,则这个字符串将不可改变。如果需要一个可以改变的字符串,我们可以使用
StringBuffer类或者StringBuilder类。
3) 每次 new 一个字符串就是产生一个新的对象,即便两个字符串的内容相同,使用 "==" 比较时也为 ”false” ,如
果只需比较内容是否相同,应使用 "equals()" 方法。s3和s4 都是通过new 在堆内存中创建的新对象,有各自的地址,
而==比较的就是地址,所以为false。
实例:
public class Test { public static void main(String[] args) { String s1 = "imooc"; String s2 = "imooc"; //定义字符串s3,保存“I love”和s1拼接后的内容 String s3="I love"+s1; // 比较字符串s1和s2 // imooc为常量字符串,多次出现时会被编译器优化,只创建一个对象 System.out.println("s1和s2内存地址相同吗?" + (s1 == s2)); //比较字符串s1和s3 System.out.println("s1和s3内存地址相同吗?" +(s1==s3)); String s4 = "I love " + s1; //比较字符串s4和s3 // s1是变量,s4在运行时才知道具体值,所以s3和s4是不同的对象 System.out.println("s3和s4内存地址相同吗?" + (s4 == s3)); } }
编译运行结果:
解释:
S1是将字符串存在常量池中,所以它的地址是常量池给的。同样S2也是常量池给的地址,地址都是字符串常
量"imooc"的地址,所以s1和s2的地址是一样的。然而s3是一个常量加上一个变量,因此是存在堆内存中,这个地址
是堆内存新给s3的。同理,s4的地址也是堆内存给他的。因此s3和s4的内存地址是不一样的。
String 类提供了许多用来处理字符串的方法,例如,获取字符串长度、对字符串进行截取、将字符串转换为大写
或小写、字符串分割等。
public class Test{ public static void main(String[] args){ String s1 = "sun java"; String s2 = "sun Java"; System.out.println(s1.charAt(1));//u System.out.println(s2.length());//8 System.out.println(s1.indexOf("java"));//4 System.out.println(s1.indexOf("Java"));//-1 System.out.println(s1.equals(s2));//false System.out.println(s1.equalsIgnoreCase(s2));//true String s = "我是程序员,我在学java"; String str = s.replace('我','你'); System.out.println(str); } }运行结果:
实例代码:
public class Test{ public static void main(String[] args){ String s = "Welcome to Java World!"; String s1 = " sun java "; System.out.println(s.startsWith("Welcome"));//true System.out.println(s.endsWith("World"));//false String sL = s.toLowerCase(); String sU = s.toUpperCase(); System.out.println(sL); System.out.println(sU); String subs = s.substring(11); System.out.println(subs); String sp = s1.trim(); System.out.println(sp); } }
运行结果:
注意事项:
1)字符串s2中字符的索引从0开始,范围为 到str.length()-1。
2)使用indexOf进行字符或字符串查找时,如果匹配返回位置索引;如果没有匹配结果,返回 -1。
3)使用substring(beginIndex , endIndex)进行字符串截取时,包括beginIndex位置的字符,不包括endIndex位置的
字符。
静态重载方法
public static String valueOf(...)可以将基本类型转换为字符串
例如:
public static String valueOf(double d) public static String valueOf(int i)
方法public String[] split(String regex)可以将一个字符串按照指定的分隔符分割,返回分割后的字符串数组。
实例代码:
public class Test{ public static void main(String[] args){ int j = 1234567; String sNumber = String.valueOf(j); System.out.println("j 是"+sNumber.length()+"位数"); String s = "Mary,F,1976"; String[] split = s.split(","); for(int i=0;i<split.length;i++){ System.out.println(split[i]); } } }
运行结果:
1)==: 判断两个字符串在内存中首地址是否相同,即判断是否是同一个字符串对象。
2)equals(): 比较存储在两个字符串对象中的内容是否一致。
这两个的用法我们在前面已经多处的用到,在这里就不再详细举例说明他们的异同,想要详细了解的可以参考脚
本之家的文章:java中equals和等号(==)的区别浅谈。