• Java中equal和==区别及String创建过程


    Java中equal和==区别

    1.起因

    在一段Java代码中,使用了两种实现方式。

    //第一种命令行输入
    int main (String[] args) {
    	if(args[0] == "-logdb"){
    		System.out.println("args==-logdb");
    	} else {
    		System.out.println("args!=-logdb");
    	}
    }
    //第二种
    int main (String[] args) {
    	String[] args1 = {"-logdb"};
        if(args1[0] == "-logdb"){
            System.out.println("args==-logdb");
        } else {
            System.out.println("args!=-logdb");
        }
    }
    

    结果发现,第一种显示的是args!=-logdb,而第二种显示的却是args!=-logdb。


    2.原因

    • 1.首先,在Java中,和equal是不一样的。对于基本类型,如int,char之类的,比较的是他们的值。而对于复合类型(类),当使用比较的就不是他们的值,而是他们的地址,的意思可以看成是参与比较的两个对象是不是同一个对象,即是否具有相同的地址。而equal的初始行为是比较地址,但在一些类中被重写覆盖,如String类中的equal方法:

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

    我们可以很明白地看出,在开始比较地址如果相同就返回true,后续则是比较String的内容。所以,当我们需要比较两个字符串是否相同的时候,最好使用equal来进行比较。

    • 2.创建字符串对象原理

      • 在创建一个字符串对象str = X时,jvm会拿着X去字符串缓存池中找到是否有内容相同的字符串,若有,则将str与其联系起来,若没有,则在池中创建。

      • 使用new创建对象时,会在堆栈区中创建一个对象。

      • 如果直接指定,如第二个例子,则会去字符串缓存池中检查是否存在字符串,不存在则创建,不会在堆栈区创建。

      • 例子

          String str1 = "abc"; 
          System.out.println(str1 == "abc");   //true
        

        步骤:

        1. 栈中开辟一块空间存放引用str1;

        2. 字符串缓存池中开辟一块空间,存放String常量"abc";

        3. 引用str1指向池中字符串缓存池"abc";

        4. str1所指代的地址即常量"abc"所在地址,输出为true;

          String str2 = new String("abc");
          System.out.println(str2 == "abc"); //false

        步骤:

        1. 栈中开辟一块空间存放引用str2;

        2. 检查维护串池,若串池中有"abc",copy到堆中,若没有,在堆中创建,并添加到串池中

        3. 引用str2指向堆中的新建的String对象"abc";

        4. str2所指代的对象地址为堆中地址,而常量"abc"地址在池中,输出为false;

          String str3 = new String("abc");
          System.out.println(str3 == str2); //false

        步骤:

        1. 栈中开辟一块空间存放引用str3;
        2. 堆中开辟一块新空间存放另外一个(不同于str2所指)新建的String对象;
        3. 引用str3指向另外新建的那个String对象 ;
        4. str3和str2指向堆中不同的String对象,地址也不相同,输出为false;

          参考链接1
          参考链接2
    • 3.字符串缓存池
      在程序运行过程中,会创建一个字符串缓存池。下面,让我们来看一看第一个例子。

        int main (String[] args) {
        	if(args[0] == "-logdb"){
        		System.out.println("args==-logdb");
        	} else {
        		System.out.println("args!=-logdb");
        	}
        }
      

    我们可以看到,在new出一个args字符串数组的时候,在字符串缓存池中,并没有存在着"-logdb"。
    所以,这两个字符串进行比较时,比较的是他们的地址,一个位于堆中,一个位于缓存池中,地址当然是不同的,所以返回的是不等于。

    	int main (String[] args) {
    		String[] args1 = {"-logdb"};
    	    if(args1[0] == "-logdb"){
    	        System.out.println("args==-logdb");
    	    } else {
    	        System.out.println("args!=-logdb");
    	    }
    	}
    

    而在第二个例子中,我们先示例化了一个字符串数组,其中存在着"-logdb",所以,当后续比较时,程序先在String缓存池中寻找相同值的对象,即这两比较对象的地址其实是一样的,都是缓存池中的地址,所以返回等于。

  • 相关阅读:
    使用别的电脑连接另一台电脑当中的虚拟机中的kylin项目
    Windows Server2008服务器ping不通问题解决
    kylin Build过程问题排查:17 Step Name: Build Cube In-Mem
    CDH5.14.4中的Hue集成HBase
    kylin2.4.1订单案例详细构建流程
    kylin安装过程问题排查
    全程实操cdh5.14.4中集成安装kylin2.4.1与使用测试
    centos7 下gcc离线安装
    CentOS7+CDH5.14.0安装CDH错误排查:HBase服务出现 该运行状况测试不良,因为 Service Monitor 未找到活动 Master
    Analysis Services(SSAS) 性能优化
  • 原文地址:https://www.cnblogs.com/FZfangzheng/p/7860299.html
Copyright © 2020-2023  润新知