String类中equals底层代码分析

在String类中很常用的方法之一就是equals()方法,它可以判断两个字符串是否相同,知其然更要知其所以然,知道了它的作用后为了以后能更好的使用它,我们以举几个示例来来分析一下底层代码。

1.第一个示例

package equals;

public class Test {

	public static void main(String[] args) {
		String name1="Tom";
		String name2="Tom"
		System.out.println(name1.equals(name2));
	}
}

按住Ctrl键点击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;
    }

第1行:当name1调用该方法时,将String类型变量name2作为参数传入方法,这里可以了解到是一个对象上转型,由Object类型变量指向一个String类型对象name2。

第2行:由于是name1调用的该equals方法,所以this代指的是name1对象,所以这条语句的作用是比较name1和anObject的地址是否一致,也就是比较name1和anObject指向的name2的地址是否一致,在本例中由于name1和name2都是直接赋值的Tom字符串,所以地址是一致的,所以equals方法执行到此便进入if代码块返回true,然后方法结束。

2.第二个示例

如果赋值的是两个不同的字符串如下:

package equals;

public class Test {

	public static void main(String[] args) {
		String name1="Tom";
		String name2="Sam"
		System.out.println(name1.equals(name2));
	}
}

这时我们再来分析一下底层代码:

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

第1行:还是一个对象上转型,由Object类型变量指向一个String类型对象name2。

第2行:比较的是name1和name2的地址是否相同,这时由于name1和name2是不同的字符串,所以地址显然不相同,此处返回false,跳出if判断条件。

第5行:因为anObject是个上转型对象,指向的是String类型的name2,所以anObject属于String类,即该判断条件返回true,执行if代码块。

第6行:新定义一个String类型变量anotherString,将anObject对象下转型为String类,用anotherString来指向anObject中的name2,这样后面就可以调用String类中的方法了。

第7行:定义一个整型n赋值为字符数组value的长度,这里的value是一个String类中的全局变量,创建String类对象name1时value便被赋值成存储name1字符串的字符数组了。

第8行:用name1创建的对象里value存放的是name1字符串,那用anotherString对象调用value自然存储的就是name2的字符串了,该语句用来判断name1和name2字符串的长度是否一致,该示例中返回值为true,所以执行if代码块。

第9、10行:定义两个字符串数组v1和v2存放两个字符串的字符数组value。

第11行:定义整型i用于遍历字符数组。

第12行:进入判断两字符串是否一致的循环中,循环次数为n,也就是字符串长度,如果在遍历中有一位字符不相同就返回false结束方法,这里的name1和name2第一个字符就不同,所以执行第一次就返回false结束方法。

3.第三个示例

当两个相同的字符串采用了两种不同的方式创建对象,就像下面这样,虽然输出结果一样,但是在底层里代码的执行情况却不一样:

package equals;

public class Test {

	public static void main(String[] args) {
		String name1="Tom";
		String name2=new String("Tom");
		System.out.println(name1.equals(name2));
	}
}

还是打开刚才的底层代码:

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

第2行:此时虽然name1和name2的字符串相同,但是由于name1中的Tom字符串是存储在堆的常量池中,而name2中字符串是直接存储在堆中,所以地址并不相同,于是该处返回false,跳出if代码块。

第12行:此处在遍历字符数组时,二者每一个字符都一样,所以一直到循环结束。

第17行:返回true表达字符串相同。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值