类方法
方法被声明为sta tic后,则称为类方法。类方法相对于实例方法,前者区别于后者的地方:前者为属于该类的所有实例对象共享,无须实例化对象,仅通过类名即可访问(当然,是否能够直接访问,还取决于所声明的访问权限)。
因为被sta tic化后产生上述特殊性,所以stati c变量都会在类被加载时初始
化,而类方法也同时随类加载而进驻内存。先来段代码热热身吧~
publ ic cl ass T est ...{
publ ic st aticvoidmain(Strin g[] a rgs)...{
A.p rint();
Syste m.out.prin tln(A.publ icStr);
}
}
cl ass A ...{
pr ivate stat ic Aa = n ew A();
priva te st aticStrin g pri vateS tr =null;
pu blicstati c Str ing p ublic Str = "A C lass";
p rivat e A() ...{
pr ivate Str = "A C alss";
}
pu blicstati c voi d pri nt()...{
Sys tem.o ut.pr intln(priv ateSt r);
}
}
上段代码,输出结果为:
null
AClass
由结果可知,即字符串p rvate Str的值为空。嘿,可别认为值应该是下面那样啊。那样的话,进行下去就太具挑战性了。
A Cla ss
A Cl ass
请记住一点,类变量初始化的顺序与其在类中的赋值顺序一致。
重写(覆盖)
或许大家对于面向对象编程语言最初的印象就是其语言单元是以父类、子类的关系存在着,而构建这一关系的就是继承机制了。子类可以继承父类一切非
priv ate的变量与方法,并且可以添加自己的变量与方法。在构建一个系统时,这机制让我们强烈地感觉到编程是一门优雅的艺术。
来段小小的代码简单地展示下:
p ublic clas s Tes t ...{
p ublic stat ic vo id ma in(St ring[] arg s) ...{
Progr ammer pro= new Prog ramme r("Ja ck");
pr o.pri ntNam e();
pro.prin tProf essio n();
}
}
class Man...{
pri vateStrin g nam e = n ull;
pub lic f inalStrin g cha racte risti c = "I ama thi nking anim al";
pub lic M an(St ringname) ...{
th is.na me =name;
}
pub lic v oid p rintN ame() ...{
Sy stem.out.p rintl n(nam e);
}
}
c lassProgr ammer exte nds M an ...{
priva te St ringprofe ssion = "P rogra mmer";
p ublic Prog ramme r(Str ing n ame)...{
sup er(na me);
}
publ ic vo id pr intPr ofess ion() ...{
Sy stem.out.p rintl n(cha racte risti c + ", and a "+ pro fessi on);
}java重写和重载的区别
}
结果如下:
Jack
Iam athink ing a nimal, and a Pr ogram mer
如上,子类Pro gramm er中并没定义字符串chara cteri stic,但我们却在其方法pr intPr ofess ion()中调用了;同样,我们正常使用了父类定义的print Name()方法。而这就是继承的简单实现。
继承不仅仅带来以上特性。它还赋予子类重写(覆盖)父类方法的能力(因为旨在讲类方法的重写,所以这儿就不讲重载以及变量在继承机制中的问题了)。方法的重写(覆盖):继承父类的子类,可以通过拟具有相同方法名与参数组的方法来重写父类中对应的方法,从而让子类更个性化。又因为重写(覆盖)的出现,多态也随之产生。多态:通过父类变量可以引用其子类对象,从而调用子类中那些继承自自己并被重写(覆盖)的方法。
pu blicclass Test ...{
pu blicstati c voi d mai n(Str ing[] args) ...{
M an ma nP =new P rogra mmer("Jack");
ManmanS= new Stud ent("Tom", "May BeHar vard");
manP.print Name();
Syste m.out.prin tln();
m anS.p rintN ame();
}
}
cla ss Ma n ...{
p rivat e Str ing n ame = null;
p ublic Man(Strin g nam e) ...{
this.name= nam e;
}
p ublic void prin tName() ...{
Syste m.out.prin tln(n ame);
}
}
clas s Pro gramm er ex tends Man...{
pri vateStrin g pro fessi on ="Prog ramme r";
publ ic Pr ogram mer(S tring name) ...{
s uper(name);
}
pu blicvoidprint Name() ...{
S ystem.out.print ln("H ey, I am a " +profe ssion + ". Youknow, that work is a n art.");Sys tem.o ut.pr int("My na me is ");
sup er.pr intNa me();
}
}
clas s Stu dentexten ds Ma n ...{
p rivat e Str ing s chool = nu ll;
publ ic St udent(Stri ng na me, S tring scho ol) ...{
supe r(nam e);
this.scho ol =schoo l;
}
p ublic void prin tName() ...{
Syste m.out.prin tln("Hi, I am a stud ent f rom " + sc hool);
S ystem.out.print("Mynameis ");
s uper.print Name();
}
}
结果如下:
He y, Iam aProgr ammer. You know, tha t wor k isan ar t.
My n ame i s Jac k
Hi, I am a stud ent f rom M ayBeH arvar d
My na me is Tom
Ma n类型变量引用其子类对象,并成功调用对应方法打印出个性化的自我介绍。
类方法的重写?
进行到这儿,对类方法与继承、重写等概念应该有较清楚的认识了。如果您不是很清楚、或者我上面介绍得不够详细,请参考J ava的圣经《The Java Lang uageSpeci ficat ion》
现在开始本文的问题吧:
pu blicclass Test ...{
pu blicstati c voi d mai n(Str ing[] args) ...{
M an ma n = n ew Pr ogram mer();
P rogra mmerpro = newProgr ammer();
man.print Name("ManC allMe");
Syst em.ou t.pri ntln();
pro.p rintN ame("CallM eByMy self");
}
}
cl ass M an ...{
publi c sta tic v oid p rintN ame(S tring name) ...{
S ystem.out.print ln(na me);
}
}
class Prog ramme r ext endsMan ...{
publ ic st aticvoidprint Name(Strin g nam e) ...{
Syste m.out.prin tln("Hey,I ama Pro gramm er. Y ou kn ow, t hat w ork i s anart.");
Syste m.out.prin t("My name is " + na me);
}
}
结果如下:
Hey,I ama Pro gramm er. Y ou kn ow, t hat w ork i s anart.
Ma nCall Me
Hey, I am a Pr ogram mer.You k now,thatworkis an art.
M y nam e isCallM eByMy self
“结果绝对不是这样!”如果运行过这段代码,您一定会大声的对我说。的确,结果事实上是这样的:
Man CallM e
Hey,I ama Pro gramm er. Y ou kn ow, t hat w ork i s anart.
My name is C allMe ByMys elf
按照多态的介绍,结果应该是上一个啊!?为什么事实却是纠正的那个呢?难道重写(覆盖)没有成功?事实上,重写操作是成功的,因为第二个函数调用输出的结果证明了这点。那这一切的一切的问号是为何呢?
方法被加载的顺序是这一切的根本原因!
当一个方法被调用时,JVM首先检查其是不是类方法。如果是,则直接从调用该方法引用变量所属类
中到该方法并执行,而不再确定它是否被重写(覆盖)。如果不是,才会去进行其它操作(例如动态方法查询),具体请参考:方法的加载
具体到上面那段代码,因为引用man是Man类型变量,所以JVM根据上述规定,调用的是Man中的print Name(),而不是Progr ammer中prin tName();而p ro正
是P rogra mmer,同理,其调用是自己的print Name(),出现料想外的结果也就纯属正常了。
最后,以一段有趣的代码结束本文。它也是本文对于类方法理解的强有力证据.它正确输出了结果,呵呵~
pu blicclass Test ...{
pu blicstati c voi d mai n(Str ing[] args) ...{
(Man.g etMan()).p rintN ame();
}
}
cla ss Ma n ...{
p ublic stat ic vo id pr intNa me()...{
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论