String类使用陷阱深度解析

String

在这里插入图片描述

doc

  • String类表示字符串。Java程序中的所有字符串文本(如“abc”)都作为此类的实例实现。
  • 字符串是常量;它们的值在创建后不能更改。字符串缓冲区支持可变字符串。因为字符串对象是不可变的,所以可以共享它们。例如:
String str = "abc";

相当于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);

以下是有关如何使用字符串的更多示例:

System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc".substring(2,3);
String d = cde.substring(1, 2);

  • 类字符串包括用于检查序列的单个字符、比较字符串、搜索字符串、提取子字符串以及创建字符串副本的方法,其中所有字符都转换为大写或小写。大小写映射基于Character类指定的Unicode标准版本
  • Java语言提供了对字符串连接运算符(+)以及将其他对象转换为字符串的特殊支持。字符串连接是通过StringBuilder(或StringBuffer)类及其append方法实现的。字符串转换是通过toString方法实现的,由Object定义并由Java中的所有类继承。
  • 除非另有说明,否则向此类中的构造函数或方法传递null参数将导致引发NullPointerException。
/*
返回字符串对象的规范表示形式。
字符串池最初是空的,由类String单独维护。
当调用intern方法时,如果池中已经包含一个与equals(object)方法确定的字符串对象相等的字符串,则返回池中的字符串。否则,此字符串对象将添加到池中,并返回对此字符串对象的引用。
因此,对于任何两个字符串s和t,s.intern()==t.intern()是真时则必须先满足s.equals(t)必须为真。
*/
    public native String intern();
/*重新Objectequals*/
  public boolean equals(Object anObject) {
        if (this == anObject) {
        	//引用一致
            return true;
        }
        //判断参数是否是String实例及其子类
        if (anObject instanceof String) {
        	//强转
            String anotherString = (String)anObject;
            int n = value.length;
            //如果两者长度相等
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                //每个字符是否相等
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

相等性的比较(==)

  • 对于原生数据类型来说,比较的是左右两边的值是否相等。

  • 对于引用类型来说,比较左右两边的引用是否指向同一个对象,或者说左右两 边的引用地址是否相同。

  • 对于 String 类的 equals() 方法来说,它是判断当前字符串与传进来的字符串的内容
    是否一致。

  • 对于 String 对象的相等性判断来说,请使用 equals()方法,而不要使用==。

  • String 是常量,其对象一旦创建完毕就无法改变。当使用+拼接字符串时,会生成新
    的 String 对象,而不是向原有的 String 对象追加内容。

public class StringTest2
{
	public static void main(String[] args)
	{
		String s1 = "hello";
		String s2 = " world";
		String s3 = s1 + s2;

		System.out.println(s3);
	}
}

陷阱解析

public class ObjectTest2
{
	public static void main(String[] args)
	{
		Object object = new Object();
		Object object2 = new Object();

		System.out.println(object == object2);//false

		System.out.println("----------------");


		String str = new String("aaa");
		String str2 = new String("aaa");

		System.out.println(str == str2);//false

		System.out.println("----------------");

		String str3 = "bbb";
		String str4 = "bbb";

		System.out.println(str3 == str4);//true
		
		System.out.println("----------------");

		String str5 = new String("ccc");//指向堆引用
		String str6 = "ccc";//指向字符串池

		System.out.println(str5 == str6);//false

		System.out.println("----------------");

		String s = "hello";
		String s1 = "hel";
		String s2 = "lo";

		System.out.println(s == s1 + s2);//两个引用相加 false

		System.out.println("----------------");

		System.out.println(s == "hel" + "lo");//两个常量相加 true


	}
}

String Pool(栈中字符串池)

String s = “aaa”;(采用字面值方式赋值)

  1. 查找 String Pool 中是否存在“aaa”这个对象,如果不存在,则在 String Pool 中创建
    一个“aaa”对象,然后将 String Pool 中的这个“aaa”对象的地址返回来,赋给引
    用变量 s,这样 s 会指向 String Pool 中的这个“aaa”字符串对象(此时创建0个对象)
  2. 如果存在,则不创建任何对象,直接将 String Pool 中的这个“aaa”对象地址返回来,
    赋给 s 引用。(此时创建一个对象)

String s = new String(“aaa”);创建几个对象?

  1. 首先在 String Pool 中查找有没有“aaa”这个字符串对象,如果有,则不在 String Pool
    中再去创建“aaa”这个对象了,直接在堆中(heap)中创建一个“aaa”字符串对
    象,然后将堆中的这个“aaa”对象的地址返回来,赋给 s 引用,导致 s 指向了堆中
    创建的这个“aaa”字符串对象。(此时创建了一个对象)
  2. 如果没有,则首先在 String Pool 中创建一个“aaa“对象,然后再在堆中(heap)创
    建一个”aaa“对象,然后将堆中的这个”aaa“对象的地址返回来,赋给 s 引用,
    导致 s 指向了堆中所创建的这个”aaa“对象。(此时创建两个对象)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章