JAVA程序员培训-4讲师:朱晓第三章类和对象本章目标理解对象理解类理解对象与类之间的关系掌握包的创建和导入类类以共同特性和操作定义实体类是用于组合各个对象所共有操作和属性的一种机制形状类动物类汽车类类的示例“类是具有相同属性和行为的一组对象的集合”类和对象的区别类是概念模型,定义对象的所有特性和所需的操作对象是真实的模型类和对象类定义实体对象是实际的实体类是对象的原型所有属于同一个类的对象都具有相同的特性和操作类的面向编程三大特性封装继承多态封装-private•信息隐藏,隐藏对象的实现细节,不让用户看到•将东西包装在一起,然后以新的完整形式呈现出来–例如,两种或多种化学药品组成一个胶囊–将方法和属性一起包装到一个单元中,,单元以类的形式实现“隐藏属性、方法或实现细节的过程称为封装。”类和对象举例定义类publicclassAnimal{publicintlegs;publicvoideat(){System.out.println(eat);}}生成类的对象实例AnimalmyCat=newAnimal()Animal+legs:int+eat()声明类语法格式:[修饰符]class类名{[属性声明][构造器声明][方法声明]}类修饰符共2种:默认、public声明属性语法格式:[修饰符]类型属性名[=初值];例:publicintlegs;publicintage=20;属性修饰符共4种:public、propectdefualtprivate声明方法语法格式:修饰符返回类型方法名([参数表]){[语句]}例:publicvoideat(){System.out.println(eat);}练习编写一个计算器Computer类,实现两个方法:返回两个数的相加值和两个数的相减值编写一个TestComputer类,测试打印Computer类的两个方法的返回值是否正确对象成员的访问“点”符号:对象.成员成员包括属性,方法举例:Animalxb=newAnimal();xb.legs=4;xb.eat();xb.move();xb.setLegs(2);intnum=xb.getLegs();练习写一个Cat类,定义属性weight(重量),定义方法showWeight能够返回weight的值。写一个测试类TestCat,设置weight属性值为10,调用showWeight方法输出属性值Cat+weight:int+showWeight():int在方法中调用其他方法publicclassTestCallMethod{publicvoidm1(){System.out.println(m+m2());System.out.println(m1);}publicintm2(){return2;}publicstaticvoidmain(Stringargs[]){TestCallMethodtcm=newTestCallMethod();tcm.m1();}}此处产生断点,转到m2方法体信息的隐藏和封装问题用户代码直接访问内部数据(类定义的属性)会导致数据的错误、混乱和安全性差等问题解决将类属性的访问私有化(private),不允许用户代码直接访问用户只能通过公有方法(public)对属性进行存取信息的隐藏和封装实例publicclassAnimal{privateintlegs;//将属性legs定义为private,只能被该类的成员访问publicvoidsetLegs(inti){if(i!=0&&i!=2&&i!=4){System.out.println(Wrongnumberoflegs!);return;}legs=i;}publicintgetLegs(){returnlegs;}}publicclassZoo{publicstaticvoidmain(Stringargs[]){Animalxb=newAnimal();xb.setLegs(4);//xb.setLegs(-1000);xb.legs=-1000;//非法System.out.println(xb.getLegs());}}信息的隐藏和封装总结将类属性声明为私有(private),提供公有的(public)方法setXXX和getXXX对数据进行存取,实现下列目标:隐藏一个类的实现细节;使用者只能通过事先定制好的方法来访问数据,可以方便地加入控制逻辑,限制对属性的不合理操作;便于修改,增强代码的可维护性;练习1Cat-weight:int+setWeight(w:int)+getWeight():int编写Cat类,如右图,其中在setWeight方法中限制传入的参数必须是1~10之间包括1和10,否则打印错误信息编写TestCat类,测试Cat类的setWeight方法和getWeight方法练习2Birthday-year:int-month:int……+show()编写Birthday类,如右图,封装year和month属性,自己编写setXXX和getXXX方法,提供show方法可以打印生日格式(年/月)构造器语法格式:修饰符类名([参数表]){[语句]}例:publicclassCat{privateintweight;publicCat(){weight=5;}……}•每当创建给定类的实例时就调用的方法•与类同名,但没有返回类型•Java为对象分配内存,初始化实例变量并调用构造器•两种构造器–参数化构造器–隐式构造器参数化构造器的示例classSdate{intmonth;intday;intyear;Sdate(intm,intd,inty){month=m;day=d;year=y;System.out.println(“日期是+m+/+d+/+y+.);}publicstaticvoidmain(Stringargs[]){SdateS1,S2;S1=newSdate(11,27,1969);S2=newSdate(3,3,1973);}}参数化构造方法隐式构造器的示例classSdate{intmonth=11;intday=27;intyear=1969;publicstaticvoidmain(Stringargs[]){SdateS1;S1=newSdate();}}隐式构造方法示例的构造器演示:示例1publicstaticvoidmain(String[]args){BookobjBook=newBook(CoreJava,Albert,45,true);UserobjUser=newUser();objUser.getBookStatus(objBook);}Book(Stringbook,Stringauthor,intpages,booleanstatus){bookName=book;authorName=author;nopages=pages;available=status;}voidgetBookStatus(BookobjBook){objBook.isAvailable();}默认构造器在java中,每个类都必须有至少一个构造器如果类中没有显式的定义任何构造方法,系统会自动的提供一个默认构造方法默认构造器没有参数默认构造器方法体为空publicclassCat{privateintweight;publicCat(){//系统提供}……}Cat(inta,Stringb)与Cat(Stringa,intb)重载变量的作用域变量的作用域:局部变量的作用域:在所在的方法或语句块中在程序调用方法(进入语句块)时,局部变量才被创建并可用,随方法(语句块)的退出,局部变量将被销毁全局变量的作用域:成员变量(属于全局变量)依附于对象(局部变量)存在,具有与对象相同的生存期和作用域。变量作用域举例publicclassTest{privateinti=1;publicvoidmethod1(){inti=4,j=5;this.i=i+j;method2(7);}publicvoidmethod2(inti){intj=8;this.i=i+j;System.out.println(this.i);}publicstaticvoidmain(String[]args){Testt=newTest();t.method1();}}8745栈内存1堆jithisjithistimethod2method1maintest对象Java类的成员变量默认初始化创建对象时,类中的成员变量会被自动初始化然后赋予默认值•全局变量有默认值,局部没有publicclassTest{inti;booleant;publicstaticvoidmain(Stringargs[]){Testt=newTest();//创建对象时,类中的基本数据类型属性初始化为默认值System.out.println(t.i);//0System.out.println(t.t);//false}}Java类的成员变量默认初始化原则成员变量类型默认值byte0short0int0long0Lchar‘\u0000’float0.0Fdouble0.0Dbooleanfalse所有引用类型null引用类型除了基本数据类型之外的类型就是引用类型引用类型可以存储复杂的数据结构引用类型的数据以对象的形式存在例Catc1=newCat();//创建了一个引用变量c1,并用new创建了一个实例,其中c1指向这个实例Java引用类型应用举例publicclassMyDate{privateintday=12;privateintmonth=6;privateintyear=1900;publicMydate(intd,intm,inty){year=y;month=m;day=d;}publicvoiddisplay(){System.out.println(year+/+month+/+day);}publicstaticvoidmain(String[]args){MyDatem;m=newMyDate(22,9,2001);m.display();}}成员变量初始化顺序(默认显示赋值构造)范例程序流程解析图1MyDatem;m=newMyDate(22,9,2001);m.display();当前给MyDate引用类型的引用变量分配内存nullm栈堆范例程序流程解析图2MyDatem;m=newMyDate(22,9,2001);m.display();创建新对象,用默认值初始化属性值nullm栈堆000daymonthyear范例程序流程解析图3MyDatem;m=newMyDate(22,9,2001);m.display();在属性声明中进行了显式赋值nullm栈堆1261900daymonthyear范例程序流程解析图4MyDatem;m=newMyDate(22,9,2001);m.display();在构造方法中进行了赋值nullm栈堆2292001daymonthyear范例程序流程解析图5MyDatem;m=newMyDate(22,9,2001);m.display();在引用变量m中存储了对象实例的地址0x3a478bm栈堆2292001daymonthyear0x3a478b范例程序流程解析图6MyDatem;m=newMyDate(22,9,2001);m.display();打印最后赋的值2001/9/220x3a478bm栈堆2292001daymonthyear0x3a478b引用的赋值图1MyDatem;m=newMyDate(22,9,2001);MyDatem1=m;//假如将m1赋了一个引用变量,结果两个引用变量指向了同一个实例0x3a478bm栈堆22