• String类的一些细节


    先看一段代码:

        public static void main(String[] args) {
            String a = "a"+"b"+1;
            String b ="ab1";
            System.out.println(a == b);
        }

    输出的结果是true.

    1.==和equals的区别

    (1).基本数据类型,也称原始数据类型。byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。
    (2).复合数据类型(对象类型),当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。 JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地 址,但在一些类库当中这个方法被覆盖掉了,如String,Integer,Date在这些类当中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
     对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号(==)进行比较的,所以比较后的结果跟双等号(==)的结果相同。

    2.编译时优化

    当编译器在编译代码String a="a"+"b"+1;时,会将其编译为:String a="ab1";这是为了提升整体工作效率JVM进行的优化。类似的优化还有很多,例如当程序中出现int i=3*4+120时,会在编译时就变成了i=132。
    但需要注意的是,JVM只优化可以优化的部分,即在编译阶段就可以确定值的,如果字符串中出现了变量,那么JVM是不会做这样的编译时优化的。例如:

    String a="a";

    final String c="a";

    String b=a+"b";

    String c=c+"b";

    String e=getA()+"b";

    String d="ab";

    String f = new String(b);

    其中b和e在编译时不会被优化,而c会被优化,因为c是final变量,可认为是常量。所以b==d,e==d为false,c==d为true.

    3.常量池

    程序在运行的时候会创建一个常量池,它保证同一个值的字符串全局唯一。当使用 String b = "ab1", 这样的表达是创建字符串的时候,程序首先会在这个常良池中寻找相同值的对象,在程序中,a引用的对象先被放到了池中,所以在b被创建的时候,将使b也指向这个对象。所以a==b为true.
    String 类有个intern方法,当调用它时,JVM会在常良池中通过equals方法查找是否存在等值的String,如果存在,则直接返回常量池中这个String对象的地址;如果不存在,则会在常良池中创建等值的字符串,然后再返回这个新创建空间的地址。因此,只要是同样的字符串,当调用intern方法时,都会得到常良池中对应String对象的地址。所以上面虽然b==d为false,但是b.intern()==d为true.

    4.String类的equals方法实现。

    前面说过, 对于复合数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,但String,Integer,Date在这些类当中equals有其自身的实现,因此不再是比较类在堆内存中的存放地址了。下面是String类的equals方法实现:

    public boolean equals(Object anObject)
    {

          //1、如果是同一个对象,直接返回true
            if (this == anObject)
            {
                return true;
            }
            //2、如果传递进来的参数类型不是String,直接返回false
            if (anObject instanceof String)
            {
                String anotherString = (String)anObject;
                int n = count;//字符串长度
                if (n == anotherString.count) //3、如果长度不相等,直接返回false
                {
                    char v1[] = value;//取每一个位置的字符
                    char v2[] = anotherString.value;
                    int i = offset;
                    int j = anotherString.offset;
                    while (n-- != 0) //4、循环对比两个字符串的char数组,逐个比较字符是否一致,若存在不一致的情况,直接返回false
                    {
                        if (v1[i++] != v2[j++])
                            return false;
                    }
                    return true;//5、循环结束都没有找到不匹配的,说明两个字符串相等,返回true.
                }
            }
            return false;
    }

    在上例中,f==d为false,因为内存地址不一样,但是f.equals(d)为true.

  • 相关阅读:
    数据机构与算法学习(四)- 链表
    DFS深度优先
    LeetCode.98验证二叉树
    输入一个有符号整数,输出该整数的反转值。
    如何交换两个对象
    泛型简介,泛型类及使用
    一个普通的逻辑问题
    for循环
    第一次比赛唯一ACCEPT的题目笑哭
    输入100以内具有10个以上因子的整数 并输出它的因子
  • 原文地址:https://www.cnblogs.com/muyuhu/p/4789603.html
Copyright © 2020-2023  润新知