【Java】各种各样的比较操作

在之前的源码阅读中,看到了一个挺眼熟的关键词instanceof,却一下子没反应过来是用来做类比较的,包括判断是不是子类。

突然意识到其实有很多做比较的方式都被我所忽略了,绝不仅仅只有==!=equals这些。

基本数据类型的比较方式


基本数据类型的比较使用==!=<>>=<=这些基本的比较符号,char类型、boolean类型在被编译成字节码文件的时候被转换为int类型。

public class Test {

    public static void main(String[] args) {

        int a = 50;

        char b = 'a';

        boolean c = true;

        boolean d = false;
    }
}
D:\>javap -c Test.class
Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: bipush        50
       2: istore_1
       3: bipush        97
       5: istore_2
       6: iconst_1
       7: istore_3
       8: iconst_0
       9: istore        4
      11: return
}

基本数据类型的包装类的比较方式


每一种基本类型都有与之对应的包装类,例如int类型的包装类是Integer类、char类型的包装类是Character类。

Equals

包装类的比较可以使用equals(Object obj)方法,返回值为一个boolean类型,truefalse分别代表相等不相等,比较的是包装的值。

Character类为例:

    /**
     * Compares this object against the specified object.
     * The result is {@code true} if and only if the argument is not
     * {@code null} and is a {@code Character} object that
     * represents the same {@code char} value as this object.
     *
     * @param   obj   the object to compare with.
     * @return  {@code true} if the objects are the same;
     *          {@code false} otherwise.
     */
    public boolean equals(Object obj) {
        if (obj instanceof Character) {
            return value == ((Character)obj).charValue();
        }
        return false;
    }

CompareTo

包装类还提供了一种比较方式:compareTo(包装类 another包装类)方法,该方法继承于Comparable<T>接口。

Byte类、Short类、Character类返回的是做比较的两个数的差值。

Byte类为例:

    /**
     * Compares two {@code Byte} objects numerically.
     *
     * @param   anotherByte   the {@code Byte} to be compared.
     * @return  the value {@code 0} if this {@code Byte} is
     *          equal to the argument {@code Byte}; a value less than
     *          {@code 0} if this {@code Byte} is numerically less
     *          than the argument {@code Byte}; and a value greater than
     *           {@code 0} if this {@code Byte} is numerically
     *           greater than the argument {@code Byte} (signed
     *           comparison).
     * @since   1.2
     */
    public int compareTo(Byte anotherByte) {
        return compare(this.value, anotherByte.value);
    }

    /**
     * Compares two {@code byte} values numerically.
     * The value returned is identical to what would be returned by:
     * <pre>
     *    Byte.valueOf(x).compareTo(Byte.valueOf(y))
     * </pre>
     *
     * @param  x the first {@code byte} to compare
     * @param  y the second {@code byte} to compare
     * @return the value {@code 0} if {@code x == y};
     *         a value less than {@code 0} if {@code x < y}; and
     *         a value greater than {@code 0} if {@code x > y}
     * @since 1.7
     */
    public static int compare(byte x, byte y) {
        return x - y;
    }

Integer类、Long类返回的是-101,分别代表小于等于大于

Integer为例:

    /**
     * Compares two {@code Integer} objects numerically.
     *
     * @param   anotherInteger   the {@code Integer} to be compared.
     * @return  the value {@code 0} if this {@code Integer} is
     *          equal to the argument {@code Integer}; a value less than
     *          {@code 0} if this {@code Integer} is numerically less
     *          than the argument {@code Integer}; and a value greater
     *          than {@code 0} if this {@code Integer} is numerically
     *           greater than the argument {@code Integer} (signed
     *           comparison).
     * @since   1.2
     */
    public int compareTo(Integer anotherInteger) {
        return compare(this.value, anotherInteger.value);
    }

    /**
     * Compares two {@code int} values numerically.
     * The value returned is identical to what would be returned by:
     * <pre>
     *    Integer.valueOf(x).compareTo(Integer.valueOf(y))
     * </pre>
     *
     * @param  x the first {@code int} to compare
     * @param  y the second {@code int} to compare
     * @return the value {@code 0} if {@code x == y};
     *         a value less than {@code 0} if {@code x < y}; and
     *         a value greater than {@code 0} if {@code x > y}
     * @since 1.7
     */
    public static int compare(int x, int y) {
        return (x < y) ? -1 : ((x == y) ? 0 : 1);
    }

Float类、Double类返回的也是-101,与Integer类和Long类所不同的是,Float类和Double类中该方法需要分参数值不存在NaN (Not a Number,非数,是计算机科学中数值数据类型的一个值,表示未定义或不可表示的值)和参数值存在NaN两种情况讨论,如果为NaN,那么需要将参数值格式化为IEEE 754 floating-point形式后再做比较,返回值的含义和Integer类相同。

Double类为例:

    /**
     * Compares two {@code Double} objects numerically.  There
     * are two ways in which comparisons performed by this method
     * differ from those performed by the Java language numerical
     * comparison operators ({@code <, <=, ==, >=, >})
     * when applied to primitive {@code double} values:
     * <ul><li>
     *          {@code Double.NaN} is considered by this method
     *          to be equal to itself and greater than all other
     *          {@code double} values (including
     *          {@code Double.POSITIVE_INFINITY}).
     * <li>
     *          {@code 0.0d} is considered by this method to be greater
     *          than {@code -0.0d}.
     * </ul>
     * This ensures that the <i>natural ordering</i> of
     * {@code Double} objects imposed by this method is <i>consistent
     * with equals</i>.
     *
     * @param   anotherDouble   the {@code Double} to be compared.
     * @return  the value {@code 0} if {@code anotherDouble} is
     *          numerically equal to this {@code Double}; a value
     *          less than {@code 0} if this {@code Double}
     *          is numerically less than {@code anotherDouble};
     *          and a value greater than {@code 0} if this
     *          {@code Double} is numerically greater than
     *          {@code anotherDouble}.
     *
     * @since   1.2
     */
    public int compareTo(Double anotherDouble) {
        return Double.compare(value, anotherDouble.value);
    }

    /**
     * Compares the two specified {@code double} values. The sign
     * of the integer value returned is the same as that of the
     * integer that would be returned by the call:
     * <pre>
     *    new Double(d1).compareTo(new Double(d2))
     * </pre>
     *
     * @param   d1        the first {@code double} to compare
     * @param   d2        the second {@code double} to compare
     * @return  the value {@code 0} if {@code d1} is
     *          numerically equal to {@code d2}; a value less than
     *          {@code 0} if {@code d1} is numerically less than
     *          {@code d2}; and a value greater than {@code 0}
     *          if {@code d1} is numerically greater than
     *          {@code d2}.
     * @since 1.4
     */
    public static int compare(double d1, double d2) {
        if (d1 < d2)
            return -1;           // Neither val is NaN, thisVal is smaller
        if (d1 > d2)
            return 1;            // Neither val is NaN, thisVal is larger

        // Cannot use doubleToRawLongBits because of possibility of NaNs.
        long thisBits    = Double.doubleToLongBits(d1);
        long anotherBits = Double.doubleToLongBits(d2);

        return (thisBits == anotherBits ?  0 : // Values are equal
                (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
                 1));                          // (0.0, -0.0) or (NaN, !NaN)
    }

    /**
     * Returns a representation of the specified floating-point value
     * according to the IEEE 754 floating-point "double
     * format" bit layout.
     *
     * <p>Bit 63 (the bit that is selected by the mask
     * {@code 0x8000000000000000L}) represents the sign of the
     * floating-point number. Bits
     * 62-52 (the bits that are selected by the mask
     * {@code 0x7ff0000000000000L}) represent the exponent. Bits 51-0
     * (the bits that are selected by the mask
     * {@code 0x000fffffffffffffL}) represent the significand
     * (sometimes called the mantissa) of the floating-point number.
     *
     * <p>If the argument is positive infinity, the result is
     * {@code 0x7ff0000000000000L}.
     *
     * <p>If the argument is negative infinity, the result is
     * {@code 0xfff0000000000000L}.
     *
     * <p>If the argument is NaN, the result is
     * {@code 0x7ff8000000000000L}.
     *
     * <p>In all cases, the result is a {@code long} integer that, when
     * given to the {@link #longBitsToDouble(long)} method, will produce a
     * floating-point value the same as the argument to
     * {@code doubleToLongBits} (except all NaN values are
     * collapsed to a single "canonical" NaN value).
     *
     * @param   value   a {@code double} precision floating-point number.
     * @return the bits that represent the floating-point number.
     */
    public static long doubleToLongBits(double value) {
        long result = doubleToRawLongBits(value);
        // Check for NaN based on values of bit fields, maximum
        // exponent and nonzero significand.
        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
              DoubleConsts.EXP_BIT_MASK) &&
             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
            result = 0x7ff8000000000000L;
        return result;
    }

Boolean类返回的依然是-101,但是又有所不同

  1. 当相等时,返回0
  2. 当不相等时:
    1. 调用compareTo(Boolean b) 者的值为true,返回1
    2. 调用compareTo(Boolean b) 者的值为false,返回-1
/**
     * Compares this {@code Boolean} instance with another.
     *
     * @param   b the {@code Boolean} instance to be compared
     * @return  zero if this object represents the same boolean value as the
     *          argument; a positive value if this object represents true
     *          and the argument represents false; and a negative value if
     *          this object represents false and the argument represents true
     * @throws  NullPointerException if the argument is {@code null}
     * @see     Comparable
     * @since  1.5
     */
    public int compareTo(Boolean b) {
        return compare(this.value, b.value);
    }

    /**
     * Compares two {@code boolean} values.
     * The value returned is identical to what would be returned by:
     * <pre>
     *    Boolean.valueOf(x).compareTo(Boolean.valueOf(y))
     * </pre>
     *
     * @param  x the first {@code boolean} to compare
     * @param  y the second {@code boolean} to compare
     * @return the value {@code 0} if {@code x == y};
     *         a value less than {@code 0} if {@code !x && y}; and
     *         a value greater than {@code 0} if {@code x && !y}
     * @since 1.7
     */
    public static int compare(boolean x, boolean y) {
        return (x == y) ? 0 : (x ? 1 : -1);
    }

基本数据类型和包装类的比较方式


Equals

equals(Object obj)方法也可以传入基本数据类型参数,而且在书写的时候,可以传入任意类型的参数,但是在运行的时候却会发现例如Integer类型的97char类型的'a'并不相等,根本原因就是虽然方法接受任意类型的参数,但是在方法体内会对参数的类型进行判断,所以我们应该自己注意参数的基本数据类型必须和调用方法的包装类是对应关系

Integer类为例:

    /**
     * Compares this object to the specified object.  The result is
     * {@code true} if and only if the argument is not
     * {@code null} and is an {@code Integer} object that
     * contains the same {@code int} value as this object.
     *
     * @param   obj   the object to compare with.
     * @return  {@code true} if the objects are the same;
     *          {@code false} otherwise.
     */
    public boolean equals(Object obj) {
        if (obj instanceof Integer) {
            return value == ((Integer)obj).intValue();
        }
        return false;
    }

CompareTo

compareTo(包装类 another包装类)方法同样也可以传入基本数据类型参数,包装类会自动执行装箱操作,但是需要注意的是,参数的基本数据类型必须和调用方法的包装类是对应关系

Long类为例:

public class BaseTest {

    public static void main(String argc[]) {
        Long chara = new Long(5L);
        System.out.println(chara.compareTo(10L));
    }
}

符号比较

因为包装类有自动拆箱的特性,因此可以完全适用==!=<>>=<=这些基本的比较符号的比较规则。

String类的比较方式


String类型如果直接使用比较符号,比较的是引用的地址的值,而不是内容的值。

public class Test {

    public static void main(String[] args) {

        String a = "abcd";
        String b = "abcd";
        String c = new String("abcd");
        System.out.println(a == b);
        System.out.println(a == c);
    }
}
true
false

如果要比较内容的值,我们依然需要使用equals(Object anObject)方法。

public class Test {

    public static void main(String[] args) {

        String a = "abcd";
        String b = "abcd";
        String c = new String("abcd");
        System.out.println(a.equals(b));
        System.out.println(a.equals(c));
    }
}
true
true

除此之外,String类还提供了很多种比较方式,将会在深入String类中学习。

对象的类型比较方式


类型的比较方式有instanceof关键字和getClass()方法这两种。

instanceof关键字对类型进行比较的时候,考虑继承方面的关系。

子类对象和父类类型做类型比较时,结果是true;

而父类对象和子类类型做类型比较时,结果则是false;

getClass()方法对类型进行比较的时候,不会考虑继承方面的关系。

public class Parent {

}
public class Children extends Parent {

}
public class Test {

    private static void print(Object parent, Object children) {
        System.out.println("parent instanceof Parent: " + (parent instanceof Parent));
        System.out.println("parent instanceof Children: " + (parent instanceof Children));
        System.out.println("children instanceof Parent: " + (children instanceof Parent));
        System.out.println("children instanceof Children: " + (children instanceof Children));  
        System.out.println("-----------------------------------");
        System.out.println("parent getClass Parent: " + (parent.getClass() == Parent.class));
        System.out.println("parent getClass Children: " + (parent.getClass() == Children.class));
        System.out.println("children getClass Parent: " + (children.getClass() == Parent.class));
        System.out.println("children getClass Children: " + (children.getClass() == Children.class));
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Children children = new Children(); 
        Test.print(parent, children);
    }
}
parent instanceof Parent: true
parent instanceof Children: false
children instanceof Parent: true
children instanceof Children: true
-----------------------------------
parent getClass Parent: true
parent getClass Children: false
children getClass Parent: false
children getClass Children: true

猜你喜欢

转载自blog.csdn.net/ving_suixin/article/details/80043999