下面呢我们来看一个相等还是不等,equal or
not equal。这个我们知道呢在jave语言里面呢 用一个...
两个等号来判断呢相等号,那这实际上呢 是一个复杂的问题。但是简单来说呢,这个
判断呢左右的两个数是不是相等呢,它基本类型的话
iii呢就是值相等来判断,引用类型呢判断引用是否相等。也就是说,
它是不是引用到同一个对象实体上的这个引用相等。但是呐有不少的具体情况,一定需要- 具体分析
因为不是那么简单啊,我们下面来看看呢一个基本的情况。
先看基本类型的相等,那么数字的相等呢 如果是它不同的类型呢,它转换以后进行比较,比如说整数跟实数
那它都转成实数进行比较,这个好理解。那么对浮点数
最好不要直接用这种双等号来判断,因为呢浮点数我们知道了
在计算机里面它是有误差的,很多情况下有误差的。所以呐
我们最好不用双等号,反而用判断两个数的差
的绝对值是不是很小,用来判断这两个数是不是接近,那更合理一点。甚至呢我们说
double里面的NAN就是Not An Number,不是一个数
这个很很特殊啊,就是double里面有个“不是一个数”的这个数。这两个数呢
两个"不是数"的数,它是不相等的,结果为false的这个
这是当然这种是没什么道理的,这是种规定,那具体这种规定呢那可以参见
JDK的API文档,它里面呢说得很详细。有很多细节,那以后我们
养成一个查看API文档的一个习惯。你可以比如说double你就看看它里面究竟是怎么- 介绍的。
那么布尔型呢我们要注意一下,布尔型呢是不..没法跟int相比较。因为
虽然我们说java编译器它将这个布尔型
最终是翻译成了整数类型,但是在java语言里头
我们是不能把布尔型当成整数的。下面我们看一个很特殊的一个例子,大家观察一下
int这里呢有一个Integer,那这一个呢是包装了,包装内呢
是10,整数包装成了一个对象引用
然后这两个引用,它都是包装了10,然后包装后接着 问它是不是相等的,啊它不相等。这个我们好理解它就相当于
包装到两个不同的这个对象引用上面去了,这两个引用呢当然是不等。
但是如果我们用boxing 就是装箱后拆箱机制,装箱后拆箱机制,你看装箱机制呢
这个m是10,n也是10,然后m是不是等于n。如果你上机实验一下的话
它恰恰是true的,按理说包装成两个不同的对象啦 但这里存在一个什么问题呢?这是因为这个包装啊
这个boxing啊,它把这个10包装成一个引用,这个引用它是用valueof
在java里面呢这个value函数呢它 有一个缓存,这个缓存呢就是
-128到+127,这里的这些数啊 它是进行了缓存的,这个缓存。也就是说它
认为呢这一种对象呢很经常用,那么它就把这些对象都缓存到 这里面已经生成好的这些对象,直接引用到它上面,所以这
两个相等的。但是超过-128到+127呢,这边就不等了。
因为这个对象呢是两个,这一个呢所以就是那就是相当于
直接生成了两个。所以这个在
JDK的文档里面也有,也有。这个装箱呢这个对象是否相等呢
关于我们刚才提到的是它有一个比较详细的说明,那它就说如果比如说整数 short
它是在-128到+127的话,那么这个时候呢它是有缓存的。所以这个
我们要注意。那我们在枚举对象和引用对象呢,情况如何呢?那枚举类型这种呢虽然它是c- lass
但是呢它也进行了惟一的实例化,所以呢它是 可以直接判断是否相等的,所以这个是枚举类型。
引用类型呢一般的说呢是直接看两个引用是否一样
它不是判断内容一样,所以呢我们在写的时候呢
要注意这个用euqals的方法。如果我们自己能呢用equals这个方法
那特别要注意就是我们比如说字符串相等
两个字符串相等,你要尽量用equals这个方法。那
其他的也是一样。我们如果自己要定一个类呢,你就要go read的这个equals的方法
那么java里面呢对两个对象是否能equals 是否是一样,内容是一样的这个判断呢
我们经常还要重写这个hashCode()的这个方法,overwrite的这个方法
这个方法呢实际上是把一个对象跟另一个对象直接计算出一个值,这个是一个叫hashCo-
de() 得到这个结果然后可以快速地判断这两个对象
它的相等的这个含义,所以一般时候呢这两个都是 如果要写一个,那么你要重写另一个。因为这两个呢我们在
有的时候呢用这两个要同时用到,所以你自己定义 的时候,要注意这个问题。那么对于string
这个特殊的类,这个string因为我们知道它是引用类型呢 但是它相等与不等呢,有特殊性,那个特殊性呢
我们知道在一般情况下呢,不要用这个双等号,这个我们一定要牢记于心
所以要用equals来判断内容是否相等,但是有一个特殊情形
就是字符串的常量,我们说 string literal,也就是说实实在在写出来的那个常量
那么对这个常量呢,java在编译的时候,它做了特殊处理 这个特殊处理我们成为内部化-
interned,那就是内部化,这个术语呢有点怪 我们简单的说呢,可以这么简单的理解为
如果你说两个字符串常量是一样的,这两个字符串常量是一样的话
它都把它指定到同一个字符串常量上去
我们也可以理解为引用到同一个字符串常量,所以这一个相同的字符串常量
是相等的,这里注意是常量,是字符串常量 总是相等,那变量还是要用上面这个办法
要用equals。那我们下面呢开个例子,比如说 有hello这个字符串,然后呢我们有
lo这个字符串,啊lo,它的内容是这样。注意呢这个字符串
后面这个是常量,左边呢是两个引用,引用到这个常量上面去。
那我们看“Hello”和这个hello
那我们看这个“Hello”或者这个hello是不是相等呢?它是相等的,因为
这个"Hello"它引用到这个字符串上面,那么这个字符串常量和这个字符串常量我们可- 以说它叫类补化
所谓类补化,就是同一个字符串合并到一个字符串上去了,所以它是true的
然后假设我们有另外一个类,另外一个类呢它有hello
这里面假设它也有这个字符串常量
那么这两个也是相等的。所以说,也就是说凡是相同的字符串常量它的后面呢
都指向同一个地方,所以这个引用就是相等的。那我们下面看这个例子 hello和这个Hel
lo 加这个加这两个 这两个相加呢因为它是字符串常量在编译器的时候呢
它已经把它合并成了,合并成了这个hello了,所以这两个呢又是相同的字符串,所以它- 也是true的
然后我们再看这个hello, "Hel"加上这个lo,注意这个是个变量
这个变量加这个常量,这是引用咯这个引用加这个常量之后呢,这个常量。
这个就是false,它不会把这两个呢合并成一个常量,因为这个
表达式变量,所以这个地方呢要注意。然后我们下面再看一个例子 Hello这个常量和new
String,这两个就不等咯 这是new重新创建的一个对象,它和原先那个常量呢是没关系的
所以这两个引用呢是不相等的,我们再往下看这个例子。这个hello和这个
这两个呢应该就是两个变量了,但是我们点个intern(),这个呢意思就是
求得它内部化里面的一个字符串,所以这两个呢又是相等的
所以这个也就是说,这个虽然是个变量但是我们让它去求一下
它里面内部化呢有没有跟它相等的 所以这两个呢又是相等。所以字符串常量啊,
字符串处理呢它是判断引用,这是一般情况,判断引用。但是要注意呢对常量
进行了特殊处理,有点像我们刚才那个包装,就是
对于整数的包装,有的时候呢做了一些特殊处理 这个时候我们就要特别小心。