String类
String类对象一旦被初始化,就不可被改变了,在源码“private final char value[];”中发现用于存储字符串内容的value数组被final修饰,表示只能被赋值一次,不可被改变。
以下为常用方法,String类对象不可变,所以改变返回的都是新的字符串。
String str1 = "Makka Pakka";
System.out.println(str1.length()); //返回字符串长度
System.out.println(str1.charAt(0)); //返回索引处的字符
System.out.println(str1.indexOf("a")); //返回从头到尾首个‘a’的索引
System.out.println(str1.lastIndexOf("a")); //返回从头到尾最后个‘a’的索引
System.out.println(str1.replace('a','b')); //返回一个新的字符串 将所有a换为b
System.out.println(str1.substring(0,1)); //返回一个新的字符串,由str1指定索引处组成,[0,1)前闭后开
System.out.println(str1.toUpperCase()); //返回一个新的字符串,小写字母全变大写
System.out.println(str1.toLowerCase()); //返回一个新的字符串,大写字母全变小写
System.out.println(str1.startsWith("Makka")); //是否以...开头,返回boolean
System.out.println(str1.endsWith("Pakka")); //是否以...结尾,返回boolean
System.out.println(str1.trim()); //返回一个新的字符串,去除首尾空格
需要注意的是编译器会对字符串常量拼接进行优化
String str2 ="Hello "+"Makka Pakka";
//编译器进行优化,直接认为你写的就是String str2 ="Hello Makka Pakka";
String str3 ="Hello Makka Pakka";
System.out.println(str2==str3); //true都指向方法区的"Hello Makka Pakka"
常量池
常量池分为三种:全局字符串常量池(String Pool)、class文件常量池(Class Constant Pool)、运行时常量池(Runtime Constant Pool)。本篇简单说一下全局字符串常量池。
当类加载完成后,将字符串常量的引用值存入全局字符串常量池(String Pool),每个虚拟机只有一个全局字符串常量池。
String str4 = new String("Makka Pakka");
String str5 = "Hello";
String str6 = "Hello";
String str7 = str4.intern();
String str8 = "Makka Pakka";
System.out.println(str5==str6);//true
System.out.println(str7==str4);//false
System.out.println(str7==str8);//true
intern()方法是将该字符串在String Pool中的引用值返回,如果池中没有,则将该字符串的引用添加至String Pool中。
当执行第一句语句时,生成了两个不同的实例,一个是堆中的"Makka Pakka"实例对象,并且在String Pool中存储了它的引用,还有一个是new的
String对象。str4获得的是后者引用,而不是前者。
当执行第二句语句时,则只会在堆中生成"Hello"实例,并在String Pool有其引用。当执行str6该语句时,会先查找String Pool中是否存在"Hello"的引用,这里存在,所以直接拿来用,所以str5==str6为true,其本质为同一个实例对象。
当执行str7的语句时,用intern()方法获得了字符串"Makka Pakka"实例在String Pool中的引用值,但str4获得的是new的String对象的引用值,所以str7==str4为false。
而str8和str6同理,获得了字符串"Makka Pakka"实例在String Pool中的引用值str8==str7为true。