4 [9 f& K! O& @7 d, M与一般方法名不同的是,构造方法名必须和类名保持一致,并且没有返回值。6 V* o& @! J4 \, s; } T
Java编译器会自动创建无参构造函数,因此在类中,无参构造即使没有,我们也可省略不写。实例化对象时无需赋值。 $ P0 N' T; a6 p3 A; K; K倘若类中已存在有参构造函数,则编译器不再提供默认无参构造。实例化对象时需赋值,不然报错。& B9 p2 H* L7 C' v. }8 I, U$ D
当类实例化一个对象时会自动调用构造方法。 - m# @/ t- I9 Q3 I构造器在Java的继承中会产生什么影响呢? ! V- `7 ~7 b& _6 g# `9 w0 v5 S! G# n% ], H8 k+ j9 O* h
我们虽然继承了父类但是父类的构造器是我们子类继承不了的,我们只能去调用父类的构造器。那么在继承并且编写子类的构造方法的时候就要注意两种情况了:1.父类没有重写了构造函数(即构造函数是Java默认给的一个构造函数);2.父类重写了构造函数。 6 [9 p4 ]: t; F% y) R1 A. f9 a: i% i4 y0 ~
父类使用默认构造器1 x2 c+ L7 h6 h4 b" c. w- L8 T, X
7 h( r% K* X; ~
package Extends;2 O1 A0 a- [2 C" I) ^0 y z
: l0 ?- V% l6 F6 |& h! Gpublic class Father {2 E; C: r: z, e7 F4 v: u
Father(){ //默认的看不出区别所以这边设置个无参构造器效果一样的 $ `4 P% A/ N" D6 y; ^, a3 h //当你不定义的时候就是这个构造器 : x8 M& Y3 f4 ?* z System.out.println("This is Father Constrctor");! @" c4 t8 d& N: C/ o$ G/ D3 d- A
}0 b0 s; d# `4 T2 o- V6 S3 Z& W
} 4 @! i0 m8 {2 @: q% H. Dpackage Extends;# U& S- G8 c6 K2 Z" H$ K9 {
1 G# {3 z* o0 i/ D% upublic class Nosuper extends Father{2 u8 ~0 @: }$ `: D: L. q6 Z+ @
Nosuper(){ //定义子类的构造器9 l. c' O) Y ^1 }1 @( P' m4 |" f
System.out.println("This is Nosuper Constrctor"); + C4 F& j! ~5 A# }/ P }( E" n3 w9 ^3 A1 t
4 u: b2 d/ j. q$ P
public static void main(String[] args) { F1 ] \6 C9 \1 w7 b4 E* K, p // TODO Auto-generated method stub % e; ]1 \* O! H9 k, u1 w" p; i Nosuper no=new Nosuper(); $ E2 h+ T0 N. k& i# B% U( m } ( m7 P6 a2 S6 U0 R V3 X& L$ T9 d
}1 J) }' D+ ]: s. C
OUTPUT:$ P0 U+ R2 `3 K" U1 `" h- p% N
This is Father Constrctor ' X- ]5 k! x% k2 FThis is Nosuper Constrctor & J% u9 I# E D, z0 H' ~父类不使用默认构造器3 w( ^+ ^4 x0 {0 P) U: i
: L3 D' K+ k0 ] Epackage Extends; 5 s( U6 {9 c) L8 G2 C ) V% I# x' x6 Kpublic class Father {! j0 {4 z) k* { b
Father(String name){ 1 p e* g! a: U8 A System.out.println("This is Father Constrctor,name is "+name);% i9 M8 {, m: C9 S `* h- K6 C7 p3 t
} T0 k+ n T) p8 L. a3 i}$ n1 ]* e* I, g# \1 P
package Extends; 7 \. d1 h4 _. m6 T8 K) ]) b% y% O) V' H3 B9 l
public class Nosuper extends Father{2 J5 c% M4 J3 S, k9 Z" M
Nosuper(){ 0 I% \1 g& x( k) \ _' p/ I
super("YYH"); //必须先调用父类的构造函数否则会报错( r2 n! ?: M v. k( Y }5 [( w
System.out.println("This is Nosuper Constrctor"); {! |; a5 w q5 H& x: E
} 7 A. ?0 N2 f" j8 u/ [+ I public static void main(String[] args) {0 U& N, B/ j) {
// TODO Auto-generated method stub ; P' P3 ^3 m, V; B Nosuper no=new Nosuper(); 7 ~# b: ?1 X+ ^& w } 7 G6 S. v( O* h9 k4 [9 w0 ~3 I}. @ }, E4 c# h7 M$ ^
OUTPUT:; E- [6 H9 S8 |4 u9 O4 R+ R. d
This is Father Constrctor,name is YYH, ^ Y# [& v9 O$ M# B0 A
This is Nosuper Constrctor $ e% C9 u9 a: J8 t: w: r$ a% s总结:对于继承来说,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要调用父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。 * o. v+ q! `4 i; C9 Q- c6 i8 \/ O& d$ J2 x
/ h/ x% q$ h. S. x8 m0 @7 N( j: t7 x% E* I9 Y9 b8 r
继承中的向上转型% ]8 }( P+ Y1 L- y2 m2 o y
* u7 g/ ]! p7 U2 x; v# N当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。$ c& d2 Y4 F/ Y b
! J+ K' w3 J5 n1 u& ], f' P
package _4_8;% n' m$ D: ]/ D. X5 j
$ `) `: c/ W B7 D4 ]class A { 2 H) F. q; B3 m D. t$ | public String show(D obj) {$ d4 T" A: @1 S, I7 y% T
return ("A and D");$ T2 G- l3 q9 z7 A% [! O% p
}- X+ k2 i. J$ s
public String show(A obj) {0 O, L, f3 c e2 g
return ("A and A");" u9 i/ x9 y) T1 C; [" F
} ( p; @9 M1 }3 |. x% }: _ $ [- Q& u" V9 k} , g$ C& Z0 {8 P9 n+ P1 r+ V& V ^; X2 J
# `! @4 k' I0 b" x6 r+ S
class B extends A{+ M9 W i* q# z& u
//重载. ]/ X/ _5 ?' M4 a5 d! D K* ]
$ ?1 L: u& n$ g4 D. n8 C public String show(B obj){ . r/ B+ k) D6 W; W6 S+ m6 I3 x5 L! A return ("B and B"); 9 w. z: w7 ~& p4 L }) W5 T9 O6 `/ C% V1 \/ U
//重写% h: O5 [+ h, Z/ {+ L6 s* ~
public String show(A obj){ , m$ o, p( v6 e7 s' a' Q return ("B and A"); 4 t' D* ] H7 T3 a0 B7 @5 t } n" ~5 C# W2 h* g$ S ~
3 r( H7 O3 j# X4 z, p+ m
} ; ?1 [; X9 d9 _+ B3 P6 t P% d* w
- {/ {9 O% X8 o& y' Vclass C extends B{} # I/ I0 w' |5 qclass D extends B{}4 {; |. Y( k' i
public class t { ( J) O5 s+ _6 c9 O5 G8 R public static void main(String[] args) {$ q& {% y+ i9 k& O+ N
A a1 = new A();" A& I6 h( N8 V% l* O) x5 q8 b% N
A a2 = new B(); //1.只能调用子类中重写父类的方法,不可以 ( M- z) D1 ~# k5 p //调用重载的方法2 J8 f e( ^9 K, ^' v
B b = new B(); 9 l$ M1 W3 t' D$ [ C c = new C();4 J3 w& e$ c, k2 {# E+ d
D d = new D(); % Z$ Q4 }+ v4 |$ f% r$ E" Q System.out.println("1--" + a1.show(b));2 R! y. O; l V1 I; J/ \
System.out.println("2--" + a1.show(c));" b# M8 _3 r5 @+ J% R* F
System.out.println("3--" + a1.show(d));2 |4 a% Q# |" @4 C8 @5 u
System.out.println("--------"); 2 ]- u: ?6 F5 I" w" A System.out.println("4--" + a2.show(b));2 Z L8 x* y9 v5 y6 ~8 U1 }0 w& h5 Y( H
System.out.println("5--" + a2.show(c)); - c% [1 M0 w. y System.out.println("6--" + a2.show(d));( E8 k8 {, y" V% c, d
System.out.println("6--" + a2.show(a1)); 5 d) \" O* k0 s1 m System.out.println("*"); 9 f R$ d- }# v, o( I, f B( r System.out.println("7--" + b.show(b));3 h% R" B* g# V V) W; K
System.out.println("8--" + b.show(c));: d( S: P% R* I, X! V# G
System.out.println("9--" + b.show(d)); 5 t/ f; p# b' `, Z, u0 @ }8 U+ ?# L0 a+ I6 i" B( Z. S- f
}9 ` K- G+ Z9 L6 I; W
OUTPUT:5 Q. U+ w9 D# T6 D; @* y' M
1--A and A' q8 G7 A5 i& i5 B- z
2--A and A( X C. a6 l. V! ?/ V4 B$ W8 j' J
3--A and D- P: w! F1 [$ M3 e% k+ I8 k
-------- 1 J7 n, E: d+ }9 U4--B and A0 \) ]( x1 ~, h5 d! q6 e" w% T
5--B and A! R: S. y" R+ a7 T3 ~: D3 o) ~
6--A and D1 h( w) o* y1 U
6--B and A7 t0 z, c' D. t3 _/ K7 b
*+ N$ b" s4 t- C, l: B6 H! T
7--B and B: W \/ E4 e( i0 \6 M
8--B and B! }0 u1 }7 }6 I ?+ z: b' U4 S& h
9--A and D2 U7 ~$ P& E3 k! M3 k [
仔细理解一下其中的代码不难理解其中向上转型在继承中的作用。按照this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)这个顺序一步一步的执行就会得到结果。 " |2 v o7 y5 P2 L d6 @& i! u- O6 ]/ B
将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。' ^( G# w4 f4 ]: H3 h- W
7 i% h7 f+ p6 e7 \继承慎用$ ~: S4 S) b( Z0 J
, o5 Y( d- M( [. G( |8 l. a
你会感觉当你在编写三四个程序的时候用继承解决了他们公共的部分是很方便的,但是如果你程序很大,class很多而且都继承于一个类中,当你想通过改变父类的一些信息来改变一个子类的信息的时候就会发现其他的子类也会随之改变,有时候会对其他的子类产生不必要的结果。$ e/ J7 f: h- S. G2 ` F
& t$ T! Q* k- y; E( F. z' Q父类变了其他的子类就会随之全部改变。 8 P3 p' a) C3 W- R8 F& u + y+ R5 {# x: }5 ~" C继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。 $ T7 F: z0 p( F; @9 i ( [; b) S: I% e# D( O0 k继承是一种强耦合关系。 - O8 Y- |' M$ H1 w' k3 _ 5 {1 a" q: u4 ~" f/ k6 p2 s$ p“问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承”——《Think in Java》 0 M9 `# l9 B+ x0 J% J$ W) n# i2 H
7 K5 D4 u: ?" a- `
后言" x, \1 a) i% K) E
. K, I( R1 G! H. ?: p, E
这些都是自己翻阅资料或者是查看其他大佬的blog总结的,如有侵权请告知!!!如有错误请指出,谢谢。 ( ?' m& C- |9 H3 [/ ~9 I H }! R8 c7 [6 z p
希望对你们有所帮助,本人也正在学习Java的路上也是小白一枚,还需要大佬们的多多支持。6 L2 f+ L7 h1 G# A+ R; l) j+ c
: o" ?* V7 U( o4 W% N ; x+ \( @1 J, [9 |4 u' s' c. f) U————————————————$ ^1 K1 P3 t7 _( s, i R* J
版权声明:本文为CSDN博主「YYH-ZC」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 f! j- b, s# V. A( _1 E$ B k
原文链接:https://blog.csdn.net/weixin_45629315/article/details/105876883* A/ v( o$ g6 Y+ f7 x
% u: h. F2 N8 _' g. K7 k4 X n6 X5 B0 ~8 S1 i/ k T) a