# d5 M0 S( i5 F# [- yThe instanceof operator compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.[3]5 A( B& S: H; i9 x% B
简单来说,instanceof 是用来将对象与类型进行比较,我们可以通过它确定这个对象是否是一个类,一个子类或者一个接口实现类的实例。 $ k: m/ ?# {" X2 W- }7 |5 |- k8 M9 Z+ ^2 j! ~' P1 U( x
public class InstanceofTest {% _& l5 j0 e1 ~& N! R, a& c
public static void main(String[] args) {8 l# w+ W# `! f, M
Father father = new Father(); ( Q1 F- A) t, H) d7 P5 c System.out.println(father instanceof Father); // true / m. I! k' b" n; R* Z System.out.println(father instanceof Son); // false 7 Y$ M' S: q+ T& l: C System.out.println(father instanceof MyInterface); // false 0 a) [, R A3 |; F7 K3 R System.out.println("------------------------"); , d; H1 e0 L5 o / T+ v3 R5 Y: v5 s) e Son son = new Son(); " a/ _+ P8 ^6 @2 s System.out.println(son instanceof Father); // true . J1 o' j9 k- }4 H0 q5 f System.out.println(son instanceof Son); // true T1 t( D0 O; m9 M& K System.out.println(son instanceof MyInterface); // true' ^( J/ Q3 @- A5 G5 b/ K' Y
System.out.println("------------------------");2 ]: x( [0 X$ A" w- w
3 o: g* V; O7 ~2 [3 r5 k Father father2 = new Son();3 D& F# F; I& B
System.out.println(father2 instanceof Father); // true% ?8 V1 [: i* z" v* z0 ]
System.out.println(father2 instanceof Son); // true 7 w( [" y4 i& Y+ O/ B) d System.out.println(father2 instanceof MyInterface); // true1 c! e; m7 _9 p& ]/ J+ n; i! P
System.out.println("------------------------");6 t: I( V2 s ~ E, I2 O
}/ ? s& ^8 C7 ?1 y4 |
} * I( l# v6 n/ T4 t1 lclass Father {9 l) a3 ]) v* n" E* K
6 g' J) e" j7 n( a5 h
} # I3 E' v E1 m3 x) o- a0 p( k $ k* T9 X4 d+ p% M6 i2 ]% F8 Dclass Son extends Father implements MyInterface{ e, x& X' l) _+ o6 Z5 T 3 _4 a& M1 S9 a, z& B5 S( X' n; c} " }+ i; w0 t/ o$ W 0 b1 |& ?. {3 p2 V; y" i7 Finterface MyInterface { ' H5 W; n! ^4 a : L" w$ n& ]8 @5 S}- m2 o8 f7 [/ _- ^- G! t# h
1* Q/ a4 ^5 v7 b* O& p+ R
24 L6 r2 R" \% t) D+ i+ j: i2 z+ x
3 2 J7 A6 n8 G6 Q+ @6 T5 G, Q0 Y9 i4 ) p/ S/ M0 m% r' i5 % m K" Q# @4 P3 x; u6 4 E+ V6 g2 r8 k7 O0 o3 F# y7 5 Y5 [" Y: L% W% _8 Y/ K& @, W. z% t1 l% C! R
9 0 H; J3 k* p$ O2 q9 e10 # q5 y: W6 m& d11+ k$ n" Q" R( D" S5 o& G+ W
12' X: r# L7 e$ i4 C ]
13 ' q* k( Y, R/ S! n14 0 B8 B; [" z7 C152 V' h {* |/ E/ @, ?/ E$ f: |# J
16 V. f h8 S. X3 C% d177 }" G( `2 d" ^ t- v, a
184 a! F# o- ^, W' h4 o
19* x8 c9 o& \- h8 @) U8 a
20 : O9 [7 }$ Y' d! ?2 @7 `$ B21 / b# m4 ?2 B. C% W V22" w- t2 Q: ~ }, c1 V
23 ; H1 G4 g3 H: I( ]# Y: M245 {3 w' e) v* t& }: b3 ^
25 9 W) Y1 }) N3 o26 3 L }1 u/ ^' ~1 ~1 Q27 ( b4 A# l# p+ G3 b/ N4 f28 ) \8 k) `4 Y+ m4 ?) ~29 : n/ S w e5 c; ]3 t30' ^/ @7 H* b( J+ E1 M. y& [( T
31 + Y+ ^6 C* Q0 c4 ]32 # L+ G1 P# _3 `" j$ B上述结果我们可以看出当父类变量被赋予子类对象引用时,其结果和子类变量是一样的。 ; h: r0 h' a7 J E- P, Q $ M! L4 h! q4 p- T- h3 _getClass 4 d5 B" j, H( g# }; y3 \- d& ^0 k
public final Class<?> getClass() 5 q, K5 G D; j1 t$ W1 0 e, c, v& V3 @* UReturns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.8 T$ q7 |; ?2 P
public class InstanceofTest {2 k" R o! [, q
public static void main(String[] args) {' G4 x( _$ A4 U
Father father = new Father(); 8 d2 `/ R4 g- B3 ]- D+ y System.out.println(father.getClass()); // class Father$ o3 ]1 U" h5 X3 l0 S+ K& Y
Son son = new Son(); 2 ]+ S" g3 k; u father = new Son(); P# M. q- k' t5 a9 o# M
System.out.println(son.getClass()); // class Son * W# J' _" S( @' l' h$ N5 w System.out.println(father.getClass()); // class Son 7 C, I% ]! {9 }8 t- _+ Y% |1 L( r+ ^# g8 J$ g" s+ R0 }' S2 z
} ; a' p4 z( o# H$ s0 |} B P' c1 X" t) y7 G) ~
& j9 q1 C% h& ?( E5 g: s6 _$ K' j
class Father {& c& W* w) {5 b
# L2 M; y L4 \& J! f
} - c& y: ?8 L+ K* Q9 H- B6 x: |' J. ]% c3 b. T
class Son extends Father implements MyInterface{ % ^3 L- ]# Y5 e( b1 K0 Z/ x) o0 {. f5 S; {* b7 ^' w
} & X4 j0 ]( _) w6 g# }; w ( w8 ]! l3 a- z( [( E# Einterface MyInterface {9 [ \/ y! e( x* r
8 Q0 v. {+ S# b' c% h
}* V& T/ n4 `' ]
1 6 l3 q! Z5 {! o3 N2 + [- y& T" b8 m, K! _! E34 V3 F! Q/ T3 H, K1 z7 ?
47 d8 ?1 _+ b5 l( y$ q! t) m
5% y. P2 Q; n6 o% W+ T5 U
6 : l9 r# I. A: J8 \4 G7 1 i8 h- U: I3 N% m. {/ L8. M0 b9 y9 C4 ?4 N
9% l1 i! H* G0 W! \ j4 y+ M; ^
10 ! Y! P! V" |. r; Q7 _9 |, I11 7 J2 T8 X/ M1 ]12 , i4 \7 x+ D$ Z8 M+ M; v# d7 [13 ! y% W* C( E$ ^) f% R4 V14 ! N& b- l3 m5 f* P6 [0 q) F1 f: C15 . L# A) q# L" |) T! M G, t. I16( i; \7 p$ o) O7 c' V9 }
17* b8 Q- J$ c& }
18 5 {" D. N* g# H& ~! L1 F; K9 y# g197 f; G1 P+ Z0 h2 c2 D- |1 ~
20; z. I( E/ l |4 i8 B% d8 G: A
21 " Z8 x9 @. H4 c+ S8 q22; E5 C3 D0 Y7 P
23 7 _* e) `' z/ i观察上述代码我们可以发现,getClass所返回的值与对象变量此刻的对象引用有关。; f# g" }) B" b
+ ^3 A9 o, k" d' y @Override5 O8 d$ ]* S- q
public boolean equals(Object o) {- F% ]/ V* x8 _. g& n
if (this == o) return true; 1 V( U5 F& q* ^" L& h V if (o == null || o instanceof Father) return false; - c! D5 V" b" c, `4 a' n Father father = (Father) o;* P% D; E9 t+ O- I: `* w
return Objects.equals(name, father.name); * s; A3 g/ r3 t6 E' @- k }3 F! r8 o: Y) J: Q4 h6 g
} * @# d5 D' G/ r9 ?# E8 o/ @. d i5 T) C- ? f* l/ X" e ~
class Son extends Father implements MyInterface{. D3 }6 a6 u" J! o2 k+ _8 U
private int age;' f7 Z( n5 j* J5 r5 E) q
" }7 V' x7 n3 ~# Z4 _
@Override" ]4 b1 _* f3 s3 {
public boolean equals(Object o) {" E7 I* q/ N* x9 ]
if (this == o) return true;) @$ {0 n8 _% K# Z
if (o == null || o instanceof Son) return false; // not good * `6 s7 B0 T+ r' T$ n" T if (!super.equals(o)) return false; T* w+ _2 ^, p: s4 a
Son son = (Son) o; ; y) l# d6 S# y7 ]3 P return age == son.age;: b/ j+ E! z: [& d s
} . @2 D3 s' i, o- n9 u( A* u. F}9 Q4 ^' |8 f$ G( G6 T7 I
1) z1 I9 ~5 _, r& K$ t- {
2 2 c0 ]. W& q$ ^# p3 # R' o; {8 m8 ~, ?% [8 u+ F6 |4 w4 / W; I7 F) \! O2 J& `& N8 a2 @5+ n1 d# W& q- A' ~0 t2 @, v! e
64 l) b# r2 p/ O5 F7 b" o6 t
7& e! V/ @& [5 t+ k& |
8 2 ^3 g+ b, c! z# j4 k. b# S9& [8 ` P% c7 B1 d" Y5 p3 p
10; S: s% a; S: n% P
11( a7 A, f) p4 B0 [* `# J
12( _( _3 H3 q9 q8 I% t
13 , k) d) v' U2 w2 X2 @; i3 m) ^14 4 ~! G' p$ U! }3 @' |157 `5 {9 ~% } i: S/ T* {
16# m4 Z$ S$ L& z/ }
17) G2 C( o* F% ~1 G% @, o
18 $ C4 I: M7 r3 ]& l' u19( V0 v' a; [+ y: u; y
20; J) h0 n. o6 W( i
21* K4 e3 {8 G- \$ Q
22( t# U! g5 d# [) k8 S2 B
23. m* t8 \' u4 _) E
244 N( R6 T. _4 n' ?& E
当运行 f.equals(s) 判断时(f 为 Father 对象, s 为 Son 对象,假设两个对象中 name 一致),根据代码会返回 true, 但是当运行s.equals(f) 会引用 instanceof 判断失败而返回 false, 这就不符合自反性。 5 W7 a% p/ y- X1 X( J. F, ~, D# o# n) l0 M) Y9 H; `2 X* m h# ^
综上,我们可以得出结论% {1 g- i8 C1 A5 l
; X6 [8 d/ g/ O9 W如果子类有自己相等的概念,如 Son 对象还需要比较彼此 age 是否相等,则对程序需求将强制采用 getClass 进行相等性检测。4 \, N9 C* p" X
如果有超类绝对相等的概念,那么可以用 instanceof 进行检测,只需要超类提供 equals 方法,并且要标为 final, 子类全部继承超类的 equals 方法,这样不同子类之间也可以进行比较。# a" u e. M; \" o" ?
复写 equals 方法的步骤:! w: a% o6 N% K. F; O
0 [1 M* a0 g: K/ h& B q
现实参数命名为 otherObject/ s9 m1 E% ?6 N8 V* x3 S- p
检测 this 和otherObject 是否引用同一个对象: if (this == otherObject) return true; ; E1 `2 ^8 G: c1 @检测 otherObject 是否为 null: if (otherObject == null) return false; k& n6 a9 l/ ^比较 otherObject 与 this 是否时同一类,如果 equals 语义在每个子类中有所改变,就使用 getClass 进行检测: if (getClass() != otherObject.getClass()) return false;如果所有的子类都有统一的语义,就使用 instanceof 检测: if (!(otherObject instanceof ClassName)) return false; K9 Z) W: u3 A
将 otherObject 转化为相应的类型变量:ClassName other = (ClassName) otherObject, Q2 `' d2 M3 Y
进行域的比较,如果是基本类型使用 ==, 如果是引用类型可以使用 Objects.equals(), 如果是 数组类型的域, 可以使用 Arrays.equals()进行比较。 : \( O. ?4 i& P; Z$ n! r" b6 k+ @hashCode 方法 2 B; C% I; F S( Y! T9 r5 }+ l q: Y5 a
散列码(hash code)是由对象导出的一个整数值,散列码是没有规律的,不同的对象其散列码一般不同,. ]( @3 d# N% h& U& [+ F a( Y
9 j& j6 m \6 T8 J3 zThe general contract of hashCode is: 6 X( W0 Y \" M" ~Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.4 w% N+ L) l U9 m' e. ?
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.6 _% C0 W9 @3 ^. m: p) p- Q
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables. 6 {3 u7 c0 r' ^/ ^As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)[2]1 z3 R- F( P$ c. p5 _
翻译: # w8 q1 P, j6 c' N- V在一个 Java 程序的执行中,无论何时,hashcode 返回的值都应该是同一个7 m, X1 X3 n4 w: \6 n, l( W
如果 a.equals(b) 为 true, 那么一定有 a.hashcode() == b.hashcode() 0 R/ p0 E$ I4 S- c1 F* q! ]. L% Y如果 a.equals(b) 为 false,那么 a.hashcode() 与b.hashcode()不一定不同 - ?- ~% t& g- b: b! s) epublic native int hashCode();' R. `6 R) I, B
1 " x7 q' q2 i) ^$ H; S. Y以上为 Object 中的 hashcode方法,我们可以看到这是用 native 修饰的方法,表明该方法是使用了 JNI(Java Native Interface),使用了 C 或 C++ 进行实现。在实际情况下,大部分不同对象会 生成不同的 hashcode(通过将内存地址转换为整数) 2 e+ H; U+ i4 R4 \/ Z! u7 `9 s1 A' A+ m
The main objectives of native keyword are:[5] " N! ? ^# ^ `- A2 o. D* G) f& x6 _: {3 y
To improve performance of the system. % y4 a; `' Z% ?- v) \To achieve machine level/memory level communication. ( l5 w6 O) a* h+ s0 g( x8 B7 dTo use already existing legacy non-java code." g/ Z3 q5 m; M! m, B
测试代码: . s; c3 Q- I/ ?. W * w/ u, y3 N. A7 ?" _7 I/ Hublic class HashCode { ) W! o, x% \; D2 |4 a }; D8 b: o0 e4 }
public static void main(String[] args) {& g$ R$ {, d: k& d- z
Map<Student, String> map = new HashMap<>();8 N' ~, v5 D, c5 W
Student s = new Student("Alice", 11);, i0 d }, w& Z: f# r
0 v+ Z- P& x0 {: }6 H
map.put(s, "Alice");/ G+ s& @' ^6 H- D. z; D- f( Q
map.put(new Student("Bob", 12), "Bob");0 B( ~" T) H8 F [
map.put(new Student("Cici", 15), "Cici");4 o8 c% y( M8 Y0 U! e
6 c* P$ A, t. {% W if (map.containsKey(s)) { 2 Q2 S1 f3 g6 X! O: Q System.out.println("bingo"); // bingo * o3 Z! B7 d: H, I9 J1 V' V } : p% |) |( W, r% ~# x( k Z$ m9 v( d$ q, `0 a. e
if (map.containsKey(new Student("Bob", 12))) {; D5 W: g: L% e; X' ]7 D% F
System.out.println("hello"); // hello % K( H; S8 H! t E& V } 3 A9 Q; j; c) M9 p( I. a }% @. v, ?, W5 t. m. J$ j8 A
/ L D5 i3 u( ~9 r' o! k! r2 Y
}0 r! _) o6 q" ^0 Z
4 T6 ]- z" W3 Y0 k& H
class Student { 5 X* W- U# b0 ~! B# e private String name;3 L: @6 k# J' E/ G9 |/ @4 H
private int age;' Z7 ? h3 l% a7 E& M
+ k1 \$ N; r5 T$ u1 p, F3 L
public Student(String name, int age) { # Z" y, [: y# x o. L this.name = name; & h) g( D \4 Z) z. R this.age = age; & q/ c' V: @, p2 ?3 [, g9 g( u } 2 T$ ^7 c; Q! R, ]; c7 `6 [ 8 a1 @# T- r" ]4 L9 O @Override & S: _" V) W# C. O6 w+ V' }/ k public boolean equals(Object o) { 0 \* Q V+ l( e0 Y& M if (this == o) return true; 2 o! Z7 a4 J& ~5 H$ b9 u: B) `& c if (o == null || getClass() != o.getClass()) return false;( V7 W ?2 J, v! |! f) f6 t
Student student = (Student) o; + \0 J" A( k% I4 g return age == student.age && ( P+ B3 P- Q1 S Objects.equals(name, student.name);" Y$ M+ X! U/ M% }. D4 D3 u
}0 _) W& j/ w3 M1 N