目录
>基础
>基本数据类型
>引用数据类型
>Java内存
>区别==和equals()
>==
>equals()
>总结
>基础
要想区分这两者,我们得先明白什么是基本数据类型和引用数据类型,以及Jav的内存构成
>基本数据类型
这八种数据变量中直接存储值。
>引用数据类型
引用数据类型非常多,大致包括:
类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型
例如,String类型就是引用类型。
简单来说,所有的非基本数据类型都是引用数据类型。
>Java内存
Java内存模型中存在这两种内存区域:一种是栈内存,一种是堆内存。 (注:程序计数器,运行时数据区,永久代,直接内存这里不讨论,因为java对象保存在栈内存(基本数据类型)和堆内存(引用数据类型和包装类)中
在函数中定义的一些基本类型的变量和对象的引用变量(变量名)都在函数的栈内存中分配。
当一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。
栈只是存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)
堆内存用来存放由new创建的对象(包括由基本类型包装起来的类:Integer、String、Double,实际上每个基本类型都有他的包装类)和数组。
>区别==和equals()
==比较的是两个对象的地址,而equals比较的是两个对象的内容。
举个通俗的例子来说,
==是判断两个人是不是住在同一个地址
而equals是判断同一个地址里住的人是不是同一个
>==
1)对于基本数据类型的变量, ==是直接对其值进行比较
2)对于引用数据类型的变量,则是对其内存地址的比较
下面来看一个有趣的例子:
public class deng {
public static void main(String[] args) {
Integer a =100;
Integer b =100;
Integer c =1000;
Integer d =1000;
System.out.println(a==b); //true
System.out.println(c==d); //false
}
}
这是因为Integer对象除了可以通过new来创建,也可以直接将int值赋给Integer变量,系统会自动将这个int值封装成一个Integer对象。
如:Integer a = 100;实际上的操作是:Integer a = Integer.valueof(100);
high的值为127,low的值为-128,当进行这个方法时如果值在-128-127之间,返回的值也就是地址是相同的.
这里有一个需要注意的地方:在上面Integer的valueof()方法里面,当int值范围在-128—127之间时,会通过一个IntegerCache缓存来创建Integer对象;当int值不在该范围时,直接调用new Integer()来创建对象。因此会产生以下情况:
(1)Integer a = 100;Integer b = 100;a == b为True。
因为这两个Integer变量引用的是缓存中的同一个Integer对象。
(2)Integer c = 1000; Integer d = 1000;c == d为False。
这似乎因为这两个Integer变量引用的是通过new创建的两个不同对象。
>equals()
1)基本类型不是对象,所以没有equals方法。
2)对于引用数据类型的变量,则是对其内容的比较
我们知道任何类都继承Object类,这里我们先看下object类里的equals方法:
我们可以从这段源码看出,在没有重写equals方法之前,equals方法里是直接调用==,因此实质上与==没有差别。但是要注意:equals方法不能作用于基本数据类型的变量,这是因为基本数据类型非对象的缘故,没有方法。
然而,在一些类库当中这个方法被重写了,比如String 、Date、ArrayList等类,这样就不在是去比较在堆内存中的存放地址了。这里我们可以看下String类里equals方法的重写:
从上面可以看出,先用==判断对象的地址是否相等,相等则返回true。
如果前面的判断不成立,接着判断括号内的对象上是否是String类型,接着判断两个字符串对象的的长度是否相等,最后判断内容是否相等,如果相等则返回true。
再来一道例题测试一下吧~
public class deng {
public static void main(String[] args) {
String s1,s2;
s1 = new String("嗯");
s2 = new String("嗯");
System.out.println(s1.equals(s2)); //true
System.out.println(s1==s2); //false
String s3,s4;
s3 = "嗯";
s4 = new String("嗯");
System.out.println(s3.equals(s4)); //true
System.out.println(s3==s4); //false
String s5,s6;
s5 = "嗯";
s6 = "嗯";
System.out.println(s5.equals(s6)); //true
System.out.println(s5==s6); //true
}
}
>总结
1)对于==,一般比较的是值是否相等
如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2)对于equals方法,一般为比较内容是否相同
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的地址/内容。
3)若 == 为true,则equals必为true
若equals为false,则 == 必为 false
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)