Java中equals与==区别

关系操作符 ==

首先Java中的数据类型分为

  • 基本类型
  • 引用类型

Java中equals与==区别_第1张图片

在Java中有八种基本数据类型:

  • 浮点型:float(4 byte), double(8 byte)
  • 整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)
  • 字符型: char(2 byte)
  • 布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值”true”和”false”)

对于这八种基本数据类型的变量,变量直接存储的是“值”。

所以,在八种基本类型中使用关系操作符 == 来进行比较时,比较的就是“值”本身。

除了基本类型,Java中还有引用类型 

在Java中,引用类型的变量存储的并不是“值”本身,而是与其关联的对象在内存中的地址

比如下面这行代码

String str1;

  这句话声明了一个引用类型的变量,此时它并没有和任何对象关联。 
  而通过 new 来产生一个对象,并将这个对象和str1进行绑定:

str1= new String("hello");

  那么 str1 就指向了这个对象,此时引用变量str1中存储的是它指向的对象在内存中的存储地址,并不是“值”本身,也就是说并不是直接存储的字符串”hello”。这里面的引用和 C/C++ 中的指针很类似。

小结

 因此,对于关系操作符 ==:

  • 若操作数的类型是基本数据类型,则该关系操作符判断的是左右两边操作数的是否相等
  • 若操作数的类型是引用数据类型,则该关系操作符判断的是左右两边操作数的内存地址是否相同。也就是说,若此时返回true,则该操作符作用的一定是同一个对象。

equals方法

1、来源 

  equals方法是基类Object中的实例方法,因此对所有继承于Object的类都会有该方法。 

2、equals方法的作用 

 为了更直观地理解equals方法的作用,我们先看Object类中equals方法的实现。

public boolean equals(Object obj) {
    return (this == obj);
}
通过代码可以看到,Object类里的equals方法也就是直接使用==。

 但我们都知道,下面代码输出为 true:

public class Main {
   public static void main(String[] args) {
       String str1 = new String("hello");
       String str2 = new String("hello");
       System.out.println(str1.equals(str2));
    }
}

再看一下String类的equals方法

public boolean equals(Object anObject) {
    // 先比较两个对象对否指向同一个内存地址
    // 如果相等直接返回true
    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;
            // 逐字符判断是否相等,如果有一个字符不相等,则返回false
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            // 如果所有字符都相等,则返回true
            return true;
        }
    }
    // 如果类型不相等,直接返回false
    return false;
}

可以看到String重写了equals()方法

使用equals方法,内部实现分为三个步骤:

  1. 比较引用是否相同(是否为同一对象)
  2. 判断类型是否一致
  3. 判断长度是否一致
  4. 比较内容是否一致

小结

  • String重写了equals()方法
  • 在String中使用equals()时比较的是字符串的值是否相等

------------------------------------------------------------------------------------------

String对象的创建有两种方式

方法一

对象不同,内容相同

"=="返回false,equals返回true

String s1 = new String("java");
String s2 = new String("java");
System.out.println(s1==s2);            //false
System.out.println(s1.equals(s2));    //true

同一对象

"=="和equals结果相同

String s1 = new String("java");
String s2 = s1;
System.out.println(s1==s2);            //true
System.out.println(s1.equals(s2));    //true

方法二

如果值不相同,则肯定不是相同的对象

所以在这种情况下"==" 和equals结果一样

String s1 = "java";
String s2 = "java";
System.out.println(s1==s2);            //true
System.out.println(s1.equals(s2));    //true

使用方法二创建String时,首先冲缓冲池中找有没有相同的值,如果有则直接指向它。所以这里s1==s2为true

小结

两个语句都是返回一个String对象的引用, 但JVM处理的方式不一样.

  • 方法一: JVM 马上在堆区中创建String对象, 然后将对象的引用返回.(并不会添加至 String Pool 中, 除非显示的调用 String的intern方法)
  • 方法二: JVM 首先在 String Pool 中通过String的 equals 方法查找对象池中是否有该String对象. 如果有,则直接返回而不会再重新创建; 如果没有, JVM 则在堆区中创建新的String对象, 将其引用返回, 同时将该引用添加至String Pool中.
String Pool不是在堆区,也不是在栈区,而是存在于方法区(Method Area)

你可能感兴趣的:(Java基础,源码分析)