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
在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 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值肯定不一致。总结一下: