Java中String推断相等equals与==的差别以及StringBuilder的equals

Java中String类型具有一个equals的方法能够用于推断两种字符串是否相等,可是这样的相等又与运算符==所推断的“相等”有所不同,接下来进行分析,结论由程序进行验证

String的equals函数仅仅要两个字符串“看起来”相等,就能够返回true,“看起来”相等意思指的是,当两个字符串对象所存放的内容同样时,不须要存放的内存地址同样,可是==推断则仅仅有当推断的两个变量所使用的内存地址为同样时才返回true。比如有两个长得一模一样的双胞胎A,B,若使用A==B来推断会返回false。使用A.equals(B)则会返回true。

我们能够看object中的equals函数的源代码为

public boolean equals(Object obj) {
        return (this == obj);
    }

我们知道Java中全部的对象都默认继承自Object类。所以当我们没有重写equals的方法时,若使用equals来推断两个对象的是否相等时。仅仅有这两个对象指向的是同一个内存地址时。才会返回true,否则即使内容全然同样但在内存中是两个不同的内存地址也是返回false,此时若用双胞胎A,B来对照。A==B与A.equals(B)返回的都是false。

既然如此,那String的equals与==为什么会不一样呢,这里我们要看一下String中重写equals的源代码:

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        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函数首先推断其内存地址是否为同一个:

 if (this == anObject) {
            return true;
        }

然后再推断其内容是否同样:

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;
            }
        }

当我们使用字符串连接--连接方式一般为+或concat("substring")--的方式创建字符串时,都会构建一个新的String对象。即在内存中开辟一个新的地址来存放,所以这个时候即使内容同样。用==推断的话,也是返回false;当我们使用等号赋值时,若内存中有该字符串。则该变量指向此内存地址二不是又一次创建一个,所以此时用==时会返回true,我们看一下例程:

public class StringTest01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

			String hello="hello";
			String hel1=hello;
			String hel2="hel";
			String hel3=hel2+"lo";
			String hel4=hel2.concat("lo");
			
			System.out.println(hello);
			System.out.println(hel1);
			System.out.println(hel3);
			System.out.println(hel4);
			//==等号測试
			System.out.println(hello==hel1);
			System.out.println(hello==hel3);
			System.out.println(hello==hel4);
			System.out.println(hel3==hel4);
			
			//equals函数測试
			System.out.println(hello.equals(hel1));
			System.out.println(hello.equals(hel3));
			System.out.println(hello.equals(hel4));
			System.out.println(hel3.equals(hel4));
			
			//StringBuilder測试
			StringBuilder helloBuilder = new StringBuilder("hel");
			System.out.println(helloBuilder.equals(hel2));
	}

}

其输出结果为:


最后一个StringBuilder的測试我们发现尽管使用equals来推断,可是返回的是false。这是为什么呢?

首先。当我们使用StringBuilder创建对象时。肯定会在内存中开辟一个新的专属的地址用于存放对象内容。可是即使StringBuilder中存放的内容与其它字符串的内容同样,使用equals来推断也是返回false,这是由于StringBuilder并没有重写equals函数。即StringBuilder的equals为:

public boolean equals(Object obj) {
        return (this == obj);
    }
所以会返回false。



posted @ 2018-01-13 13:03  zhchoutai  阅读(2003)  评论(0编辑  收藏  举报