1、单元 05 面向对象基本概念单元目标 理解类和对象的概念以及两者之间的关系; 掌握类的结构和定义过程; 掌握对象的创建过程。 掌握类中方法的定义和使用; 掌握构造方法的定义和意义; 理解方法重载的思想; 掌握方法重载的实现方式和特征; 能够分辨出变量作用域的范围并正确使用变量 理解类的封装意义; 掌握类的封装实现步骤; 掌握各种访问修饰符的访问范围; 能够准确使用访问修饰符控制对象使用。学习任务 01任务描述人是这个社会的主体,在系统开发过程中经常涉及到人类。人的信息包括姓名、年龄、性别、体重、家庭地址等。要求使用 Java 语言对“人类”进行描述并进行实例化。运行结果知识准备5.1 类与对象
2、的概念与关系5.1.1 对象的概念对象对象(Object)是现实世界中实际存在的某个具体实体。一般对象是有形的,例如,电视机对象拥有着自己的样式、颜色、大小等等和放映、开关和设置等功描述“人类”信息程序设计描述“人类”信息程序设计能(行为) ;也可以是无形的,例如五子棋的输赢规则。对象包含特征和行为对象包含特征和行为,特征指对象的外观、性质、属性等;行为指对象具有的功能、动作等。而面向对象技术中的对象就是这些实际存在实体在程序实现中的映射和体现。5.1.2 类的基本概念人类在认识客观世界时习惯于把众多的事物进行归纳、划分和分类。把具有相同特征及相同行为的一组对象称为一类对象(Class of
3、Object) ,同时分类原则是抽象,那么面向对象技术中类是同种对象的集合与抽象类是同种对象的集合与抽象。例如,家用轿车、公交车、货车等都属于汽车的范畴,并且通过比较总结等抽象思维方式可以发现不同的车之间存在着共同特点。 因此为了能够方便的了解和描述这些实际存在的实体在面向对象技术中定义了类这个概念来类对所有对象提供统一的抽象描述,其内部包括属性和方法两个主要部分。在面向对象的编程语言中,类是一个独立的程序单位。5.1.3 类与对象的关系类表示一个有共同性质的对象群体,而对象指的是具体的实实在在的物体。类与对象的关系就如模具和铸件的关系,类是创建对象的模具,而对象则是由类这个模板制作出来的铸件
4、;同时类又是由一组具有共同特性的对象抽象得到的。对象与类的关系如图 5-1 所示。图 2-1 对象与类的关系【经验】认识类与对象的关系是面向对象程序设计思想的第一步。类是由对象抽象出来的,对象是由类实例化得到的,很多学员会产生疑问:到底是先有类还是先有对象?其实这是问题就像鸡和蛋的关系一样并没有最正确答案, 关键是看你自己理解类和对象关系时哪一种更能说服自己。这里我的经验是:先有类后有对象,定义类的最终目的是要使用这些类, 而使用类的最主要方式就是创建并操作类创建出来的对象。5.2 类的定义Java 是一种面向对象程序设计语言, 任何一个 Java 程序都是以类的形式存在,设计程序的过程首先就
5、需要从现实问题中找出可实现的类,并用 Java 语句进行定义。类是一个独立的单位,它有一个类名,其内部包括成员变量,用于描述属性;还包括类的成员方法,用于描述行为。因此,类也被认为是一种抽象数据类型,这种数据类型不但包括数据,还包括方法。5.2.1 类的格式类是通过关键字 class 来定义的, 在 class 关键字后面加上类的名称, 这样就创建了一个类。在类里面可以定义类的成员变量和方法。类的定义格式如下:修饰符修饰符class类名类名 /定义属性部分定义属性部分成员变量成员变量 1;成员变量成员变量 n;/定义方法部分定义方法部分方法方法 1;方法方法 n;注解:1. 修饰符修饰符。修饰
6、类的修饰符有 public、abstract 和 final,这些修饰符将在后面的任务中介绍。包含包含 main 方法的主类必须定义为方法的主类必须定义为 public。2. class 关键字关键字。class 为 Java 定义类的关键字,必须写在修饰符和类名中间,使用空格隔开,并且不能改变任何一个字符的大小写,如:Class 是错误的。3. 类名类名。类的名字要符合 Java 的命名规范,同时名字要有意义能够反映出这个类的内容,第一个字母一般为大写。【实例 2-1】用 Java 类的定义描述汽车。 【源代码】public class Car String color;/ 颜色int co
7、unt;/ 容纳人数String bound;/ 汽车品牌float weight; / 重量【注意】【注意】如果你有 C+编程经验请注意,类的声明和方法的实现要存储在同一个地方并且不能被单独定义。由于所有类的定义必须全部定义在一个单个的源文件中,这有时会生成很大的.java 文件。在 Java 中设计这个特征是因为从长远来说,在一个地方指明,定义以及实现将使代码更易于维护。5.2.2 类的成员变量和方法类的成员变量是用来描述属性信息的,因此大部分成员变量是以名词的形式出现,如姓名、颜色、大小等。类的成员变量一般是简单的数据类型,也可以使对象、数组等复杂数据类型。修饰符修饰符数据类型数据类型成
8、员变量名成员变量名=初值初值;例如:publicStringname = ”Jack”;intage = 10;成员变量的修饰符包括 public、private、protected、static 和 final,通过这些修饰符来保证成员变量的被访问范围以及创建的过程。例如:public 表示该成员变量可以被自己和其他类访问到, 而 static 表示为静态变量创建过程不需要实例化对象,具体在后面的单元中会详细讲解。类的方法又被称为成员方法(函数) ,用来描述动作、行为和功能,因此大部分方法是以动词形式出现,如:吃、学习、启动等。方法包括方法名、方法返回值、方法参数三个要素,以及修饰符和一段用
9、来完成某项动作或功能的方法体。具体在后面的单元中会详细讲解。描述“人类”信息程序设计5.3 创建对象5.3.1 创建对象的格式类是对象的模板,对象是由类实例化得到,这是创建对象的依据。类也是数据类型,可以使用这种类型来创建该种类型的对象,而 Java 提供的关键词为new。格式为:类名类名对象名对象名 = new类名类名 (参数参数 1,参数,参数 2) ;例如,上面实例【2-1】中,已创建 Car 类,下面定义由类产生对象的语句:Cartruck;/声明一个 Car 类的对象 trucktruck = new Car(); /是用 new 关键字实例化 Car 对象并赋值给 truck由上面
10、例子得出,创建属于某类的对象,可以通过两个步骤来实现:1. 声明该类类型的一个变量, 实际上它只是一个能够引用对象的简单变量。2. 利用 new 创建对象,并指派给先前所创建的变量。即在内存中划分一块区域存放创建出来的对象,并把该内存空间指向对象的引用。当然也可以把声明和实例化的过程通过一个语句完成,这种形式为:Cartruck = newCar();对象实例化的过程在内存中的存在形式如图 2-2:图 2-2 对象实例化过程的内存创建示意图5.3.2 对象的使用创建类的对象目的是为了能够使用在这个类中已经定义好的成员变量和成员方法。通过使用运算符“.” ,对象可以实现对自己变量的访问及对自己方
11、法的调用。对象访问格式如下:变量访问:变量访问: 对象名对象名.成员变量名;成员变量名;方法访问:方法访问: 对象名对象名.成员方法名(成员方法名(参数参数 1,参数,参数 2) ;例如:创建 2 个实例 2-1 中的 Car 对象,对象名分别为 truck、bus,然后对这两个对象进行属性赋值。Car truck = new Car();truck.color=黑色; truck.count =3;truck.bound=黄河; truck.weight=12.5f;Car bus = new Car();bus.color =红色; bus.count =50;bus.bound=宇通;
12、bus.weight=8.5f;truck 与 bus 各自占有一块内存空间,有自己的属性值,所以 truck、bus 不会互相影响。这也就是说由一个类实例化出的对象相互间没有直接的关系,各自都有着独立的存储空间,修改自己的属性是不会影响到其他对象的。图 2-3由 Car 类实例化得到的 truck 和 bus 对象内存分配图任务实施1.实现思路(1)打开 Eclipse,创建 Person 类;(2)在类大括号内进行属性定义;(3)利用创建的 Person 对象,使用“对象名.属性名”形式进行赋值,并输出对象的各个属性值。2.程序代码package com.soft.ght;/包名publi
13、c class Person描述“人类”信息程序设计描述“人类”信息程序设计/省略属性声明public static void main(String args) Person p1 = new Person () ; / 声明并实例化一 Person 对象 p1Person p2 = new Person () ;/声明并实例化一 Person 对象 p2/ 给 p1 的属性赋值p1.name = 张三 ;p1.age = 25 ;p1.address=济南;p1.sex=m;p1.weight=100;/ 给 p2 的属性赋值p2.name = 李四 ;p2.age = 30 ;p2.ad
14、dress=北京;p2.sex=w;p2.weight=80;/省略输出语句任务拓展任务中对类 Person 的测试是在类中的 main()方法中进行的。但在实际的项目中每一个有代表含义的类都是要单独存在, 而测试使用的 main()方法也应当放在一个单独的类中, 对上面的任务进行拓展要求新建一个 PersonTest 测试类,对类 Person 进行测试。每个类单独为一个源代码文件。package com.soft.ght;/包名public class Person /省略属性声明public class PersonTest public static void main(String
15、args)/ 声明并实例化一 Person 对象 p1Person p1 = new Person () ;/声明并实例化一 Person 对象 p2Person p2 = new Person () ;/省略给 p1 的属性赋值描述“人类”信息程序设计/省略给 p2 的属性赋值/省略输出语句运行结果如下所示:我是:张三,性别:m,今年:25岁,体重:100.0,住址是:济南我是:李四,性别:w,今年:30岁,体重:80.0,住址是:北京任务实训1.实训目的 掌握类的定义; 掌握创建类对象的方法; 掌握使用对象的步骤。2 实训内容编写一个手机类,其中属性包括手机品牌、手机型号;方法包括显示手机
16、信息,并编写测试类进行对象创建。学习任务 02借书卡是学生日常生活重要组成部分。每张借书卡信息包含账号、持卡人姓名、身份证号码、地址、已借书数、可借书数、本次借书数、本次还书数。方法有借书、 还书和查询。 要求根据持卡人不同操作, 显示不同信息。 当借书操作后,显示本次借书数及已借书数;当还书操作时,显示本次还书数和已借书数。运行结果描述“人类”信息程序设计知识准备5.4 类的方法5.4.1 定义类的方法类中的方法又称之为成员方法或成员函数,用来描述类所具有的功能和操作,是一段完成某种功能或操作的代码段。方法定义的格式:访问修饰符访问修饰符返回值类型返回值类型 方法名称方法名称 (参数列表参数
17、列表) 方法体方法体注解:1. 返回值类型返回值类型。表示方法返回值的类型。如果方法不返回任何值,它必须声明为 void(空)。对于不返回 void 类型的方法必须使用 return 语句。方法返回方法返回值类型必须与值类型必须与 returnreturn 语句后面的表达式数据类型一样语句后面的表达式数据类型一样。例如,方法中含有语句return Java;那么方法的返回值类型必须是 String 类型。2.2. 方法名称:方法名称:可以是任何 Java 合法标识符,一般要求方法名字要有意义,并且首字母小写。例如:定义一个获得姓名的方法名,可以写作 getName()。3.3. 参数列表:参数
18、列表:参数是方法接收调用者信息的唯一途径,Java 允许将参数值传递到方法中。多个参数用逗号分开,每一个参数都要包含数据类型和参数名。方法中的参数一般称为形式参数(简称形参) ,而由调用者传入的参数称之为实际参数(简称实参) 。【注意】(1)形参和实参的类型必须要一致,或者要符合隐含转换规则。(2)形参类型不是引用类型时,在调用该方法时,是按值传递的。在该方法运行时, 形参和实参是不同的变量,它们在内存中位于不同的位置,形参将实参的值复制一份,在该方法运行结束的时候形参被释放,而实参内容不会改变。(3)形参类型是引用类型时,在调用该方法时,是按引用传递的。运行时,传给方法的是实参的地址,在方法
19、体内部使用的也是实参的地址,即使用的就是实参本身对应的内存空间。所以在函数体内部可以改变实参的值。【实例 2-2】定义一个加法方法,方法的功能是将两个输入的整数操作数相加的结果作为方法的返回值。public int addOperate(int op1,int op2) /声明方法,返回值为int型return op1+op2;/return后面的表达式结果是int类型借书卡程序设计借书卡程序设计5.4.2 使用类的方法方法定义的目的是让其他类进行调用使之发挥方法执行的功能。 方法的使用的一般前是必须先创建对象,然后使用“.”操作符实现对其方法的调用,方法中的局部变量被分配内存空间,方法执行完
20、毕,局部变量即刻释放内存。使用方法的格式如下:数据类型数据类型 接收变量名接收变量名=对象名对象名.方法名方法名(实参实参 1,实参实参 2,);如果两个方法在同一类中,可以直接使用该方法名字进行调用。使用 static修饰的静态方法有点特殊,静态方法的调用无需定义对象,可以通过类名直接使用。格式如下:数据类型数据类型 接收变量名接收变量名=类名类名.方法名方法名(实参实参 1,实参实参 2,);【实例 2-3】计算立方体的体积程序设计public class Box public int calVolume1 (int width,int height,int depth) /声明方法ret
21、urn (width * height * depth);public static int calVolume2 (int width,int height,int depth) /声明方法return (width * height * depth);public class Main public static void main(String args)Box b1=new Box ();int volume=b1.calVolume1(10,20,50);/使用对象.方法名调用int volume1=Box. calVolume2(10,20,50);/使用类名.方法名调用程序 in
22、t volume=b1.calVolume1(10,20,50);表示由对象 b1 调用了方法calVolume1 并传入了 10,20,50 三个实际参数。【经验】方法调用的目的是要执行方法的功能,若方法执行完毕并有返回值,那么这个返回值是相当重要,但是方法执行完毕后并不会自动保存返回值,因此我们需要使用一个变量来存储方法的返回值。变量的数据类型与方法的返回值类型一样。借书卡程序设计5.5 构造方法每次在创建实例变量,对类中的所有变量都要初始化是很乏味的。如果在一个对象最初被创建时就把对它的设置做好, 那样的话, 程序将更简单并且更简明。Java 允许对象在创建时进行初始化,初始化的实现是靠
23、构造函数来完成的。创建类的对象时,使用 new 关键字和一个与类名相同的方法来完成,这个方法是在实例化过程中被调用的, 称之为构造方法。 构造方法区别于普通的方法,有几个明显的特点:1.它的名字必须与它所在的类的名字完全相同。2.不返回任何数据类型,也不需要使用 void 声明。3.它的作用是创建对象并初始化成员变量。4.在创建对象时,系统会自动调用类的构造方法。5.构造方法一般都用 public 来声明,这样才能在程序任意位置创建对象。6.每个类至少有一个构造方法。如果不写构造方法,Java 将提供一个默认的不带参的方法体为空的构造方法。构造方法定义格式:访问权限访问权限 类名称类名称(参数
24、参数 1,参数参数 2,)/程序语句程序语句 ;/构造方法没有返回值构造方法没有返回值【经验】【经验】如果类中显性的定义了构造方法, 那么系统不再提供默认的不带参的方法体为空的构造方法。若对一个已完成的程序进行扩展,因某种需要而添加了一个类的构造方法,由于很多其他类原先使用默认构造方法,这势必会导致找不到构造方法的错误。解决的方法就是把默认的构造方法显性的写出来。当构造方法定义完毕后就可以通过创建对象来对属性进行初始化操作。 一般情况下需要结合 new 实例化操作,使用传递实参的形式进行。【实例 2-4】使用构造方法对 Person 类的两个属性进行初始化,并打印各个对象的属性值。public
25、 class Person借书卡程序设计String name;int age;public Person()/默认的构造方法需要显性的写出来public Person(String myName,int myAge)/带参的构造方法来初始化属性name= myName;age= myAge;public class TestNewPerson public static void main(String args)/通过 new 操作并传入实参来实现属性的初始化和对象的实例化Person p1=new Person (张三,20);Person p2=new Person (李四,30);S
26、ystem.out.println(我是:+p1.name+,今年:+p1.age+岁);System.out.println(我是:+p2.name+,今年:+p2.age+岁);程序运行结果如下:我是:张三,今年:20 岁我是:李四,今年:30 岁5.6 方法重载方法重载方法重载是指多个方法享有相同的名字,但是这些方法的参数必须不同。例如,参数的个数不同,参数类型不同,参数的顺序不同等。当一个重载方法被调用时,Java 根据参数的类型和(或)数量来表明实际调用的重载方法。参数不同是区分重载方法的关键因素,参数不同主要包括以下方面的不同:(1) 参数类型不同。例如: public void
27、method(String s); public void method(int s);(2) 参数个数不同。例如: public void method(String s,int i); public void method(String s);(3) 参数顺序不同。例如: public void method(String s,int i); public void method(int i,String s);【注意】参数顺序不同的情况中一定要注意指的是参数全体,而不是简单的参数名,参数名在参数中其实没有实际意义,只是一个代号。例如: public void method(String
28、s,int i); public void method(String i,int s);上面的例子是不属于顺序不同的,因为只是互换了参数的名字,参数的类型并没有互换。【实例 2-5】求圆形的面积,要求用户输入任何类型的数据后都要能得到最终的面积值。public class MethodOverloading final float PI=3.14;double calArea(double r) return PI * r * r;float calArea (float r) return PI * r * r;float calArea(int r) return PI * r * r;
29、folat calArea (String r) float i=Float.parseFloat(r);return PI * i * i;public class Main public static void main(String args) MethodOverloading mo = new MethodOverloading();System.out.println(面积是:+mo.calArea(10);/调用参数为int的方法System.out.println(面积是:+mo.calArea(9.5);/调用参数为double的方法System.out.println(面积
30、是: +mo.calArea(8.5f);/调用参数为float的方法借书卡程序设计System.out.println(面积是:+mo.calArea(10);可以发现方法重载主要目的是为了满足在不同输入的情况下依然可以得到进行相同或相似的处理。 在编程上有些麻烦, 但是在使用性和灵活性得到了加强。由于实现了Java在编译时的方法的多种状态,所以有时也成为静态多态。在 Java 里,不仅普通方法可以重载,构造方法也可以重载。构造方法的重载是为了让实例化对象和初始化变量更为方便。【实例 2-6】利用构造函数重载创建对不同变量初始化的对象public class Rectangle double
31、 width;double length;Rectangle () /直接初始化为数值width = 1;length=5;Rectangle (double x)/把两个变量初始化为相同传入值width = x;length =x;Rectangle (double w,double len) /分别对两个属性初始化不同的值width = w;length=len;public void prnt()/省略方法体;public class ConstructOverLoad public static void main(String args) Rectangle Rectangle1 =
32、 new Rectangle (10,20);Rectangle Rectangle2 = new Rectangle ();Rectangle Rectangle3 = new Rectangle(7);/省略其他语句借书卡程序设计在实例中有三个 Rectangle ()构造函数, 当 new 执行时根据指定的参数多少调用适当的构造函数。5.7 变量的作用域变量声明的位置决定变量作用域。Java 变量的范围有四个级别:类级、对象实例级、方法级、块级。 类级变量又称全局级变量,在对象产生之前就已经存在,即用static修饰的属性。 对象实例级,就是属性变量。 方法级:就是在方法内部定义的变量,
33、就是局部变量。 块级:就是定义在一个块内部的变量,变量的生存周期就是这个块,出了这个块就消失了,比如if、for语句的块。【实例 2-7】变量作用域演示程序设计public class TestVariable private static String name = 类级;/ 类级private int i; / 对象实例级/ 属性块,在类初始化属性时候运行int j = 3;/ 块级public void test1() int j = 4;/ 方法级if (j = 4) int k = 5;/ 块级/ 这里不能访问块级的变量,块级变量只能在块内部访问System.out.println(
34、name= + name + ,i= + i + ,j= + j);public static void main(String args) TestVariable t = new TestVariable();t.test1();TestVariable t2 = new TestVariable();程序运行结果如下:借书卡程序设计name=类别,i=0,j=4若局部变量与类的成员变量同名,则类的成员变量被隐藏。下面的例子说明了局部变量 z 和类成员变量 z 的作用域是不同的。【实例 2-8】同名变量作用域测试程序设计public class Variable int x = 0, y
35、= 0, z = 0;/ 类的成员变量void init(int x, int y) this.x = x;this.y = y;int z = 3; / 局部变量System.out.println(* in init* + x= + x + y= + y + z= + z);public class VariableTest public static void main(String args) Variable v = new Variable();System.out.println(*before init* + x= + v.x + y= + v.y + z=+ v.z);v.i
36、nit(10, 15);System.out.println(*after init* + x= + v.x + y= + v.y + z=+ v.z);运行程序结果如下。*before init*x=0 y=0 z=0* in init *x=10 y=15 z=3*after init*x=10 y=15 z=05.8 定义包和导入包的关键字Java 中为了便于管理各种类,将多个具有类似功能的类方法组成一个组,这个组就称之为包(package) 。伴随着包的出现,同时解决了命名冲突、引用不方便、安全性等问题。程序员在协同编写程序时很多时候是完全不知道别人使用的类名,如果使用了相同的类名则会
37、产生冲突,若使用包的机制,即使不同包中的两个同名文件也不会冲突。 这就类似于不同文件夹下允许建立相同名称的文件。借书卡程序设计5.8.1 定义包Java 通过关键字 package 来定义包。package 语句作为 Java 源文件的第一条语句,指明该源文件定义的类所在的包。格式如下:package 包名包名注释:1. 包名的命名规范是若干个标识符加“.”分割而成。例如:package .can;2. Sun 公司建议使用公司域名倒写顺序来定义包,然后加入子包。例如:某公司的域名为 ,那么包名为 com.ican。5.8.2 使用包如果几个类分别属于不同的包,为了能够使用某一个包的成员,需要
38、在Java 程序中使用 import 关键字语导入该包。格式如下:importpackage1.package2.(classname|*);注解:1. Java 源文件中 import 语句应位于 package 语句之后,所有类的定义之前。2. *操作符表示导入包中所有的类。3. 使用 Eclipse 等开发工具编程时,工具会及时提醒需要导入的包。4. 导入的包可以是 Java 类库中的包或类,也可以是自定义的包和类。 经经 验验 为了方便很多时候会使用*关键字来导入整个包,这样会增加编译时间特别是在引入多个大包时。 因此明确命名想要用到的类而不是引入整个包是一个好的方法。然而,星号形式对
39、运行时间性能和类的大小绝对没有影响。任务实施1实现思路Java 中的方法描述了类的行为。本任务中的行为有借书、还书和查询。在BookCard 类分别定义了 3 个方法: borrow(int);TheReturn(int);query()。 打开 Eclipse,创建 BookCard 类; 在类大括号内进行属性定义; 在类的大括号内定义 3 个方法,表示借书、还书和查询; 在 BookCard 类的 main 方法中,创建一个 BookCard 类的对象; 利用创建的 BookCard 对象,用对象名.方法的形式调用方法,完成具体的功能; 运行程序。2. 程序代码package com.gh
40、t.soft;public class BookCard /省略属性赋值,属性有:账号、持卡人姓名、已借书数、可借书数public void borrow(int cash) if (Remain = cash) Remain = Remain - cash;/省略输出语句public BookCard() public BookCard(String cardnum, String name, String idname, intborrowsnum,int returnnum, int remain) /省略属性赋值语句public void TheReturn(int cash) Rem
41、ain = Remain + cash;/省略输出语句public void query() System.out.println(可借书数 + Remain);public class Task02 public static void main(String args) / 程序的入口BookCard wang = new BookCard(); / 创建类的对象/省略属性赋值语句wang.query();借书卡程序设计任务拓展一般方法都是需要有返回值的, 并且调用方法后都需要使用返回值进行下一步执行的开始,及时一些方法没有明显的返回也可以使用 Boolean 类型作为返回值来说明方法执行
42、完毕与否。下面对任务进行扩展让 borrow(int)、TheReturn(int)方法都具有返回值,现在改为正确借书、还书后,返回 true,否则返回 false。public class Bookcard2 /省略属性赋值public boolean borrow(int cash) if (Remain = cash) Remain = Remain - cash;System.out.println(本次借阅书数 + cash);System.out.println(可借书数 + Remain);return true;return false;public boolean TheRe
43、turn(int cash) if (cash 0) Remain = Remain + cash;return true;System.out.println(本次还书数 + cash);System.out.println(可借书数 + Remain);return false;public void query() System.out.println(可借书数 + Remain);public static void main(String args) / 程序的入口借书卡程序设计BookCard wang = new BookCard(); / 创建类的对象/省略属性赋值语句if(w
44、ang.borrow(1)wang.query();if(wang. TheReturn(1)wang.query();任务实训1.实训目的 掌握类的方法定义和使用; 掌握定义包和导入包; 掌握变量作用域; 掌握注释使用方法。2.实训内容编写一个程序,实现设置上月电表读数、设置本月电表读数、显示上月电表读数、显示本月电表读数、计算本月用电数、显示本月用电数、计算本月用电费用、显示本月用电费用的功能。学习任务 03任务描述在现实中,人的年龄和体重都不能小于 0;更恐怖的是如果忘记给名字赋值就会成为无名氏。 要求使用封装完成对属性的控制, 当年龄输出错误时提示出错。运行结果借书卡程序设计知识准备2
45、.9 封装2.9.1 封装的概念封装是 JAVA 面向对象的一种特性,也是一种信息隐蔽技术。它有两个含义: 一是指把对象的属性和行为看成一个密不可分的整体,将这两者“封装”在一个不可分割的独立单位(即对象)中。另一层含义指“信息隐蔽”,把不需要让外界知道的信息隐藏起来,有些对象的属性及行为允许外界用户知道或使用,但不允许更改,而另一些属性或行为,则不允许外界知晓;或只允许使用对象的功能,而尽可能隐蔽对象的功能实现细节。2.9.2 如何实现封装Java 中的封装不是为了做一个完全不能对外开放的类,这种类也没有任何存在意义。封装只是为了对类中的属性更好进行控制,因此要实现封装需要属性私有化,这样可
46、以保证属性不会被其他类改动。然后使用公有方法把私有的属性暴露出去,在方法中对属性进行有效读写控制,也把这些方法称之为访问器。封装的实现需要提供三项内容:1. 一个私有的属性(变量) ,使用 private 来声明私有变量。例如:private String name;2. 一个公有的读操作访问器,使用 getter 方法来完成。例如:public String getName()/方法体3. 一个公有的写操作访问器,使用 setter 方法来完成。例如:public void setName(String name)/方法体【实例 2-9】 使用封装技术模拟对学生借书的过程, 要求学生最多只能
47、借 10本书。学生类中只有一个整数型变量 count,为书的数量,对 count 设置时不能大于 10,获得 count 值时不能获得一个负数。public class Student private int count;public void setCount(int myCount) if(myCount10)保护人的“隐私”程序设计保护人的“隐私”程序设计System.out.println(获取错误);elsecount= myCount;public int getCount() if(count=0)System.out.println(获取错误);return 0;elseret
48、urn count;public class TestStudent public static void main(String args)Student s=new Student();s.setCount(11);s.setCount(5);int count=s.getCount();System.out.println(“Count的值是:”+count);s.setCount(0);count=s.getCount();System.out.println(“Count的值是:”+count);程序运行结果如下:设置错误设置错误Count 的值是 5获取错误 提示提示 对于什么时候
49、需要封装,什么时候不用封装,并没有一个明确的规定,不过从程序设计角度来说,设计较好的类属性都是需要封装。要设置或取得属性值,则只能用 setXxx()、getXxx()方法,这是一个明确且标准的规定。2.10 Java 的修饰符在定义类中成员变量和成员方法时,都会使用一些修饰符来做出某些限制。修饰符分为访问控制修饰符和非访问控制修饰符。访问控制修饰符是来限定类、属性或方法在程序其他地方访问和调用权限的,包括public、private、protected等。Java的非访问先支付包括:static、final、abstract、native、volatile、synchronized等。1.p
50、ublic 修饰符public 修饰符表示公有,可以修饰类、属性和方法。如果使用了 public 访问控制符,则它可以被包内其他类、对象以及包外的类和对象方法使用。 注意注意 每个 Java 程序的主类都必须是 public 类。若在一个 Java 源文件中定义了多个类,只能有一个类是公有类。一般的构造方法都会使用 public 来修饰。2.private 修饰符private 修饰符只能修饰成员变量和成员方法。若使用 private 声明的变量和方法则只能由它所在类本身使用,其他的类和对象无权使用该变量和方法。封装中就是利用了这一点特性让属性私有化。如果一个类的构造方法声明为 private