在JAVA世界中,所有的对象都有一个共同的基类Object,这个基类提供了一系列的方法包括equals();当然这个方法需要子类去重写。在实际编写代码时,就得注意如果是判断两个对象是否相等不能使用==,只能使用equals()。前者判断的是两者的引用是否指向同一个对象而不是判定两个对象是否相等。但是我发现在项目中,有的同学判断两个枚举对象是否相等的时候使用的==,当然这实际也没错:
public class Main { static enum ETest { HP, CURRENT_HP; } public static void main(String[] args) { ETest x = ETest.CURRENT_HP; if (x == ETest.CURRENT_HP) System.out.println("equals"); if (x.equals(ETest.CURRENT_HP)) System.out.println("equals"); } }都会输出"equals",因为枚举的对象是唯一的,直接使用==是不会出错,实际上Enum类的equals()方法比较的就是枚举对象的引用:
/** * Returns true if the specified object is equal to this * enum constant. * * @param other the object to be compared for equality with this object. * @return true if the specified object is equal to this * enum constant. */ public final boolean equals(Object other) { return this==other; }
但是,我们在编写的代码的时候必须要遵守规范,避免潜在的bug。对所有的对象进行判等必须使用equals()方法。
而对于值的判等,我们需要区分准确的值和不准确的值。目前java提供的基本值类型中float、double是不准确的,其他都是准确的。这和值类型在内存中的存储方式有关,为什么浮点数(float、double)就不是准确的呢,google之。因为这个特性,在项目中遇到了一个BUG:测试同学反应玩家的某个操作时而能进行时而不能进行(不能进行的几率比较小,但是确实是存在的)。然后就对相关的代码进行排查,然后发现了问题所在——有个操作的条件判断会比较两个float值是否相等,如果相等就允许玩家做某个操作,否则不允许。代码类似这样写的:
public static void test(float x) { if (x == 1F) { // ... } else { // ... } }这里存在一个BUG(当然本身使用浮点数是否相等做开关是设计的不合理)——浮点数本身不是准确的,所以比较两个浮点数是否相等不能想int类型那样直接使用==,而因该比较两个浮点数之间的差值,如果小于我们设定的一个极小值epsilon,则我们认为这两个浮点数就相等,否则不等。也就是说应该这样比较浮点数的大小:
public static void test(float x) { final float EPSILON = 0.00001F; if (x - 1F > -EPSILON && x - 1F < EPSILON) { // ... } else { // ... } }