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缓存池中寻找相同值的对象,即这两比较对象的地址其实是一样的,都是缓存池中的地址,所以返回等于。

Java中equal和==区别及String创建过程的更多相关文章

  1. Java 中>>和>>>的区别

    Java 中>>和>>>的区别 Java中的位运算符: >>表示右移,如果该数为正,则高位补0,若为负数,则高位补1: >>>表示无符号右移 ...

  2. Java中new一个对象是一个怎样的过程?JVM中发生了什么?

    Java中new一个对象的步骤: 1. 当虚拟机遇到一条new指令时候,首先去检查这个指令的参数是否能 在常量池中能否定位到一个类的符号引用 (即类的带路径全名),并且检查这个符号引用代表的类是否已被 ...

  3. 关于Java中equal函数和==的一些区别

    equal函数比较的到底是什么,很明显是比较的值,但是什么值?与==比较的堆中的内存地址不同,其比较的是对象的值,包括各个属性的值.我们在重新overriding此方法时首先要判断是否为同一对象,如果 ...

  4. 关于Java中equal 和 == 的区别

    在对Java开发还不熟练的时候,往往很多人都喜欢用==去比较两个对象是否相等,有时候就会出现很奇葩的问题. 其实这类问题并不是奇葩问题,只是我们不够细心而已,在Java中“==”比较两个变量本身的值, ...

  5. JAVA中Integer.valueOf, parsetInt() String.valueOf的区别和结果

    先来看段代码 public class IntegerDemo { public static void main(String[] args) { String num = null; System ...

  6. Java中的字符串驻留(String Interning)

    1. 首先String不属于8种基本数据类型,String是一个对象. 因为对象的默认值是null,所以String的默认值也是null:但它又是一种特殊的对象,有其它对象没有的一些特性. 2. ne ...

  7. 全面解释java中StringBuilder、StringBuffer、String类之间的关系

    StringBuilder.StringBuffer.String类之间的关系 java中String.StringBuffer.StringBuilder是编程中经常使用的字符串类,在上一篇博文中我 ...

  8. .NET和JAVA中BYTE的区别以及JAVA中“DES/CBC/PKCS5PADDING” 加密解密在.NET中的实现

    场景:java 作为客户端调用已有的一个.net写的server的webservice,输入string,返回字节数组. 问题:返回的值不是自己想要的,跟.net客户端直接调用总是有差距 分析:平台不 ...

  9. Java中的堆栈区别

    在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配 ...

随机推荐

  1. unity getcomponentsinchildren 翻船

    今天使用GetComponentsInChildren, 老司机翻船.因为一直以来我使用这个函数,下意识的从来所有的相同component都是放在子节点下,本身节点肯定不会放一个相同的componen ...

  2. AngularJS执行流程详解(转)

    一.启动阶段 大家应该都知道,当浏览器加载一个HTML页面时,它会将HMTL页面先解析成DOM树,然后逐个加载DOM树中的每一个元素节点.我们可以把AngularJS当做一个类似jQuery的js库, ...

  3. typedef和#define的简单比较

    1.通常说typedef比#define要好,尤其在有指针的情况下 typedef char* pStr1; #define pStr2 char* pStr1 s1,s2; pStr2 s3,s4; ...

  4. 10_set集合

    一.集合类型 集合是一组无序排列的可哈希的值(可哈希的值->不可变),集合成员可以做字典中的键.但集合本身是不可哈希的. 集合是无序没有索引,也没有像字典的key,所以集合不能更改元素.只能增删 ...

  5. HTML基础知识概括

    1.html的概念 HTML是用来描述网页的一种语言. HTML指的是超文本标记语言(HyperText Markup Language) HTML不是一种编程语言,而是一种标记语言(markup l ...

  6. python threading queue模块中join setDaemon及task_done的使用方法及示例

    threading:     t.setDaemon(True)  将线程设置成守护线程,主进行结束后,此线程也会被强制结束.如果线程没有设置此值,则主线程执行完毕后还会等待此线程执行.     t. ...

  7. MySQL系统临时表、用户临时表

    MySQL临时表分为系统使用的临时表和用户使用的临时表. 系统使用的临时表是指MySQL在执行某些SQL语句时需要依赖临时表来完成整个过程.系统使用的临时表的情况可以分为以下几种: *  group ...

  8. CF 375D. Tree and Queries【莫队 | dsu on tree】

    题意: 一棵树,询问一个子树内出现次数$≥k$的颜色有几种 强制在线见上一道 用莫队不知道比分块高到哪里去了,超好写不用调7倍速度!!! 可以用分块维护出现次数这个权值,实现$O(1)-O(\sqrt ...

  9. hiveql函数笔记(二)

    1.数据查询 //提高聚合的性能 SET hive.map.aggr=true; SELECT count(*),avg(salary) FROM employees; //木匾不允许在一个查询语句中 ...

  10. sql sever基本语法总结

    一.数据库导入表 1.先用sql语句创建相应的表,包括表的字段和字段类型 2.导入数据,选择相应的表名,不带'$'符号的表名 二.创建数据库 create datatable 数据库名 三.查看表里的 ...