[Java] Various comparison operations

In the previous source code reading, I saw a familiar keyword instanceof, but I didn't realize that it was used for class comparison, including judging whether it was a subclass.

Suddenly I realized that there are actually many ways to make comparisons that I have overlooked, not just ==, !=, and equalsthese.

How to compare primitive data types


The comparison of basic data types uses ==, !=, <, >, >=, <=these basic comparison symbols, and chartypes and booleantypes are converted to types when they are compiled into bytecode files 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
}

How to compare wrapper classes for primitive data types


Each basic type has a corresponding wrapper class. For example int, the wrapper class of a type is a Integerclass, and charthe wrapper class of a type is a Characterclass.

Equals

The comparison of the wrapper class can use the equals(Object obj)method, the return value is a booleantype, trueand the sum falserepresents 相等and respectively 不相等, and the comparison is the wrapped value.

Take a Characterclass as an example:

    /**
     * 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

Wrapper classes also provide a way to compare: compareTo(包装类 another包装类)methods, which inherit from Comparable<T>interfaces.

Byteclass, Shortclass, Characterclass returns the difference between the two numbers being compared.

Take a Byteclass as an example:

    /**
     * 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;
    }

IntegerClass and Longclass return -1, 0, 1, which represent 小于, 等于, respectively 大于.

Take for Integerexample:

    /**
     * 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);
    }

FloatClasses and Doubleclasses also return -1, 0, 1. The difference between classes and Integerclasses is that the method in classes and classes needs to be discussed in two cases : the absence of parameter values ​​and the existence of parameter values . If yes , then the parameter values ​​need to be formatted as After comparing the form, the meaning of the return value is the same as that of the class.LongFloatDoubleNaN (Not a Number,非数,是计算机科学中数值数据类型的一个值,表示未定义或不可表示的值)NaNNaNIEEE 754 floating-pointInteger

Take a Doubleclass as an example:

    /**
     * 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;
    }

BooleanThe class returned is still -1, 0, 1, but it is different

  1. When equal, return 0;
  2. When not equal:
    1. The value of the caller compareTo(Boolean b)is true, return 1;
    2. The caller compareTo(Boolean b)'s value is false, return -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);
    }

How primitive data types and wrapper classes compare


Equals

equals(Object obj)The method can also pass in basic data type parameters, and when writing, you can pass in parameters of any type , but when running, you will find that Integerthe type 97and chartype are 'a'not equal, the fundamental reason is that although the method accepts any type The parameters of the parameter, but the type of the parameter will be judged in the method body , so we should pay attention to the basic data type of the parameter must correspond to the wrapper class of the calling method .

Take a Integerclass as an example:

    /**
     * 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包装类)The method can also pass in the basic data type parameter, and the wrapper class will automatically perform the 装箱operation, but it should be noted that the basic data type of the parameter must correspond to the wrapper class that calls the method .

Take a Longclass as an example:

public class BaseTest {

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

Symbol comparison

Because the wrapper class has the feature of automatic unboxing, it can fully apply the comparison rules of ==, !=, <, >, >=, <=these basic comparison symbols.

How to compare String classes


StringIf the type uses the comparison symbol directly, the value of the referenced address is compared, not the value of the content.

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

If we want to compare the value of the content , we still need to use equals(Object anObject)methods.

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

In addition, the Stringclass also provides a variety of comparison methods, which will be learned in the in-depth String class.

How to compare the types of objects


There are two ways to compare types: instanceofkeywords and getClass()methods.

Inheritance aspects areinstanceof considered when comparing types using keywords.

When the subclass object is compared with the superclass type, the result is true;

When the parent class object and the child class type are compared, the result is false;

getClass()When comparing types with methods, inheritance is not considered.

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

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325906728&siteId=291194637