String表示字符串类型,属于引用数据类型,不属于基本数据类型。String类由final关键字修饰,表示该类不能被继承。在Java中,String的对象可以通过直接赋值的形式进行实例化操作,也就是说在Java中,使用双引号""引起来的都是String的对象。字符串的字符使用Unicode进行编码,一个字符(不区分字母还是汉字)占两个字节。Java中规定,双引号括起来的字符串是不可变的,也就是说"abc"自出生到最终死亡,不可变,不能变成"abcd",也不能变成"ab"。注意:String s=null;和String s="";这两者有什么区别呢?答:前面的形式表示没有字符串对象,后面的形式表示有字符串对象但是没有内容。
在JDK中双引号括起来的字符串都是直接存储在方法区的字符串常量池中的,字符串常量池中是不会存储相同内容的字符串的,为什么SUN公司要把字符串存储在字符串常量池中呢,因为字符串在实际开发中使用太过频繁,为了执行效率,所以把字符串存储在方法区的字符串常量池中。下面是两个示例代码以及图解:
例1
- public class Stringtest {
- public static void main(String[] args) {
- //下面两行代码创建了三个字符串对象,都在字符串常量池当中
- String s1="abc";
- String s2="abc"+"xy";
-
- //凡是双引号括起来的都在字符串常量池中有一份
- //new对象的时候一定在堆内存中开辟空间
- String s3=new String("xy");
- }
- }
例2
- String s="abcde";
- s="xyz";
- //以上创建了两个对象
例3
- public class Stringtest {
- public static void main(String[] args) {
- String s1="hello";
- String s2="hello";
- //==双等号比较的是变量中保存的内存地址
- System.out.println(s1==s2);//输出true
- String s3=new String("xy");
- String s4=new String("xy");
- System.out.println(s3==s4);//输出false
- }
- }
使用初始化方式创建字符串对象时,JVM会先检查字符串常量池中是否存在相同的字符串,如果存在,则直接返回该字符串引用地址,如果不存在,则字符串存放到常量池中并返回字符串引用地址。上图中s1和s2指向一个字符串常量池中的hello,所以s1==s2为true
使用new关键字创建对象时,JVM同样会先到常量池中检查字符串是否存在,若存在,则在内存中创建一个字符串对象并返回对象引用地址,如果不存在,则在常量池和堆中依次创建字符串对象,返回该对象的引用地址。上图中s3和s4指向堆中不同的对象,虽然堆中的对象指向字符串常量池中同一个对象,但堆中两对象内存地址不同,所以s3==s4为false
所以为了保险起见,我们对比字符串时,会用字符串的equals方法来比较(字符串含有重写的equals方法,因为字符串属于引用类对象)
1 String s="xxx"
- String s1="我是中国人";
- System.out.println(s1);
- //输出:我是中国人
2 String(String original)
- String s2=new String("我是中国人");
- System.out.println(s2);
- //输出:我是中国人
3 String(char[] c)
- char[] c={'我','是','中','国','人'};
- String s3=String(c);
- System.out.println(s3);
- //输出:我是中国人
4 String(char[],int start,int length)
- char[] c={'我','是','中','国','人'};
- String s4=String(c,2,3);
- System.out.println(s4);
- //输出:中国人
5 String(byte[])
- byte[] b={65,66,67,68};
- String s5=String(b);
- System.out.println(s5);
- //输出:ABCD
6 String(byte[],int start,int length)
- byte[] b={65,66,67,68};
- String s6=String(b,1,2);
- System.out.println(s6);
- //输出:BC
7 String(StringBuffer buffer)
- StringBuffer sb1=new StringBuffer("我是河南人");
- String s7=String(sb1);
- System.out.println(s7);
- //输出:我是河南人
8 String(StringBuilder builder)
- StringBuilder sb2=new StringBuilder("我是湖北人");
- String s8=String(sb2);
- System.out.println(s8);
- //输出:我是湖北人
String类型与StringBuffer,StringBuilder类型的主要区别在于String类是不可改变的对象,StringBuffer和StringBuilder类的对象能够实现被多次修改,并且不产生新的未使用对象。因此,每次对String类型进行改变都相当于创建一个新的对象,然后将原引用地址指向新的对象,这样不仅效率低,而且浪费大量的内存空间,特别是当内存中没有引用的对象多了以后,JVM的GC会自动开始工作,程序的运行效率就会大大的降低。
在大量字符串拼接时,StringBuilder可以增加拼接效率
- public class Stringtest {
- public static void main(String[] args) {
-
- String s="";
- long start=System.currentTimeMillis();
- for(int i=0;i<100000;i++) {
- s+="a";
- }
- long end=System.currentTimeMillis();
- System.out.println(end-start);//输出:1627
- }
- }
- public class Stringtest {
- public static void main(String[] args) {
-
- StringBuilder s=new StringBuilder();
- long start=System.currentTimeMillis();
- for(int i=0;i<100000;i++) {
- s.append("a");
- }
- long end=System.currentTimeMillis();
- System.out.println(end-start);//输出:4
- }
- }
使用普通字符串拼接100000字符串耗时1627毫秒,而使用StringBuilder耗时4毫秒,两者效率差别很明显。因为在使用普通字符串拼接时,JVM会在每次拼接的时候new一个StringBuilder对象,那么普通拼接的100000次,就会new100000个StringBuilder对象,相比于使用一个StringBuilder对象拼接,效率就会大大降低,所以在大量字符串拼接时,要使用StringBuilder
方法名 | 作用 |
char charAt(int index) | 返回指定位置的字符串 |
int compareTo(String anotherString) | 比较两个字符串,相等返回0,前大后小返回1,前小后大返回-1 |
boolean contains(charSequence s) | 判断字符串是否包含s |
boolean endsWith(String suffix) | 判断字符串是否以suffix结尾 |
boolean equals(Object anObject) | 判断两个串是否相等 |
boolean equalsIgnoreCase(String anotherString) | 忽略大小写判断两个串是否相等 |
byte[] getBytes() | 将字符串变成字节数组返回 |
int indexOf(String str) | 返回str在字符串中第一次出现的位置 |
boolean isEmpty() | 判断字符串是否为空 |
int length() | 返回字符串长度 |
int lastIndexOf(String str) | 返回str最后一次出现的位置 |
String replace(CharSequence target,CharSequence replacement) | 用replacement替换字符串target的字符 |
String[] split(String regex) | 将字符串以regex分割 |
boolean startsWith(String prefix) | 判断字符串是否以prefix开始 |
String substring(int beginIndex) | 从beginIndex开始截取字符串 |
String substring(int beginIndex,int endIndex) | 截取beginIndex到endIndex-1的字符串 |
char[] toCharArray() | 将字符串转换成char数组 |
String toLowerCase() | 字符串转小写 |
String toUpperCase() | 字符串转大写 |
String trim() | 去除字符串两边空格 |
Static String valueOf(int i) | 将i转换成字符串 |