java 中instanceof 和 isInstance() 和equals()和 == 四者之间的比较

 

instanceof保持了类型的概念,它指的是“你是这个类吗,或者你是这个类的派生类吗?”

isInstance()和instanceof一致。

看代码:

class Base{}
class Derived extends Base{}


public class Main {

    static void test(Object x) {
        System.out.println("Test of x class:" + x.getClass());
        System.out.println("Base.isInstance(x):" + Base.class.isInstance(x));
        System.out.println("Derived.isInstance(x):" + Derived.class.isInstance(x));
        System.out.println("x instanceof Base:" + (x instanceof Base));
        System.out.println("x instanceof Derived:" + (x instanceof Derived));
    }

    public static void main(String[] args) {
        test(new Base());
        test(new Derived());
    }
}

运算结果:

Test of x class:class Base
Base.isInstance(x):true
Derived.isInstance(x):false
x instanceof Base:true
x instanceof Derived:false
Test of x class:class Derived
Base.isInstance(x):true
Derived.isInstance(x):true
x instanceof Base:true
x instanceof Derived:true

所以,instanceof可以用来比较类型,比较该对象的类型是否为比较对象的类型或者派生类。

equals():

在java中,只有类才拥有equals,基本数据类型(int,char,double等)没有equals方法。所以比较基本类型就直接用==比较。

Object中的equals()方法:

 public boolean equals(Object obj) {
        return (this == obj);
    }

可见,默认的equals方法是直接比较两个类的地址是否相同。

我们在new一个类的时候默认是继承了Object类,我们可以重写equals()方法来定义我们自己的比较方法。

接下来我们看看String的equals()方法,

 public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String aString = (String)anObject;
            if (coder() == aString.coder()) {
                return isLatin1() ? StringLatin1.equals(value, aString.value)
                                  : StringUTF16.equals(value, aString.value);
            }
        }
        return false;
    }
@HotSpotIntrinsicCandidate
    public static boolean equals(byte[] value, byte[] other) {
        if (value.length == other.length) {
            for (int i = 0; i < value.length; i++) {
                if (value[i] != other[i]) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

 看得出是直接比较String对象中的字符,逐个比较的。

由于String比较特殊,它可以作为基本类型,也可以作为对象。

接下来我们测试一下:

public class _3 {
    public static void main(String[] args) {
        String s1 = new String("hello");
        String s2 = "hello";
        String s3 = s1;
        String s4 = "hello";
        String s5 = new String("hello");
        System.out.println(System.identityHashCode(s1));
        System.out.println(System.identityHashCode(s2));
        System.out.println(System.identityHashCode(s3));
        System.out.println(System.identityHashCode(s4));
        System.out.println(System.identityHashCode(s5));
        System.out.println("s1==s2:" + (s1 == s2));
        System.out.println("s1.equals(s2):" + s1.equals(s2));
        System.out.println("s1==s5:" + (s1 == s5));
        System.out.println("s1.equals(s5):" + s1.equals(s5));
        System.out.println("s1==s3:" + (s1 == s3));
        System.out.println("s1.equals(s3):" + s1.equals(s3));
        System.out.println("s2==s4:" + (s2 == s4));

    }
}

输出:

475266352
1355531311
475266352
1355531311
1967205423
s1==s2:false
s1.equals(s2):true
s1==s5:false
s1.equals(s5):true
s1==s3:true
s1.equals(s3):true
s2==s4:true

s1创建的时候在字符串常量池中添加了"hello",然后java中添加了对象引用地址,堆中实例化了s1对象,栈中的地址指向堆中的对象,s2的地址也是指向堆中的实例化的s2对象,所以s1和s2的地址不一致,导致了s1==s2比较的结果为false,但是s1和s2的内容都是字符串常量池中的"hello",所以equals()方法比较得出的结果是true。

s3创建的时候直接引用s1,所以s3的地址和s1的地址是一样的,指向的实例化对象也是同一个,所以== 和equals都是true。

我打印结果的时候也把内存地址打印出来了,所以能够很直接得看到s1和s3地址一致,s2地址不一致。总结一下:

equals()方法对String比较的是对象的字符串内容,==对对象比较的是他们的内存地址。

不同类对equals()方法有着不同的重写。在这里就不一一列举了。

 

hashCode()方法比较:

还是接着上面的代码,在后面添加代码:

         String s6 = new String("sss");
        System.out.println(s1.hashCode() == s5.hashCode());
        System.out.println(s1.hashCode() == s6.hashCode());
        System.out.println(s1.hashCode() == s3.hashCode());
        System.out.println(s2.hashCode() == s4.hashCode());

输出为:

true
false
true
true

s1和s5是两个不同的对象,即使他们的内容相同,但是他们的内存地址不一致,但是他们的hashCode值一样,所以hashCode值一致不代表他们是同一个对象 。s1和s6的内容不同,所以他们的hashCode值肯定也不同,因此,不同对象hashCode值肯定不一致。总结一下:

hashCode值一样,不代表为同一个对象,hashCode值不一样,肯定不为同一个对象。

 

你可能感兴趣的:(JAVA字段,java)