& S3 y5 z* B8 O8 ^; i6 W4 tpublic class Father {( Q8 u0 z) X5 F9 X! a" ]
Father(){ //默认的看不出区别所以这边设置个无参构造器效果一样的: e) W+ G1 j4 C# G+ c
//当你不定义的时候就是这个构造器 ) g5 A# E& r. ^, F System.out.println("This is Father Constrctor"); I4 z/ `- }) \; [3 k
}$ y# |- Y/ L: h
}' B, Z+ z6 f; p
package Extends; 1 Z3 A8 U) p" N% f- r + E6 l9 Z+ W) \" {* q% N, y. Mpublic class Nosuper extends Father{ $ ?$ P L" h5 i" A6 f+ t, u+ ~ Nosuper(){ //定义子类的构造器 # c. B; h1 j' S6 |4 s# n; d" a System.out.println("This is Nosuper Constrctor"); ) U) A8 @$ ^9 @, y }% v* T2 ]2 v4 a3 j" c1 v6 k! I
% a# e9 X5 U3 c2 d5 b' V& L4 p
public static void main(String[] args) {; O, z$ ^1 i) S
// TODO Auto-generated method stub ! b3 `5 W$ P. [ ` Nosuper no=new Nosuper();1 L' I9 p1 r' {3 g! B
} ) t- E5 Q. \3 ]. D* h' j4 O' f; s l! D4 k# r& |4 [" i/ G6 V) t
} ( y0 C* L6 ~/ v# nOUTPUT:5 a8 n2 W# y; r |" M8 M
This is Father Constrctor( u% T2 l B; Y2 a- N3 l2 l
This is Nosuper Constrctor " T" T$ C3 K0 s5 ~( w. b& s Z Y父类不使用默认构造器5 I) u- G7 E# u5 F" E
( J/ L ?- v( P( r0 n' ipackage Extends; 4 u2 E4 _ t5 R9 U! K9 j* n7 `/ \% N9 j0 b+ X1 i7 g7 B
public class Father {& q. Q3 M( f/ I7 t% f0 l' V" P
Father(String name){9 `5 c3 U% h6 Y a0 e& a
System.out.println("This is Father Constrctor,name is "+name); 6 }8 y) [2 n5 T, n& m }7 k9 P, p" X# i7 K# ]
} & W3 D; s! v# X/ q2 opackage Extends;, m0 f" O7 F' l9 [. N( |# H) d# X5 `
, R/ ?; Z7 [4 v, D. |' o" k0 Wpublic class Nosuper extends Father{ : e$ W7 M# g6 ~ Nosuper(){ 9 X3 v1 z9 \+ i1 M' C. S( s/ \( K' \
super("YYH"); //必须先调用父类的构造函数否则会报错" _: c* V5 X3 Z9 V1 d
System.out.println("This is Nosuper Constrctor");7 f. p: ]) ^5 p$ j
} : v: Z' }& ~( C* r public static void main(String[] args) { % ^- `% F; {, x9 F% f. `+ l- t // TODO Auto-generated method stub N1 W1 \0 ^* l, I( W h
Nosuper no=new Nosuper(); 5 |& W6 t$ T/ `# y8 F }7 N! D3 z( s/ f4 G, Y' f. E l7 D
} 5 N" \4 m6 d" Y! SOUTPUT:1 E! w% I2 ?4 D4 G, y( c. o$ t4 i
This is Father Constrctor,name is YYH X H0 H/ `; e3 p+ W8 UThis is Nosuper Constrctor r( T, h: `$ X) W% ~
总结:对于继承来说,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要调用父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。0 ~$ q8 h- |' \2 z' A
j" O& K% m! \; Q3 F8 G8 h
2 X& T7 T' Z' i ' A! R% R1 H+ Q继承中的向上转型" U y, Y$ J( w Z1 F2 K
* C$ b7 x7 P/ x$ y
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。% @4 s2 n4 V* ?1 j* c- e
) U+ Y- `8 H G: Vpackage _4_8; 5 c9 `, M% ?. t, a5 c5 `7 k0 y ( k% |, n. ?, S' H6 y9 j& ?& `7 ^' Tclass A { ; ]5 ?! i/ d1 H( J2 v2 _0 P public String show(D obj) { 1 `' I* q q5 R* _7 F return ("A and D"); ; Z3 L6 y0 @2 D0 J% c } ; N3 ]# u. O6 p+ ?7 e public String show(A obj) { |8 O, L' `, S K4 l% e7 ] return ("A and A");* P* N u2 d K$ ~1 G2 v
} ; m! N3 [, P& t. l. R' S+ h 3 d) |, Q3 t5 a) \# I% e& P}* i" i0 L. g, ?5 a+ h% r
% f4 A. t0 r1 u8 e" c) O, F) c& ~& W' @* O6 O/ w0 v% k
class B extends A{ 4 t) F( z& e) Q5 N6 M. n //重载 N" _" c, `) u4 N+ w' Q/ k
. O0 y( H) I( d7 {. j: l- U+ K1 x
public String show(B obj){! m4 u3 t; `; f1 M
return ("B and B");% A% ~1 n7 t3 y7 I* G6 z" _
}5 V, T- \/ H1 L6 b4 R6 D9 k
//重写. T' L) m6 I+ n* l1 ]/ B
public String show(A obj){' N6 j6 `, h; @7 Q6 o$ W6 d3 Q
return ("B and A"); N7 V7 e* M7 ?# N } $ I$ u' x1 f; t S0 w
- a6 e# z, b5 O& Z V; s, S* s
}% w6 H* c9 F- l
. l T0 l0 E' h9 s2 l
$ X* N/ \: a8 n
class C extends B{}/ Y# f5 G1 ]) v6 r8 o
class D extends B{} / ~$ g$ c: Q8 S, ?) K, \public class t { ( P1 Y D/ R$ u. d, b& _$ A9 b1 ?9 Z C public static void main(String[] args) {$ k" z8 m" D, Z+ ^4 y; f
A a1 = new A();1 O7 g% T& @. L/ I4 h! w: @
A a2 = new B(); //1.只能调用子类中重写父类的方法,不可以 " m% S: d* j/ ~( |1 O8 C
//调用重载的方法 . }5 g/ {4 f+ o8 F8 q2 Z B b = new B();- _0 |. M& [# e% S; G3 c. |2 i `
C c = new C(); ! H( S- g( l- r9 |3 w. A. d, r# F1 x D d = new D();7 ~- u/ ^8 k4 N
System.out.println("1--" + a1.show(b)); ' U8 ]) X+ N2 d4 D! g System.out.println("2--" + a1.show(c));4 {0 a( e4 N. Q* _. O
System.out.println("3--" + a1.show(d));- Q+ v" }# d s9 N+ H4 O
System.out.println("--------"); 2 e" B- O# N2 @$ } System.out.println("4--" + a2.show(b)); 9 W ~& h$ s, `; H8 z System.out.println("5--" + a2.show(c)); 5 _3 S% {- _' N- Y2 A6 ~ System.out.println("6--" + a2.show(d));1 w- Q# X' l/ y9 W j' x
System.out.println("6--" + a2.show(a1));3 A$ B, o0 p6 y( z# E
System.out.println("*"); ! J: o8 [* ~5 S/ R* S& q. h) D System.out.println("7--" + b.show(b)); - t4 y/ ?8 e' c1 Y, o$ F2 ~ System.out.println("8--" + b.show(c));0 ?" _# i1 u# c' Q% B
System.out.println("9--" + b.show(d)); 5 Y: ?' s6 M( ?9 u! R. D' ~
}& v" c9 G$ X2 Q4 L; z
} 7 y: N& K& a1 H+ q6 F9 R3 \OUTPUT: % P$ C0 O; ?1 {* ^6 w1--A and A2 k9 J) b# w, ^
2--A and A 4 J- Q- Y* T1 n- k) G3--A and D 1 m9 P0 b5 k2 f Y5 g--------- ^) t5 {/ T7 B) q5 c
4--B and A 6 V$ g! [5 e8 U, t; ?5--B and A # r2 [9 h2 @ n! I* s6--A and D 7 a x, U8 l- w7 R* K6--B and A 0 T9 r$ u( H, k: W0 E*( T. _1 I5 m! @
7--B and B/ ]3 a4 A/ s8 N9 F& d
8--B and B R# f% B3 E( u! o9--A and D* y* i0 {) \2 m# t( h* Z/ s/ l, H
仔细理解一下其中的代码不难理解其中向上转型在继承中的作用。按照this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)这个顺序一步一步的执行就会得到结果。 : f1 T( h9 [, [ $ r8 J9 i B, ~ c$ @) I5 j7 P将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。9 v& B1 s6 ?6 b- [, m$ Y! y
1 U9 H) A' _9 f# [( ~
继承慎用- A4 F1 N2 m4 I& B! G: T
, a& I) l: x. M0 Z
你会感觉当你在编写三四个程序的时候用继承解决了他们公共的部分是很方便的,但是如果你程序很大,class很多而且都继承于一个类中,当你想通过改变父类的一些信息来改变一个子类的信息的时候就会发现其他的子类也会随之改变,有时候会对其他的子类产生不必要的结果。) A! u* U/ s' l0 p9 [1 _9 d
! l1 ], ?- Y9 X! d
父类变了其他的子类就会随之全部改变。0 {/ S) O7 \/ m7 T" C
}0 e0 v/ X/ S5 v% C/ D d
继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。7 X B$ r8 r- c) o0 `1 ~. R
8 @& |. g3 o& B5 n继承是一种强耦合关系。( x/ R: X' r- R- g, M8 u, d
, z$ G1 I0 r$ b7 R E“问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承”——《Think in Java》 ' S. v5 U, T; J- Q% f$ T N2 C" h, ?9 T# I6 {) C# D5 z8 N
后言. Y o6 G4 h" W9 a- S; k