String

String

​ Java中通过String类来创建和操作字符串数据。

1.String实例化

​ 1.直接赋值

String str1="Hello Word!";

​ 2.通过构造函数创建对象

String str2=new String("Hello Word!");

2.String两种实例化方法的区别

​ 首先,我们来看一段代码:

String str1="Hello Word!";
String str2=new String("Hello Word!");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));

​ 结果是false和true;由此可见,str1和str2指向的是不同的内存地址,但是两个字符串的值相等。(双等比较的是字符串的地址,而String类重写的equals方法比较的是字符串的值)

​ 然后,我们来看如果都用直接赋值的方式进行比较:

String str1="Hello Word!";
String str2="Hello Word!";
System.out.println(str1==str2);
System.out.println(str1.equals(str2));

​ 结果是true和true;由此可见,str1和str2指向的是相同的内存地址,而且两个字符串的值是相等的。

​ 最后,让我们来看看都用构造函数的方式创建对象。

String str1=new String("Hello Word!");
String str2=new String("Hello Word!");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));

​ 结果是false和true;由此可见,str1和str2指向的是不同的内存地址,但是两个字符串的值相等。

​ 直接赋值进行实例化的方式:在堆内存的字符串常量池中分配空间存储字符串,在栈内存中存储引用变量,只有String可以直接赋值进行实例化,其他类必须new一个对象出来才能完成实例化。String类的设计使用了共享设计模式,JVM底层会自动维护一个字符串常量池。直接赋值的方式在创建对象时,会先判断是否已经存在该实例化对象,如果没有,就会创建实例化对象保存在字符常量池中。如果有的话,就会直接引用。(两次直接赋值如果内容相同则会指向同一字符串对象。)

​ 使用构建函数的方式实例化String对象:String str2=new String("Hello Word!");由于“Hello Word”也是一个String对象,因此,JVM会先在堆上创建一个“Hello Word!”字符串,再讲这个字符串复制一份并由str指向,这就导致出现了垃圾空间(”匿名String对象“Hello Word!”),并且如果采用构造方法的话,也不会将该字符串对象加入到JVM的“字符串常量池”中,导致字符串共享问题。

​ 垃圾空间:如果使用String的构造方法就会开辟两块堆内存空间,并且其中一块堆内存将会变成垃圾空间。(字符串常量“Hello Word!”也是一个匿名对象,使用一次之后就不在使用,就成了垃圾空间,会被JVM自动回收);字符串共享:同一个字符串可能被存储多次,比较浪费空间。

​ 为了解决“字符串共享”问题,可以使用String类的intern()方法将构造方法方法方式创建的String对象手动加入到“字符串常量池”中。

String str1=new String("Hello Word!").intern();
String str2="Hello Word!";
System.out.println(str1==str2);

​ 这时候的返回值是true,我们可以得到结果str1和str2指向的是同一个地址。即str1创建的对象入了JVM中的字符串常量池中,str2在字符串常量池中找到了“Hello Word!”,所以直接指向了改地址。

​ 结论:

​ 1.直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。

​ 2.构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,默认不会自动保存在对象池中,可以使用intern()方法手工入池;但是并没有解决垃圾空间的问题。

​ 总结,我们一般使用直接赋值的方式实例化String对象。

3.String的常用方法

方法 描述
public String (char value[]) 将一个char数组转换为字符串对象
public String (char value[],int offset,int count) 将一个指定范围的char数组转换为字符串对象
public String (byte value[]) 将一个byte数组转换为字符串对象
public String (byte value[],int offset,int count) 将一个指定范围的byte数组转换为字符串对象
public int length() 获取字符串长度
public boolean isEmpty() 判断字符串是否为空
public char charAt(int index) 返回指定下标的字符
public char[] toCharArray() 返回char类型数组
public byte[] getBytes() 返回byte类型数组
public boolean equals(Object anObject) 判断两个字符串是否相等
public boolean equalsIgnoreCase(Object anObject) 判断连个字符串是否相等(忽略大小写)
public int compareTo(String value) 对字符串进行排序(比较ASCII长度)
public int compareToIgnoreCase(String value) 对字符串进行排序(比较ASCII长度,忽略大小写)
public boolean startsWith(String value) 判断字符串是否以value开头
public boolean endsWith(String value) 判断字符串是否以value结尾
public int hashCode() 返回字符串的hash值
public int indexOf(String str) 返回str在字符串中的下标
public int indexOf(char a) 返回a在字符串中的下标
public int indexOf(String str,int fromIndex) 从指定位置开始查找,返回str在字符串中的下标
public int indexOf(char a,int fromIndex) 从指定位置开始查找,返回a在字符串中的下标
public String subString(int beginIndex,int endIndex) 截取字符串
public String concat(String str) 追加字符串
public String[] split(String regex) 用指定的字符串对目标字符串进行分割,返回数组
public String toLowerCase() 字符串转小写
public String toUpperCase() 字符串转大写

​ 注意:

​ 1.前四个方法是构造方法的重载,使用的时候要注意。

​ 2.null和空是两个概念。空是指对象存在,但是没有内容,长度为0;null是指对象不存在,引用地址为空(栈里面有,但是对里面没有)。这也就解释了为什么当String为null的时候调用isEmpty()会报空指针异常,因为isEmpty()是实例化方法,而null对象不存在。

​ 3.下标是从0开始的!

​ 4.返回字节数组和返回char类型数组方法名有很大区别,且字节数组中存储的是ASSII码值。

​ 5.compareTo返回的是两个字符串的ASCII差值。

public int compareTo(String anotherString) {
    byte v1[] = value;
    byte v2[] = anotherString.value;
    if (coder() == anotherString.coder()) {
        return isLatin1() ? StringLatin1.compareTo(v1, v2)
                          : StringUTF16.compareTo(v1, v2);
    }
    return isLatin1() ? StringLatin1.compareToUTF16(v1, v2)
                      : StringUTF16.compareToLatin1(v1, v2);
 }

​ 6.public int indexOf(String str)默认查找首先出现的str的下标;如果没有返回负数。

​ 7.public String subString(int beginIndex,int endIndex)截取的字符串,包含beginIndex,不包含int endIndex

​ 8.public String concat(String str)并没有对原字符串进行修改,返回了一个匿名字符串。

​ 9.public String[] split(String regex)使用的时候要注意指定的字符串是否要写成转义字符形式。常见应用场景:不同手机可能有数量不等的描述标签,如果每个标签都在设计数据库的时候设计出来,可能会造成浪费,就可以在数据库中就设置一个标签,然后使用某个字符将标签连接起来,使用的时候再拆分。

public class Demo5 {
    public static void main(String[] args) {
        //构造函数类型
        char[] arrayChar={'H','e','l','l','o'};
        String strChar1= new String(arrayChar);
        String strChar2=new String(arrayChar,1,2);
        System.out.println(strChar1);
        System.out.println(strChar2);

        byte[] arrayByte={'H','e','l','l','o'};
        String strByte1=new String(arrayByte);
        String strByte2=new String(arrayByte,1,2);
        System.out.println(strByte1);
        System.out.println(strByte2);

        String str="Hello Word!";
        String str1="";
        String str2="Hello Word!";
        String str3="hello word!";
        //获取字符串的长度
        System.out.println(str.length());

        //判断字符串是否为空
        System.out.println(str1.isEmpty());

        //返回指定下标的数值
        System.out.println(str.charAt(1));

        //返回char类型数组
        char[] charArray=str.toCharArray();
        for(int i=0;i<charArray.length;i++){
            System.out.print(charArray[i]+" ");
        }
        System.out.println();

        //返回byte类型数组
        byte[] byteArray=str.getBytes();
        for(int i=0;i<byteArray.length;i++){
            System.out.print(byteArray[i]+" ");
        }
        System.out.println();

        //判断两个值是否相等
        System.out.println(str.equals(str2));
        System.out.println(str.equals(str3));

        //判断两个值是否相等(忽略大小写)
        System.out.println(str.equalsIgnoreCase(str3));

        //比较ASCII差值
        System.out.println(str.compareTo(str2));
        System.out.println(str.compareTo(str3));

        //判断字符串是否以某个字符串开始
        System.out.println(str.startsWith("H"));

        //判断字符串是否以某个字符串开始
        System.out.println(str.endsWith("H"));

        //返回str的hashcode值
        System.out.println(str.hashCode());

        //返回字符串/字符在str中的下标
        System.out.println(str.indexOf("He"));

        //从指定位置开始查找符串/字符在str中的下标
        System.out.println(str.indexOf("l",3));

        //从指定位置开始截取
        System.out.println(str.substring(1,3));

        //追加字符串
        System.out.println(str.concat("aaaaa"));

        //用指定的字符串对目标字符串进行分割,返回数组
        String str4="Hello,Word,!,Java";
        String[] strArray=str4.split(",");
        for(int i=0;i<strArray.length;i++){
            System.out.print(strArray[i]+" ");
        }
        System.out.println();

        //字符串转小写
        System.out.println(str.toLowerCase());

        //字符串转大写
        System.out.println(str.toUpperCase());
    }
}

4.参考博客

​ 参考博客:https://blog.csdn.net/weixin_43490440/article/details/101164178


原文地址:https://www.cnblogs.com/wind-and-sky/p/15505588.html