java课件第八版第九章中文版.ppt_第1页
java课件第八版第九章中文版.ppt_第2页
java课件第八版第九章中文版.ppt_第3页
java课件第八版第九章中文版.ppt_第4页
java课件第八版第九章中文版.ppt_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

不变对象与类:,不变对象:指在实例化后其外部可见状态无法更改的对象。不变类:生成不可变对象的类。例如:不变类:Boolean,Byte,Character,Double,Float,Integer,Long,Short,String.可变类:StringBuffer,java.util.Date等不变对象的好处:只能处于一种状态,所以只要正确构造了它们,就决不会陷入不一致的状态。不必复制或克隆不变对象,就能自由地共享和高速缓存对它们的引用;也可以高速缓存它们的字段或其方法的结果,而不用担心值会变成失效的或与对象的其它状态不一致。,它们本来就是线程安全的,所以不必在线程间同步对它们的访问。这可以极大地简化编写并发程序的过程,并减少程序可能存在的潜在并发错误的数量。线程安全问题发生在当多个线程正在试图并发地修改一个对象的状态(写-写冲突)时,或当一个线程正试图访问一个对象的状态,而另一个线程正在修改它(读-写和写-读冲突)时。要防止这样的冲突,必须同步对共享对象的访问,以便在对象处于不一致状态时其它线程不能访问它们。类不变条件:所有成员都是private。不提供对成员的修改器方法(setXXXX)。没有可变成员的访问器方法(可变成员引用getXXXX),举例:三条件缺一不可,publicclassT9ChangableClasspublicstaticvoidmain(Stringargs)ChangableClassc=newChangableClass(originalvalue);System.out.println(c.getSB().toString();c.getSB().append(ischanged);System.out.println(c.getSB().toString();classChangableClassprivateStringBuildersb;publicChangableClass(Stringsb)this.sb=newStringBuilder(sb);publicStringBuildergetSB()returnsb;,本例的类具备前两条件,即类ChangableClass属性全部私有,且无setter。但对象构造后内容仍可变-状态可变!。,this引用:,代指实例本身的引用。因而,与类的实例有关。作用一:当方法中的局部变量与实例变量同名时,实例变量被隐藏,为访问该实例变量,需要在实例变量名前加this引用。作用二:用在构造器中,调用重载的构造器。this(参数表);/调用有参构造或this();/调用无参构造调用构造器时必须在其他语句前出现,否则编译错误!Super()也不行!有参构造必须显式调用!举例(作用二):测试如下内容隐含this(用于限定构造器中的变量)显式this调用重载构造器(无参中均先调用有参)默认无参构造器调用及顺序无参中均先调用有参是否导致父类构造器重复调用?!,publicclassT9Thispublicstaticvoidmain(Stringargs)Sonson=newSon();/用无参构造器生成实例classGrandfatherprivateStringname=grandPa;publicGrandfather()/无参构造器,隐式调用this(grandfather);System.out.println(name);publicGrandfather(Stringname)/有参构造器,须显式调用System.out.print(name);,classFatherextendsGrandfatherprivateStringname=dadi;publicFather()/无参构造器,隐式调用this(father);System.out.println(name);publicFather(Stringname)/有参构造器,须显式调用System.out.print(name);classSonextendsFatherprivateStringname=son;publicSon()this(son);System.out.println(name);publicSon(Stringname)System.out.print(name);,使用无参构造时:调用父类无参构造器时刻,使用有参构造时:调用父类无参构造器时刻,只使用无参构造器时的运行结果。父类构造器隐式调用,并按继承层次上从上到下顺序构造。子对象的构造包含父对象的构造。父类无参构造器只会调用一次!子类无参构造器调用自己的有参构造器不会导致两次隐式调用父类无参构造。,将Sonson=newSon();换成:Sonson=newSon(“child”);运行结果。同样,隐式调用父类构造器。,问题:下述程序执行结果?,classTeacherintvar;Teacher(doublevar)this.var=(int)var;Teacher(intvar)this(hello);Teacher(Stringvar)this();System.out.println(var);Teacher()System.out.println(goodbye!);publicstaticvoidmain(Stringargs)Teachert=newTeacher(5);,super关键字:,子类构造时要隐式调用父类的无参构造器,能否显式调用父类的构造器去初始化父类呢?如能,则对父类对象的初始化可依据需要灵活进行。super指当前对象的父类的关键字。一定想要在子类中访问继承父类的同名属性,使用super.属性名来访问(问题:不同名如何?)访问父类被子类覆盖的方法也用super.方法名(问题:未被子类覆盖的方法如何?)Super和this不同,它不是引用!Super只限于子类内部使用;this可传到类的外部去!,使用super:,publicclassT9UsingSuperpublicstaticvoidmain(Stringargs)UsingChildt=newUsingChild();System.out.println(t.getSuperField();System.out.println(t.callSuperMethod();classUsingParentStringname;UsingParent(Stringname)=name;StringgetName()returnname;,classUsingChildextendsUsingParent/子类全覆盖父类成分Stringname=child;UsingChild()super(parent);/显式调用父类有参构造器publicStringgetName()returnname;publicStringgetSuperField()System.out.print(Returnthefieldvalueofsuper:);;/访问父类同名属性publicStringcallSuperMethod()System.out.print(Callingthemethodofsuper:);returnsuper.getName();/访问被子类覆盖的父类方法,完全同父类,可见不是子类构造器中使用super时,无第一条语句约束。显式调用父类构造器则必须第一条语句。,举例:测试this引用可赋值给其类类型的变量,publicclassT9AssignThispublicstaticvoidmain(Stringargs)AssignThist=newAssignThis();AssignThiss=t.getThis();System.out.println();classAssignThispublicStringname=Test;AssignThisas;AssignThis()as=this;publicAssignThisgetThis()returnas;,举例:测试super不是引用,publicclassT9AssignSuperpublicstaticvoidmain(Stringargs)AssignSupert=newAssignSuper();AssignParents=t.getSuper();System.out.println();classAssignParentpublicStringname=Test;classAssignSuperextendsAssignParentpublicAssignParentgetSuper()returnsuper;,如是引用,则本方法应能执行(同上例一样),继承复用:如果想要一个类也具有另一个类的方法功能时,早期一般情况会采用将这个类去继承另一个类,这就是继承复用继承复用问题:继承一定是从一般到特殊的关系,父子类之间一定要是is-a的关系。而程序中的两个类不是/不一定是is-a的关系,不能直接设计为继承关系如果被继承的另一个类中有protected属性,那么在子类中就可以随意访问和修改,数据不安全,继承复用破坏了封装。(public更不用说!)对于被继承的另一个类中有些方法,子类不想要,但因继承却不得不要,破坏了子类的设计要求继承复用也称白盒复用,其要破坏封装。,继承复用和组合/聚合复用,组合/聚合复用:在一个类中维护另一个类的对象作为属性,然后在自己的方法中不写自己实现,而去调用属性指示的另一个类的对象方法来实现自己的方法。组合/聚合复用的好处不破坏封装不需要继承不想要的方法可以复用别的类的方法来实现自己的方法组合/聚合复用也称黑盒复用,不破坏封装复用总则:尽可能使用组合/聚合复用,不采用继承复用。,A类组合/聚合复用B类的方法resuedMethod()ClassABb=newB();reusedMethod(.)b.resuedMethod(.);ClassBreusedlMethod(),OO设计原则在Java中的体现:,类的设计原则:除了上一章中介绍的Java类设计的原则外,OOD中更一般的类设计原则:依赖倒置原则DependencyInversionPrinciple(DIP)里氏替换原则LiskovSubstitutionPrinciple(LSP)接口分隔原则InterfaceSegregationPrinciple(ISP)单一职责原则SingleResponsibilityPrinciple(SRP)开闭原则TheOpen-ClosedPrinciple(OCP),依赖倒置原则DependencyInversionPrinciple(DIP),两个原则,两重含义:高层类模块不依赖低层类模块,两者均依赖于抽象。(传统的面向过程的方法中,高层模块一般依赖于低层的具体过程,使得两者均难于复用!)。抽象不应依赖于细节,而细节应依赖于抽象。具体实现:,高层模块(抽象),低层模块,高层模块,低层模块,抽象接口,classAclassBextendsAclassCextendsA.以上是第一方式实现InterfaceCclassApublicvoidhandle(Cc)classBimplementsC,Cb=newB();Aa=newA();a.handle(b);,抽象,抽象,高层模块,具体,里氏替换原则LiskovSubstitutionPrinciple(LSP),所有引用基类的地方必须能透明地使用其子类的对象。2个条件:不应该在代码中出现if/else之类对子类类型进行判断的条件。以下代码就违反LSP定义。if(objectinstanceofsubClass1)elseif(objectinstanceofsubClass2)子类应当可以替换父类并出现在父类能够出现的任何地方,或者说如果我们把代码中使用基类的地方用它的子类所代替,代码还能正常工作。,违反LSP原则举例:,classRectangledoublewidth;doubleheight;publicdoublegetHeight()returnheight;publicvoidsetHeight(doubleheight)this.height=height;publicdoublegetWidth()returnwidth;publicvoidsetWidth(doublewidth)this.width=width;,classSquareextendsRectanglepublicvoidsetHeight(doubleheight)super.setHeight(height);super.setWidth(height);publicvoidsetWidth(doublewidth)super.setHeight(width);super.setWidth(width);,假如系统中存在以下业务逻辑代码:voidgetArea(Rectanglerect)rect.setWidth(6);rect.setHeight(4);System.out.println(rect.getWidth()*rect.getHeight();则使用Rectangle的子类Square,在调用上述既有业务逻辑时:Rectanglesquare=newSquare();getArea(square);给出不正确的结果。,LSP设计原则提示:符合LSP设计原则的类的扩展不会给已有的系统引入新的错误。如果一个继承类的对象可能会在基类出现地方出现运行错误,则该子类不应该从该基类继承,或者说,应该重新设计它们之间的关系。上述实现中,Square不应从Rectangle继承,而应为独立的类。,接口分隔原则InterfaceSegregationPrinciple(ISP),不能强迫用户去依赖那些他们不使用的接口。包含了两方面的含义:接口设计应该遵循最小接口原则,不要把用户不使用的方法塞进同一个接口里。如果一个接口的方法没有被使用到,则意味着应将其分割成几个功能专一的接口。接口继承也应该遵循上述原则:继承的接口方法如未使用,则说明存在因继承不当导致的接口污染,应重新设计它们的关系。Java实现的方式:Adapter模式:将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。当接口存在不需要的方法时,先建立一个适配器,将其转换成满足客户端需要的新类,继承并实现需要的那部分接口即可!,publicinterfaceMouseListenerextendsEventListenerpublicvoidmouseClicked(MouseEvente);publicvoidmousePressed(MouseEvente);publicvoidmouseReleased(MouseEvente);publicvoidmouseEntered(MouseEvente);publicvoidmouseExited(MouseEvente);publicinterfaceMouseWheelListenerextendsEventListenerpublicvoidmouseWheelMoved(MouseWheelEvente);publicinterfaceMouseMotionListenerextendsEventListenerpublicvoidmouseDragged(MouseEvente);publicvoidmouseMoved(MouseEvente);,举例-接口分隔原则,publicabstractclassMouseAdapterimp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论