回顾equals() 方法 与 “==” 的区别

要想了解==和equals 的区别 ,首先要了解“值”在jvm中的存储结构。java

值类型是存储在内存中的堆栈(之后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其自己则存储在堆中eclipse

    ==操做比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。jvm

   注意 此处的equals为重写Object以后的方法工具

    equals操做表示的两个变量是不是对同一个对象的引用,即堆中的内容是否相同。测试

    ==比较的是2个对象的地址,而equals比较的是2个对象的内容。this

    显然,当equals为true时,==不必定为true;spa

 

1. 基本数据类型

java的基本数据类型,也称为原始的数据类型。它们分别是: 
byte, short, char, int, long, float, double, boolean . 
基本数据类型进行 “==” 比较时,比较的是 它们的值 是否相同。 
例如:code

int a = 10;
int b = 10
System.out.println(" (a == b) = " + (a == b));

输出的结果为真。 
另外须要注意的是,对于基本类型而言,它们没有 equals() 方法,你们别上当啊对象

2. 复合数据类型(类)

1) 当 两个对象使用 “==” 进行比较时,比较的是它们在 内存中存放的地址。 也就是说,除非是 同一个new() 出来的两个对象(内存地址相同), 不然比较的结果都是false。具体测试代码以下:继承

public class Main {
    public static void main(String args[]) {
        Worker worker1 = new Worker();
        //worker2 是 worker1 的引用,同指向一个内存空间。
        Worker worker2 = worker1;
        System.out.println("(worker1 == worker2) : " + (worker1 == worker2));

        System.out.println("-------------------------");

        Worker worker3 = new Worker();
        //worker3 与 worker4 都是调用new 产生的对象,不指向同一个内存空间。
        Worker worker4 = new Worker();
        System.out.println("(worker3 == worker4) : " + (worker3 == worker4));
    }
}

class Worker {

    private String name;
    private double salary;

    public Worker() {
        this.name = "echo";
        this.salary = 0.0;
    }
    public Worker(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
}

输出的结果:
(worker1 == worker2) : true
-------------------------
(worker3 == worker4) : false

2) 你们都知道java的全部类 都是从 java.lang.Object 这个类继承下来,而Object 类中本来就有一个 equals() 方法。首先,咱们来看看源代码中 Object 类的equals() 方法。具体代码以下:

public boolean equals(Object obj) {
    return (this == obj);
}

能够发现,默认状况下,当咱们调用equals() 方法时,也仍然是比较两个对象 是否指向同一块内存空间。 咱们 稍微 修改 上面的代码,进行测试。具体代码以下:

public class Main1 {
    public static void main(String args[]) {
        Worker worker1 = new Worker();
        //worker2 是 worker1的引用,同指向一个内存空间。
        Worker worker2 = worker1;
        System.out.println("worker1.equals(worker2) : " + worker1.equals(worker2));

        System.out.println("-------------------------");

        Worker worker3 = new Worker();
        //worker3 与 worker4 都是调用new 产生的对象,不指向同一个内存空间。
        Worker worker4 = new Worker();
        System.out.println("worker3.equals(worker4) : " + worker3.equals(worker4));
    }
}

class Worker {
    private String name;
    private double salary;

    public Worker() {
        this.name = "echo";
        this.salary = 0.0;
    }
    public Worker(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
}

运行结果以下:
worker1.equals(worker2) : true
-------------------------
worker3.equals(worker4) : false
  • 家必定有疑问了,不是都说,equals() 方法比较的是 两个对象的内容嘛? 没错,默认的约定是这样的。对于咱们本身写的类,若是想要达到这个效果,那么就要重写 equals()方法了。具体代码以下: 
    (能够直接使用 eclipse的工具,选择本身想要进行比较的变量,自动生成 equals()方法)。

 

3. 怪异的String

上文说了,String类重写了 equals() 方法,当调用equals()方法比较两个String对象时,比较的是其内容,那 怪异二字 从何而来呢? 且看下面代码:

public class Main2 {
    public static void main(String args[]) {
        String s1 = "hello world";
        String s2 = "hello world";

        System.out.println("s1.equals(s2) : " + s1.equals(s2));
        System.out.println("(s1 == s2) : " + (s1 == s2));

    }
}

运行结果以下:
s1.equals(s2) : true
(s1 == s2) : true
输出结果说明,s1 与 s2 同指向一个 String对象。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

先不着急,咱们再修改一下上面代码:

public class Main3 {
    public static void main(String args[]) {

        String s1 = "hello world";
        String s2 = new String("hello world");

        System.out.println("s1.equals(s2) : " + s1.equals(s2));
        System.out.println("(s1 == s2) : " + (s1 == s2));

    }
}

运行结果:
s1.equals(s2) : true
(s1 == s2) : false
输出结果说明,s1 与 s2 不属于同一个String对象。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

为何出现上面这个怪异的问题? 
原来,程序在运行的时候会建立一个字符串缓冲池。 
当使用 String s2 = “hello world” , 
这样的表达是建立字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在第一个程序中,s1先被放到了池中,因此在s2被建立的时候,程序找到了具备相同值的 s1,将s2引用 s1所引用的 对象 “hello world”。 
第二段程序中,使用了 new 操做符,它明白的告诉程序:”我要一个新的!不要旧的!”因而一个新的”hello world” Sting对象被建立在内存中。它们的值相同,可是内存地址不一样,一个在池中游泳,另外一个在岸边休息。

事情还没完,在看看下面这个例子。

public class Main4 {
    public static void main(String[] args) {
        String s1 = "hello world";
        String s2 = new String("hello world");

        s2 = s2.intern();

        System.out.println("s1.equals(s2) : " + s1.equals(s2));
        System.out.println("(s1 == s2) : " + (s1 == s2));
    }
}

运行结果以下:
s1.equals(s2) : true
(s1 == s2) : true
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

怎么会这样??? 
原来,java.lang.String的intern()方法 ,例如 “abc”.intern()方法的返回值仍是字符串”abc”,表面上看起来好像这个方法没什么用处。但实际上,它作了个小动做:检查字符串池里是否存在”abc”这么一个字符串,若是存在,就返回池里的字符串;若是不存在,该方法会 把”abc”添加到字符串池中,而后再返回它的引用。

相关文章
相关标签/搜索