字符串判等整合

版权声明:本文出自孤星卟哭的博客,原创文章,转载请注明出处。 https://blog.csdn.net/zcy92949/article/details/79930223

前言

字符串判等分很多情况,随着不断地加深学习,遇到了很多出乎意料的结果,在此做一个积累,便于日后添加和查阅。

1、equals()和”==”二者的比较

public class EqualsPractice {
    /**
     * 注:输出语句中,如果比较语句中不加两边的括号会把前面的文字吃掉,这是运算符优先级问题,
     * 程序会先执行+,字符串拼接之后才会进行比较
     */
    public void getSummary() {
        /*
         * EqualsPractice中没有重写equal()方法,所以比较的是地址
         */
        EqualsPractice c = new EqualsPractice();
        EqualsPractice c1 = new EqualsPractice();
        System.out.println("c.equals(c1):" + c.equals(c1)); //false

        /*
         * String类中重写了equal()方法,所以比较的是字面量;而==比较的是地址
         */
        String c2 = new String("abc"); //new String("abc")存放在堆中,c2存放在栈中(堆栈通常指栈)
        String c3 = new String("abc");
        System.out.println("c2.equals(c3):" + c2.equals(c3)); //true
        System.out.println("c2 == c3:" + (c2 == c3)); //false

        /*
         * 常量比较中,"=="和equal()方法比较的都是地址
         */
        String s = "abc"; //"abc"存放在常量池中,s存放在栈中
        String s1 = "abc";
        System.out.println("s == s1:" + (s == s1)); //true
        System.out.println("s.equals(s1):" + s.equals(s1)); //true
    }

    public static void main(String[] args) {
        EqualsPractice objSum = new EqualsPractice();
        objSum.getSummary();
    }
}

这是去年二月十六号第一次接触判等时记录的笔记,当时觉得自己终于掌握判等了,直到后来我才知道原来自己会的只是冰山一角。

2、String中的intern()方法

public void getSum() {
    /**
     * 一个String变量调用intern()方法时,JVM查找常量池中是否有相同的字符串常量,
     * 如果存在,会将等号左边的值指向常量池此地址,但是并不会改变等号右边原字符串的地址指向。
     * 
     * 注:输出语句中,如果比较语句中不加两边的括号会把前面的文字吃掉,这是运算符优先级问题,
     * 程序会先执行+,字符串拼接之后才会进行比较
     */
    String s0 = "上官海翰";
    String s1 = new String("上官海翰");
    String s2 = new String("上官海翰");
    System.out.println("s0 == s1:" + (s0 == s1)); //false:地址不一样,前者在常量池,后者在堆内存中

    s1.intern();
    s2 = s2.intern();
    System.out.println("s0 == s1:" + (s0 == s1)); //false:同上,因为s1.intern()改变的并不是s1的地址指向
    System.out.println("s0 == s1.intern():" + (s0 == s1.intern())); //true:因为s1.intern()改变的是s1.intern()整体的地址指向,指向的是常量池,这里说的就是上述的等号左边
    System.out.println("s0 == s2:" + (s0 == s2)); //true:同上,因为s2.intern()的结果赋值给s2了,所以s2的地址指向常量池,因此相等

    String s3 = new String("上官海翰");
    String s4 = s3.intern();
    System.out.println("s3 == s4:" + (s3 == s4)); //false:s3指向堆内存,s4指向常量池

    String s5 = "上官";
    String s6 = "海翰";
    String s7 = "上官海翰";
    String s8 = s5 + s6; // 在编译的时候,JVM并不知道s5+s6等于上官海翰,所以在运行的时候会创建新的上官海翰,因此地址不一样
    String s9 = "上官" + "海翰"; //在编译的时候会自动合并成上官海翰,所以调用之前"上官海翰"的地址,因此地址一样
    System.out.println("s7 == s8:" + (s7 == s8)); //false
    System.out.println("s7 == s9:" + (s7 == s9)); //true
}

代码中的注解已经很清楚了,所以基本都不会有任何疑问。

以下是我当时产生的疑问:

String s3 = new String("上官海翰");
String s4 = s3.intern();
System.out.println("s3 == s4:" + (s3 == s4)); //false

可是如果单拿出这段代码运行,按照intern()方法的解释,在常量池并没有”上官海翰”,难道JVM是在堆内存中又创建了一个对象,赋值为”上官海翰”并指向s4?
其实并不是这样的,这是JVM的一个机制,当创建一个对象并赋值时,会先去常量池查找是否有这个值,如果存在这个值,就复制一份到堆内存中,如果不存在这个值,会先在常量池创建这个值,之后复制一份到堆内存中。因此,常量池已经包含”上官海翰”了。

如果对JVM存储机制想详细了解,可以看这篇文章
https://blog.csdn.net/Marvel__Dead/article/details/69220153

3、总结

以上就是我对字符串判等的理解,如有不对之处,希望诸君不吝赐教。

猜你喜欢

转载自blog.csdn.net/zcy92949/article/details/79930223
今日推荐