




已阅读5页,还剩98页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Java程序设计 第8章类与对象 Motivations Afterlearningtheprecedingchapters youarecapableofsolvingmanyprogrammingproblemsusingselections loops methods andarrays However theseJavafeaturesarenotsufficientfordevelopinggraphicaluserinterfacesandlargescalesoftwaresystems Supposeyouwanttodevelopagraphicaluserinterfaceasshownbelow Howdoyouprogramit 对象以现实世界中的一个对象为例 如某个人 可以说人具有许多属性 或状态 如姓名 身份证号 性别 身高和体重 人还具有各种行为 如说话 走路 思维和吃饭 在OOP的世界里 对象也具有许多属性和行为 使用面向对象的技术 就可以以某个人建立一个模型 类的定义 人 姓名 name 身份证号 id 性别 sex 身高 height 体重 weight 说话走路思维吃饭 状态描述表明了对象的状态特征 方法描述确定了对象具有的能力 类的定义 类被称为模板或者蓝本 对象就是由这些模板或者蓝本产生的 属于某个类的特性和行为总称为该类的成员 以上面提到的人为例 人的特性 包括姓名 身份证号 性别 身高和体重称为类的属性 用变量表示 而人的行为如如说话 走路 思维和吃饭称为类的方法 用函数表示 类的定义 变量 数据成员或成员变量 类 方法 成员方法或成员函数 类的定义 Java中类定义的一般格式为 修饰符class类名 extends父类名 类型成员变量1 类型成员变量2 修饰符返回值类型成员方法1 参数列表 类型局部变量 方法体 修饰符返回值类型成员方法2 参数列表 类型局部变量 方法体 类的定义 定义中的各元素的具体含义是 class是关键字 类定义的开始 类似于type 类型 的含义 class前的修饰符可以有多个 用来说明并限定类的使用方式 类名是用户为该类所起的名字 要遵从标识符的语法要求 extends是关键字 如果所定义的类是从某一个父类派生而来 那么 父类的名字应写在extends之后 Java中只允许单重继承 即父类只能有一个 类定义中的数据成员变量可以含有多个 成员变量前面的类型是该变量的类型 可以是任意的类型 类中定义的成员方法也可以有多个 方法体中定义的局部变量 只在该方法内有效 类的定义示例 类的定义示例 Objective Demonstratecreatingobjects accessingdata andusingmethods TestCircle1 Run 类的定义示例 Objective Demonstratecreatingobjects accessingdata andusingmethods TestTV Run TV 访问权限修饰符 访问权限修饰符有public private protected 它们既可以用来修饰类 也可以用来修饰类中的成分 包括数据成员及成员方法 此外 还有一个修饰符是friendly 这个修饰符也称为包访问权限 是默认修饰符 如果一个成分前面没有使用任何修饰符的话 隐含地认为使用的是friendly 使用包访问权限限定的成份可以在同一个包内使用 但对于包外的成员 这个成份是不可见的 也就是不能被包外的成员使用 访问权限修饰符 使用public修饰的元素是公有的 意味着它可以被程序中的任何对象在程序的任何位置来访问 这是最不受限制的权限 使用private修饰元素时 表明被修饰元素的使用权限最窄 这样的成分称为私有的 定义为私有的方法或是数据成员 只能被本类的实例对象所访问 其他任何类都无法访问 由此体现数据隐藏的特点 如果想让其他人共享的成员 应该使用其他权限的修饰符 访问权限修饰符 例8 3类的私有成员变量示例publicclassDate privateintday privateintmonth privateintyear classDateUser Date类外publicstaticvoidmain Stringargs Datemydate newDate mydate day 21 直接访问 错误 在类外不能直接访问Date的三个私有成员变量 取值或赋值的操作只能通过调用Date类的成员方法来完成 访问权限修饰符 对象的创建 java中的对象有基本数据类型的对象和类对象两种 对应的创建过程也有两种方式 对于类类型 需要先说明类的变量 也就是定义这个类型的变量 然后再创建对象 这两步缺一不可 类类型变量名 变量名 new类类型 参数列表 如果还没有说明变量 也可以将变量的说明与对象的创建合起来完成 格式如下 类类型变量名 new类类型 参数列表 对象的创建 对象创建语句中的new是Java用来分配内存的关键字 它表明到这一步系统才真正为对象分配内存 如 Circleyourcircle newCircle 当使用new创建对象时 系统按类模板的定义为对象分配内存 同时将该内存块的首地址放到刚才定义的那个引用中 此时引用才真正指向了内存中已创建的这个对象 当仅说明类变量时 因为还没有创建对象 也就没有分配相应的内存 此时引用中保存一个特殊的值null 表明它现在不指向任何地方 显式初始化 对象创建后还不能立即使用 因为它的数据成员还没有初值 也就是对象所占的内存中的量还不确定 强行使用的话没有任何意义 为安全起见 系统要求对对象必须先赋初值然后才能使用 例8 4显式初始化示例publicclassInitDemo privateintx1 25 privatefloaty2 6 6f privateStringname3 ZhangNan 显式初始化 也可以在说明一个类类型的引用后 使用点运算符 给它们赋初值 相应的语句格式是 对象引用 成员数据 初值如给前面定义的Date类型的引用赋初值 mybirthday day 26 mybirthday month 11 yourbirthday year 2009 构造方法 说明类对象之后 调用new运算符为对象分配空间 这个过程中系统到底是如何操作的呢 实际上此时系统调用了一个函数 这个函数是类的构造方法 这是一类非常特殊的方法 不同于类中定义的其他方法 构造方法 constructor 也称为构造函数 是与类名同名的一个或多个方法 当构造一个对象时 系统的处理步骤如下 1 为对象分配空间 并进行默认的初始化 在Java中 这两步是不可分的 从而可确保对象都有初值 2 执行显式的成员初始化 3 执行构造方法 构造方法及其重载 构造方法是一类特殊的方法 其名字与类名相同 并且没有返回值 构造方法只由系统来调用 在使用new创建对象的时候 就是系统调用构造方法的时刻 每个类都有构造方法 而且允许有多个 也就是构造方法可以重载 如果程序员没有编写构造方法 系统会自动补充一个默认的构造方法 如果有重载的构造方法 创建对象时 系统会根据程序员给出的初值个数及类型选择调用合适的一个构造方法 数据成员赋初值示例 例8 5给数据成员赋初值publicclassMyClass1 成员变量intxVar publicMyClass1 参数列表为空的构造方法xVar 0 程序指定初值 publicMyClass1 inti 带一个参数的构造方法xVar i 参数做为初值 例8 5 定义了类MyClass1 类中有两个参数列表不同的构造方法 因为它们接受对象初始值的方式不同 所以在方法体内的处理也不同 创建MyClass1的实例时 可以使用两种形式 MyClass1myclass1 newMyClass1 不带参数MyClass1myclass2 newMyClass1 15 带一个参数 构造方法定义示例 例8 6构造方法的定义publicclassDate privateintday privateintmonth privateintyear Date intd intm inty day d month m year y 类定义中惟一的一个构造方法带有三个参数 分别对应类中的三个成员变量 创建对象时需要给出三个初值 这三个值就是初始化成员变量时所赋的初值 创建对象时的语句可以这样写 DatedateFirst newDate 26 11 2009 还可以再创建另一个对象 DatedateSecond newDate 01 10 1949 参数类型的提升示例 虽然有重载构造方法的存在 在创建对象时 根据实参的个数与类型 系统还是有可能找不到参数列表完全一致的构造方法 此时系统会将实参的类型按赋值兼容的原则提升 再与构造方法的参数列表进行匹配 看下面的例子 例8 7参数类型的提升publicclassConsDemo doublexVar intyVar ConsDemo doubledpara intypara xVar dpara yVar ypara 参数类型的提升示例 上例中只定义了一个构造方法 下面两行语句都可以正确创建对象 ConsDemocd1 newConsDemo 6 6 5 ConsDemocd2 newConsDemo 6 6f 5 创建cd1时 系统很容易将实参与构造方法的参数列表匹配成功 对象创建成功 创建cd2时 所带的第一个参数是浮点型 系统找不到对应的构造方法 因此把这个参数进行类型提升 变为双精度型 然后也正确调用类中定义的构造方法 默认的构造方法 每个类都必须有构造方法 如果程序员在类中没有定义 系统会自动生成一个默认的构造方法 这个默认构造方法的参数列表是空的 方法体也是空的 它的作用只是要创建一个 基本对象 因为要在构造方法中给数据成员提供初值 而默认构造方法显然不能完成这些 Java规定 凡是使用默认构造方法生成的对象 成员变量按默认值来设置初值 即数值类型的量设为零 其他类型的量设为null 默认的构造方法示例 程序8 8类中不定义构造方法 类BankAccount中没有定义任何的构造方法 classBankAccount StringownerName 账户名intaccountNumber 账号floatbalance 余额 publicclassBankTester publicstaticvoidmain Stringargs BankAccountmyAccount newBankAccount 使用默认的构造方法System out println ownerName myAccount ownerName System out println accountNumber myAccount accountNumber System out println balance myAccount balance 修改属性值示例 例8 8修改属性值BankAccountmyAnotherAccount myAnotherAccount newBankAccount 创建对象myAnotherAccount ownerName Wangli 修改属性值myAnotherAccount accountNumber 1000234 myAnotherAccount balance 2000 00f System out println ownerName myAnotherAccount ownerName 输出属性值System out println accountNumber myAnotherAccount accountNumber System out println balance myAnotherAccount balance 添加这几行语句后 再输出的结果如下 ownerName WangliaccountNumber 1000234balance 2000 0 二维平面坐标系下点的定义示例 现在定义二维坐标系下的点myPoint类 由几何原理可知 空间坐标系下的点使用坐标来表示 平面中的点包含两个坐标值 三维坐标系中的点包含三个坐标值 例8 9二维平面坐标系下点的定义classmyPoint intx y 横 纵坐标myPoint intx1 inty1 x x1 y y1 myPoint x 0 y 0 使用预设的坐标值 voidsetPoint intx1 inty1 x x1 y y1 使用参数作为坐标值 类myPoint中两个成员变量x y分别表示点的横 纵坐标 类中定义了两个构造方法 和一个赋值函数 赋值函数使用实参确定一个点 基本类型的参数 程序8 10整型量做实参publicclassParameterTest publicstaticvoidmain Stringargs intpara 300 ParameterTestpT newParameterTest 创建对象System out println BeforeanotherMethod para para pT anotherMethod para System out println AfteranotherMethod para para EndofmainpublicvoidanotherMethod intk k 100 System out println InanotherMethod k k EndofanotherMethod 基本类型的参数 程序8 10的输出如下 BeforeanotherMethod para 300InanotherMethod k 400AfteranotherMethod para 300 对象作为参数 程序8 11对象做实参classValHold publicintk 10 publicclassObjectParameter publicstaticvoidmain Stringargs ObjectParameterObjectPara newObjectParameter 创建对象ValHoldvOBJ newValHold 使用默认的构造方法创建对象vOBJ k 20 改新值System out println BeforeanotherMethod vOBJ k vOBJ k ObjectPara anotherMethod vOBJ System out println AfteranotherMethod vOBJ k vOBJ k publicvoidanotherMethod ValHoldv v k 30 System out println InanotherMethod v k v k EndofanotherMethod 对象作为参数 程序的输出如下 BeforeanotherMethod vOBJ k 20InanotherMethod v k 30AfteranotherMethod vOBJ k 30 TheRandomClass YouhaveusedMath random toobtainarandomdoublevaluebetween0 0and1 0 excluding1 0 Amoreusefulrandomnumbergeneratorisprovidedinthejava util Randomclass TheRandomClassExample IftwoRandomobjectshavethesameseed theywillgenerateidenticalsequencesofnumbers Forexample thefollowingcodecreatestwoRandomobjectswiththesameseed3 Randomrandom1 newRandom 3 System out print Fromrandom1 for inti 0 i 10 i System out print random1 nextInt 1000 Randomrandom2 newRandom 3 System out print nFromrandom2 for inti 0 i 10 i System out print random2 nextInt 1000 Fromrandom1 734660210581128202549564459961Fromrandom2 734660210581128202549564459961 DisplayingGUIComponents Whenyoudevelopprogramstocreategraphicaluserinterfaces youwilluseJavaclassessuchasJFrame JButton JRadioButton JComboBox andJListtocreateframes buttons radiobuttons comboboxes lists andsoon HereisanexamplethatcreatestwowindowsusingtheJFrameclass TestFrame Run 类的继承 在已有类的基础上 保留想要的属性及方法 去掉或是修改要变化的属性及方法 这样就得到一个新的类 原来的类称为父类或超类 新类称为子类 可以将子类看作是来源于父类的类 这就是类的继承机制 子类继承于父类 父类派生了子类 子类还可以再派生它的子类 形成一个单向的关系 处于上层的类是父类 它是更一般化的 与之相对的 条件更强的类是子类 它的表现更特殊一些 父类的特性可以适用于子类上 如家用电器都需要用电来驱动 电视当然也需要用电驱动 子类还可以具有各自特殊的特征 一个子类的属性可能不属于另一个子类 如电视不具备电冰箱的制冷属性 客观世界中 特殊类对象共享更一般类对象的状态及行为 称为子类继承父类的特性 语言中 子类可以继承父类的属性和方法 还可以增加自己特有的属性和方法 类的继承 Java语言中定义类继承关系时使用关键字extends 定义子类的格式如下 publicclass子类名extends父类名 类中的相关定义 定义中 子类名和父类名都必须是合法的标识符 如果在类的定义中没有出现extends关键字 则表明它派生于Object类 这个类是Java中预定义的所有类的父类 它处在类目录中的最高层 不论一个类有没有明确指定父类 都可以看作是从Object类直接或间接派生来的 Object类包含了所有Java类的公共属性 这个类中定义的方法可以被任何类的对象使用或继承 Object类中的主要方法 单重继承 子类的父类可以有几个呢 Java中规定 父类只能有一个 这是Java独特于其他面向对象语言的地方 这称为单重继承 当子类有多于一个的父类时称为多重继承 多重继承在处理方法重载时有它自身先天的二义性 为了避免这种歧义的情况出现 Java规定当子类继承父类时 只能有一个父类 这样如果子类需要使用父类中的方法 因为父类的惟一性 避免了歧义的产生 单重继承的类关系结构如同一个树状结构 单重继承 一个子类可以从父类中继承成员变量和成员方法 而这个父类也有可能再从它的父类中继承属性 这种继承关系具有传递性 即一个对象可以继承其所有的祖先类 在树中通往Object的路径上的所有类 中的成员变量和方法 访问父类成员变量 例对父类中成员变量的访问示例classsuperClass publicintaOK 10 公有的 可以访问privateintbNOK 20 私有的 不能访问protectedintcOK 30 保护的 可以访问publicintgetB 公有方法 可以调用return0 publicclasssubClassextendssuperClass publicintdOK publicstaticvoidmain Stringargs subClasssC newsubClass System out println sC aOK 允许System out println sC bNOK 不允许 因为bNOK是私有的System out println sC getB 允许调用System out println sC cOK 允许System out println sC dOK 允许 访问父类成员变量 子类的方法中可以调用父类中的方法 当然也可以修改它们 也就是在子类中定义一个与父类有相同名字和相同参数列表的方法 但两个方法的代码不完全相同 这种机制称作方法的重写 多态性与转换对象 赋值语句执行的功能是将表达式计算结果赋给同类型的变量 这同样适用于类类型 程序中可以将一个实例赋给赋值号左侧类的引用 赋值号左侧的引用和右侧的实例同属一个类时 赋值过程类似于基本类型的赋值语句 一个类变量指向其子类对象时称为转换对象 casting 从语法上看 允许将子类的实例赋给父类的引用 这称为赋值兼容 Java是强类型语言 它对变量类型的检查非常严格 同时也提供了一些赋值兼容原则 赋值兼容规定 在继承树中允许向上赋值但不允许向下赋值 就是说 子类的实例不只允许赋值给同类的变量 还允许赋值给其祖先类的变量 包括父类变量 或者说 类的变量允许指向本类的实例 也可以指向其子类或后代类的实例 但反过来是不允许的 即类的变量不能指向祖先类的实例 示例 我们将图中说明的类具体化 定义雇员类和经理类 同时 根据职员的类别打印相应的信息 示例 例8 12类的定义publicclassEmployee privateStringname 姓名privateDatehireDate 入司时间privateDatedateOfBirth 生日privateStringjobTitle 职位privateintgrade 级别privateintseNumber 工号 成员方法的定义 publicclassManagerextendsEmployee 子类privateStringdepartment 部门privateEmployee subordinates 团队员工 成员方法也继承于父类 经理Manager当然属于雇员Employee 所以这两个类定义为父子关系 一个Manager类的对象也是Employee类的对象 它继承了Employee类所有可继承的属性 包括成员变量和成员方法 示例 下面定义方法myMessageBox 上例续publicvoidmyMessageBox Employeee if einstanceofManager 使用instanceof判明是子类的实例 经理级人士相关的程序代码Managerm Manager e 转换对象System out println Manager System out println Thisisthemanagerof m department elseif einstanceofContractor 承包人相关的程序代码Contractorc Contractor e 转换对象System out println Contractor System out println Thisisthecontractorof c department else 普通雇员相关的程序代码System out println Employee 程序中 使用对象转换是必要的 如果没有进行转换 当调用e department时 因为编译器知道在Employee中没有department成员 所以会出现错误 实参中的对象转换示例 例8 13实参中的对象转换publicTaxRatefindTaxRate Employeee 进行计算并返回e的税率 而在应用程序类中可以写下面的语句Managerm newManager TaxRatet findTaxRate m findTaxRate 方法的参数必须是Employee类型的 而调用时的实参是Manager类型的 Manager类是Employee类的子类 所以Manager的实例也是Employee的一员 可以将方法的实参替换为更 一般 的变量类型 所以最后一行的方法调用是正确的 转换对象引用原则 转换对象引用时有以下的原则 沿类层次向 上 转换总是合法的 例如 把Manager引用转换为Employee引用 此种方式下不需要转换运算符 只用简单的赋值语句就可完成 对于向 下 转换 只能是父类到子类转换 其他类之间是不允许的 例如 把Manager引用转换为Contractor引用肯定是非法的 因为Contractor不是Manager 这两个类之间没有继承关系 赋值号右侧的类必须是赋值号左侧引用类型的某个子类 对象转换是在编译后正式运行时进行的 编译时不会检查 程序中需要使用instanceof来判别对象的实际类型 保证程序的正确性 关键字static 使用static可用来描述变量及方法 所描述的变量称为静态变量 或类变量 所描述的方法称为类方法 类变量和类方法统称为类成员 系统在类定义时即为类成员分配内存 而不是创建实例时才分配 下图表示了这种类成员的共享形式 静态数据成员示例 例8 14静态数据成员示例publicclassCount privateintserialNumber 定义一个私有变量privatestaticintcounter 0 定义一个私有静态变量publicCount counter 对静态变量的操作serialNumber counter 类Count中定义了私有成员serialNumber 它表示的是每个类对象自己独特的序列号 这个号码应该是惟一的 因此用一个静态变量counter负责记数 当创建一个对象时 counter的值加1 保证号码的惟一性及有序性 然后把这个号赋给每个对象的serialNumber Count类的所有对象共享counter的值 就是说从每个对象中看到的counter值都是一样的 访问静态成员示例 例8 15访问静态成员示例classStaticVar publicstaticintnumber 相当于全局变量 publicclassOtherClass publicvoidmethod intx StaticVar number 类名 静态变量名 类StaticVar中定义了公有静态变量number 在程序的整个作用域内都可访问它 并且它的值对所有对象都是一样的 所以它的作用相当于全局变量 在method 方法内只通过类名就可以访问它 类方法使用示例 例8 16类方法使用示例classstaticTestFunction publicstaticintaddUp intx inty 这个方法是类方法returnx y publicintsub intx inty returnaddUp x y 类内调用静态方法 直接调用 publicintanothersub intx inty returnsub x y 类内调用非静态方法 直接调用 类方法使用示例 publicclassUseGeneral publicstaticvoidmain Stringargs inta 9 intb 10 intc staticTestFunction addUp a b 类外调用静态方法 使用类名调用staticTestFunctionsTF newstaticTestFunction intd sTF anothersub a b 类外调用非静态方法 使用实例名调用System out println addUp gives c System out println sub gives d 例8 16中共使用了四种方式来调用方法 当在类内调用方法时 不论被调用的方法是静态的或是非静态的 都可以直接调用 类方法中使用变量的限制示例 例8 17在类方法中使用变量的限制示例publicclassWrong intxVar 方法外定义的非静态成员staticintyVar 方法外定义的静态成员publicstaticvoidmain Stringargs xVar 9 方法内不能使用yVar 9 方法内可以使用 由于类方法可以在没有定义任何实例的情况下加以调用 故不存在this值 因此一个类方法只能使用其内部定义的参数或静态变量 如果企图使用非静态变量将引起编译错误 不能重写 覆盖 静态方法 例8 18不能重写静态方法ClassSuperClass staticvoidnoOverload ClassSubClass voidnoOverload 重写父类中的同名方法 错误 静态方法不能被重写 也就是说 在这个类的子类中 不能有相同名称 相同参数的方法 例5 18由于试图重写父类中的静态方法 因此会引起编译错误 关键字final 对于不需要再派生子类的类 可以使用关键字final来修饰它 这样的类称为终极类 用final修饰的类已到达类层次中的最低层 类的成员也可以用这个关键字来修饰 分别称为终极方法及终极变量 终极的含义是 这样定义的元素不能再被改变 如果是类 则表明终极类不能再被继承 如果是终极变量 表示它的值不能再被改变 也即终极变量等同于一个常量 如果是终极方法 意味着它不能再被改写 声明终极类的格式为 finalclass终极类名字 终极类示例 如果试图派生终极类的子类 将导致错误 见下面的例子 例8 19不能从终极类派生finalpublicclassFinalClass 这是一个终极类intmemberar voidmemberMethod classSubFinalClassextendsFinalClass 从终极类派生 错误intsubmembervar voidsubMemberMethod 例8 19中定义的SubFinalClass类要从终极类FinalClass派生 这会导致编译错误 将这个例子修改如下 终极类示例 例5 20不能从终极类派生publicclassFinalClass 这不再是一个终极类intmemberar voidmemberMethod classSubFinalClassextendsFinalClass 可以派生 正确intsubmembervar voidsubMemberMethod 终极类中方法的使用 在类外可以调用终极类中定义的方法 这和调用非终极类中的方法是一样的 看下面的例子 例8 21终极类中方法的使用finalclassBase 定义终极类publicvoidamethod System out println amethod publicclassFin publicstaticvoidmain Stringargs Baseb newBase b amethod 调用终极类中的方法 终极方法 类中的方法也可以定义为终极的 如果一个方法不想被改变 则可以使用final关键字来定义 这样就可以保证它们在使用中不被改变 终极方法的定义格式为 final返回值类型终级方法名 参数列表 因为终极类不能有子类 所以从逻辑上可以保证不会有重写终极类中方法的可能性 即被声明为final的方法只能被调用 不能被重写 为此 Java规定 如果一个类被定义为终极类 则其中的方法自动成为终极方法 除了类及方法可以是终极之外 变量也可以定义为终极的 终极变量使用final来修饰 它的值在程序中不能被修改 所以终级变量等同于一个常量 终极变量的值必须在定义它的时候给出 在程序中不能再被改变 试图改变终极变量的值将引起编译错误 修改终极引用变量 如果将一个引用类型的变量标记为final 那么这个变量将不能再指向其他对象 但它所指对象的值仍然是可以改变的 看例5 22 例8 22修改终极引用变量classCar intnumber 1234 classFinalVariable publicstaticvoidmain Stringargs finalCarmycar newCar 终极变量mycar number 8888 可以被改变 mycar newCar 不能再指向其他实例 错误 在这里 改变变量mycar的成员变量number的值是可以的 但如果试图用mycar指向其他对象就会引起错误 关键字abstract 用abstract可以修饰类或成员方法 表明被修饰的成分是抽象的 被abstract关键字修饰的类称为抽象类 被abstract关键字修饰的方法称为抽象方法 在类中定义抽象方法时 只需要给出方法的原型说明 包括方法名 方法的返回值类型 方法的参数列表 而方法体是空的 甚至不需要表示块的那对大括号 含有抽象方法的类必须说明为抽象类 和终极类不能派生子类相反 抽象类一定要派生子类 所以在类的派生关系树中 抽象类一定是树中的分支结点 当由抽象类派生子类后 父类中的抽象方法可以在子类中实现 也可以在子类中继续说明为抽象的 然后在更下一层的子类中实现 当父类中有多个抽象方法时 子类可以仅实现父类中的部分抽象方法 也就是允许子类继承父类中的抽象方法 当子类中含有抽象方法时 这样的子类还必须定义为抽象类 仍需要在它的子类中实现抽象方法 直到所有的抽象方法都实现时 这样的类才可以创建实例 也才可以实际使用 抽象类定义 一个类中可以同时定义抽象方法和非抽象方法 不论非抽象方法的个数有多少 只要有一个抽象方法 这个类就必须说明为抽象类 抽象的类或方法使用关键字abstract修饰 抽象类的定义格式如下 publicabstractclass类名 定义体 为使此类有用 它必须有子类抽象方法的定义格式如下 publicabstract返回值类型方法名 参数列表 使用abstract定义的抽象方法没有方法体 具体的代码只能在子类中写出 构造方法不能说明为抽象的 这是因为构造方法是不能被继承的 它在子类中也不能被具体实现 因为一个抽象类必须被继承 而终极类是不能被继承的 所以不能把一个类既声明为abstract 又声明为final的 这两个修饰关键字一定不能同时出现 抽象类及抽象方法示例 例8 23抽象类及抽象方法的定义publicabstractclassDrawing publicabstractvoiddrawDot intx inty publicvoiddrawLine intx1 inty1 intx2 inty2 重复使用drawDot 方法 通过连续画点的方式画出线段 抽象类 一个抽象类中可以包含非抽象方法和成员变量 概括地说 包含抽象方法的类一定是抽象类 但抽象类中的方法不一定都是抽象方法 一个抽象类是不能创建对象的 除非通过间接的方法来创建其子类的对象 但是可以定义一个抽象类的引用变量 也就是说 程序中形如newObjectStorage 的表示是错误的 但是下述表示 ObjectStorageobst newStack 则是可以的 关键字this和super 这两个关键字都用来指代类 this指代本类 super指代父类 在类的成员方法中可以使用它们 实际上在前面的示例中 我们已经使用了这两个关键字 在子类的方法中 如果需要先调用父类的方法 就可以使用super来指代父类 例8 24this的使用publicclassDate privateintday month year publicvoidprintDate System out println Thecurrentdateis dd mm yy this day this month this year 类Date中定义了分别表示年月日的三个量 当要访问当前对象的三个成员变量day month和year时 使用this来指向它们 关键字this和super 实际上 在类方法中Java自动用this关键字把所有变量和方法引用结合在一起 所以例子中的this可以完全省略不写 例5 26可以改写如下 例8 25省略thispublicclassDate privateintday month year publicvoidprintDate System out println Thecurrentdateis dd mm yy day month year 如果对象实例作为方法的自变量来使用时 则this是不能省略的 当在完全独立的类中调用一个方法 并把对象实例作为一个自变量来传送时 要用this指明对哪个对象实例进行操作 有些情况下关键字this是必需的 例如 BirthdaybDay newBirthday this 构造方法的重载 定义重载的构造函数时 经常使用this和super这两个关键字 以省略构造函数中重复的代码段 代码的可重用性提高 程序也更加简捷 看下面的例子 例8 25定义了三个构造方法 分别带有不同的参数列表 对于没有实参的成员变量使用相同的预设值作为初值 构造方法的重载 例8 26构造方法的重载publicclassStudent Stringname intage publicStudent StringsVar intnVar name sVar age nVar publicStudent StringsVar name sVar age 20 publicStudent name Unknown age 20 构造方法的重载 我们可以使用this来简化代码 将例子8 26改写如下 例8 27改写例8 26publicclassStudent Stringname intage publicStudent StringsVar intnVar name sVar age nVar publicStudent StringsVar this sVar 20 publicStudent this Unknown 构造方法的重载 这里 使用关键字this来指代本类中的其他构造方法 第一个构造方法使用两个实参作为初值 第二个构造方法只有一个字符串初值 第三个则没有任何的实参 super使用的示例 例8 30super的使用示例classSuperClass 父类voidshowMyPosition 父类中的方法System out println Iaminsuperclass System out println Iwillgobacknow classSubClassextendsSuperClass 子类voidshowMyPosition 重写的子类中的同名方法System out println AtfirstIwillgotosuperclass super showMyPosition 调用父类的同名方法System out println NowIhavemovedtosubclass super使用的示例 publicclassSuperTest publicstaticvoidmain Stringargs SubClassson newSubClass 子类实例son showMyPosition 调用方法 程序中 super showMyPosition 将调用父类中的showMyPosition 方法 方法重写 方法重载 overloaded 和方法重写 overridded 是两个相近的概念 非常容易混淆 重载是指在一个类中 存在多个同名方法 例如前面介绍过的构造方法的重载 有了重载 就可以让一个名字具有多种意思或用途 意味着操作的多样性 这种机制允许程序员用相同的名字来完成不同的功能 而且这种灵活是在运行时决定的 并不是在编译时决定 重写是指在子类中对父类或祖先类中方法的全面取代 如果父类中定义的方法不适合子类的要求 则在子类中可以重新写一个同名的方法 当然参数列表也要与父类中的一致 这样的机制 保证在子类中不再看到父类中的同名方法了 达到了修改的目的 这也是多态性的一个表现 方法重写 使用类的继承关系 则子类可以具有父类定义的所有可继承的方法 如果父类中定义的方法不能满足子类中的特性 则可以在子类中修改这个方法 这称为方法的重写 也称为方法的隐藏 我们知道方法重载是多态性的一种表现 方法重写也是多态性的表现 方法重载是在同一类中定义多个同名但具有不同参数列表的方法 而方法重写是在父类与子类之间的一种多态表现 允许父 子类中有同名 同参数列表的方法 它们的代码可能不完全相同 处理的细节也允许有差异 重写方法后可以让方法具有多种形式 虽然方法的参数列表及返回类型完全相同 但方法具体实现的功能可以改变 新的方法可以修改原方法中不适用的地方 也可以扩展新的功能 这样就可以满足父类与子类的不同需求 程序也更具有灵活性 重写方法示例 publicclassEmployee Stringname intsalary publicStringgetDetails return Name name n Salary salary publicclassManagerextendsEmployee Stringdepartment publicStringgetDetails return Name name n Managerof department 应用重写的规则 方法重写是面向对象程序设计中非常重要的手段 几乎所有可用的程序都离不开方法重写 这包括我们重写系统提供的类库中的方法 或是重写其他人提供的方法 应用重写时必须注意以下两条重要规则 1 重写方法的允许访问范围不能小于原方法 2 重写方法所抛出的异常不能比原方法更多 以上两条规则均源于多态性和Java所具有的 类型安全性 的要求 调用父类构造方法 虽然一个子类可以从父类继承所有可继承的方法和成员变量 但不能继承父类的构造方法 任何一个类都不能继承父类的任何构造方法 因为构造方法的特殊性 一个类能够具有构造方法的途径只有两种 一是程序员自己编写 另一个是系统提供默认的版本 程序员编写的构造方法可以重载 当不提供任何自定义的构造方法时 系统自动提供默认的构造方法 默认的构造方法不会重载 也不带任何的参数 虽然子类不能继承父类的构造方法 但在子类的构造方法中 可以调用父类的构造方法 使用super关键字就可以了 这也是值得推荐的一种良好的程序设计风格 调用父类的构造方法 例8 34调用父类的构造方法classEmployee Stringname publicEmployee StringsVar 父类的构造方法name sVar classManagerextendsEmployee 子类Stringdepartment publicManager StringsVar StringdVar super sVar 调用父类的构造方法 处在第一行department dVar 调用父类的构造方法 一般来讲 调用super 时参数的个数没有限制 只要其参数个数及类型和父类中的某个构造方法的参数个数及类型相符即可 在通常情况下 没有参数的默认构造方法常被用于初始化父类对象 当然 对于父类的不同构造方法可视情况进行选择 如果super 调用不是放在构
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 46075.5-2025电子束焊机验收检验第5部分:跳动精度的测量
- 2024-2025学年度中医助理医师模拟试题及答案详解【全优】
- 应急安全培训及演练总结课件
- 2025水利设施管养人员模拟试题及答案详解(历年真题)
- 2024平凉市公务员行测及参考答案详解(满分必刷)
- 新生儿呼吸道合胞病毒-RSV-感染诊疗与预防
- 迁移路灯合同(标准版)
- 2024年冶金工业技能鉴定过关检测试卷带答案详解(A卷)
- 2024-2025学年测绘职业技能鉴定考试综合练习带答案详解(夺分金卷)
- 2025年工业互联网平台入侵检测系统在智慧城市中的应用与优化报告
- 贵金属废料提炼合同协议
- 中国传统木工工艺课件
- 有限空间作业培训内容
- 淋巴瘤PET-CT及PET-MR显像临床应用指南(2025版)解读课件
- 模具部的组建和管理
- 《中国近现代史纲要》课程教学大纲
- 康复专转本试题及答案
- 2025基于人工智能的智慧公路应用技术研究报告
- 【艾青诗选】22《雪落在中国的土地上》思维导图+批注
- 精神科护理学见习
- 版高空作业培训内容
评论
0/150
提交评论