我们在编程时总是会用到=或==,但是等于号都有什么作用呢?下面我们来看一下
(注:下文会提及一点常量池堆栈,由于本人了解还不是透彻,暂不做解释,日后会做总结,可先点击字面查看理解)

一、单等于号的作用

1.单等于号具有赋值作用

我们在定义变量时,会对变量进行赋值,例如a=3,就是把3赋值给a。
这就是在初始化对象的时候进行赋值。

2.单等于号具有引用对象作用

比如我们写了 a1=a2,表示对象a1指向的内存地址与a2相同,即a1,a2指向同一个对象,这时候a2就引用了a1的地址,起到了传地址的作用。如果改变a2,a1也会相应改变。


二、双等于号的作用

==操作对于 基本数据类型比较的是两个变量的值是否相等 ,对于 引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。

这时我们应该注意到== 具有不严谨的性质 ,即当 == 两边值类型不同的时候,要先进行类型转换,再比较,这时就可能会相等,下面我们看具体情况:

1.如果两个值类型相同,进行 === 比较。

2.如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:

  • a如果一个是null、一个是undefined,那么相等。
  • b.如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
  • c.如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
  • d.如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象。(这个目前我也不太懂)
  • e.任何其他组合,都不相等。

例如:

“1” == true
类型不等,true会先转换成数值 1,现在变成 “1” == 1,再把"1"转换成 1,比较 1 == 1, 结果为true。


三、三等于号的作用(注意===只在JavaScript中出现)

从前面我们已经知道
= 赋值运算符
== 等于
针对 == 的不严谨来说,三等于号就是用来进行严格判断的,(不做类型转换,类型不同的一定不等) 无论js还是java中都是如此
例:

var a = 3; 
    var b = "3";
    
    a == b 返回 true 
    a === b 返回 false

因为a,b的类型不一样
===用来进行严格的比较判断

下面我们具体看看===的规则用来判断两个值是否相等:
1、如果类型不同,则不相等;
2、如果两个都是数值,并且是同一个值,那么相等; (有一个例外,如果其中至少一个是NaN,那么不相等) (判断一个值是否是NaN,只能用isNaN()来判断) ;
3、如果两个都是字符串,每个位置的字符都一样,那么相等;否则不相等;
4、如果两个值都是true,或者都是false,那么相等;
5、如果两个值都引用同一个对象或函数,那么相等;否则不相等;
6、如果两个值都是null,或者都是undefined,那么相等。


四、双等于号和equls的区别

1.==和equals的区别

  • 前面我们知道==可以用来比较基本类型和引用类型,判断内容和内存地址
  • equals用来判断两个对象内容是否相等

注:我们可以从equals源码发现

Compares this string to the specified {@code StringBuffer}.  The result
     * is {@code true} if and only if this {@code String} represents the same
     * sequence of characters as the specified {@code StringBuffer}. This method
     * synchronizes on the {@code StringBuffer}.

即:equals只能针对string类型比较,比较的两者不是String类型,一定会返回false

2.在String之间的判断

String str1 = "hello";//存在于常量池中,堆栈
		String str4 = "hello";
		String str2 = new String("hello");//存放在堆中
		String str3 = new String("hello");
		String str5 = str2;
		
		System.out.println(str1.equals(str2));//true
		System.out.println(str3.equals(str2));//true
		System.out.println(str1==str2);//false
		System.out.println(str3==str2);//false
		System.out.println(str1==str4);//true
		System.out.println(str5==str2);//true

字符串缓冲池是程序在运行的时候创建的一个字符串缓冲池。
当使用 String str4 = “hello”; 这样的表达是创建字符串的时候,
程序首先会在这个String缓冲池中寻找相同值的对象,
因为在String str1 = “hello”;中,str1先被放到了池中,所以在str4被创建的时候,程序找到了具有相同值的 str1,并将str4指向s1所引用的对象"hello"

3.Java面试宝典中是这样解释的

==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用 ==操作符。

如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj 是一个内存,new Object()是另一个内存,此时,变量obj 所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。

equals 方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:

String a=new String("foo");
    String b=new String("foo");

两条new 语句创建了两个对象,然后用a,b 这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a 和b 中存储的数值是不相同的,所以,表达式a==b 将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。

在实际开发中, 我们经常要比较传递进行来的字符串内容是否等, 例如, String input= …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的。应该牢记,字符串的比较基本上都是使用equals 方法。

如果一个类没有自己定义equals 方法,那么它将继承Object 类的equals 方法,Object 类的equals方法的实现代码如下:

boolean equals(Object o){
    return this == o;
}

这说明,如果一个类没有自己定义equals 方法,它默认的equals 方法(从Object 类继承的)就是使用 == 操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals 和使用 ==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals 方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。

总结下来,对于等号又有了新的认识!真好