《Java程序设计基础》第5章:类与对象.ppt
第5章 类与对象,学习重点:类的定义方法是如何成为对象的对外接口的类的实例化Java Application的基本结构,本章逻辑结构,5.1 对象的实现 对象的结构 对象和类的关系 类的定义 对象的创建 程序结构及使用对象的成员 修饰符 再谈方法 对象间的赋值 构造函数 对象有效范围和废物回收 5.2 Java 应用程序的结构 应用程序结构 命令行参数 5.3 练习题,5.1 对象的实现,在面向对象的思想中,任何实体都看做对象。对象是通过对实体进行抽象得到的,它并不要求能面面俱到地反映一个实体,它只抽象出程序中用到的一些东西。但这个所谓的对象和程序中的什么样的结构相对应?程序是如何实现对象的呢?这一节将解释这些内容。,5.1.1 对象的结构,程序中的对象是一个固定结构,它是由属性和方法组合在一起形成的。属性是实体的一些特征值或组件,方法用来表示实体的功能和动作,即它能进行什么操作,能产生什么动作。我们拿一台电力磨面机为例,说明程序中对象的结构。,磨面机有许多特征值,它也有许多组件,所有这些东西,如果程序需要的话,就用某个名称来代表它,形成属性,它们的值就是属性值,不同的属性可能属于不同的类型,例如:,float weight;/重量 float power;/功率 Electromotor electromotorA;/一个电机 其中,weight和power都是浮点型,而electromotorA是Electromotor类型,它既是miller的一个属性,又是一个对象,且这个对象Electromotor类的一个实例,它也有自己的属性和 方法。,磨面机的功能就是磨面,我们就用一个方法来表示它,可取名为milling。我们把磨面看成是一个方法,其输入是wheat,输出是flour。属性和方法都放入一个整体的结构中,就形成了一个对象,可取名为millerA。millerA的属性和方法可以总结到下图中。,面向对象方法就是把任何事物都看做对象,都抽象成类似上面的一种结构。那么为什么要这样思考问题呢?,有了对象结构,外界就不能直接修改对象的属性,需要修改时必须通过对象的方法来间接操作,对象通过自己的方法把自己的属性封装了起来,它与外界的联系都是通过方法来实现的,5.1.2 对象和类的关系,事实上,类与对象的关系如同图纸和实体一样。假设一个程序就是一台机器,它由许多零件组成,对象就相当于机器的一个个零件,类相当于不同零件的图纸。一台机器的制造是先画图纸,然后按照图纸制造零件,最后组装机器。Java程序也是这样,先定义一个个类,再按照类的模式建造对象(这一步称为类的实例化),最后用对象来完成程序功能。,5.1.3 类的定义,类的定义格式如下:修饰符 class 类名 extends 父类名 implements 接口名1,接口名2,类属性声明;类方法声明;其中以 括起的内容表示定义时可以没有。以大括号括起的内容称类体,之前部分称类头,修饰符 class 类名 extends 父类名 implements 接口名部分就是类头。,1.类头说明,类头中关键词class表示类定义的开始,后面紧跟的是类名。修饰符用来说明类的特殊性质,如前面程序中的public等。关键词extends表示该类是个子类,它的父类名紧跟在extends后。关键词iplements表示该类实现了哪些接口,后面就是接口名。,2.类体说明,类体的说明包括两部分:属性说明和方法说明属性说明的格式如下:修饰符 变量的数据类型 变量名=初始值;/类属性为简单变量时修饰符 类名 对象名=new 类名(参数列表);/类属性为对象时,类属性是简单变量时,这个变量可以不赋初值(这点和方法中的变量不同),这时它将被置为该数据类型的默认值。类属性为对象时,定义中的类名一定是另一个类,后面的对象就是该类名的实例。new 类名(参数列表)是指创建该对象,如果没用new,该句只说明了这个属性是某个类的对象,而并没有创建它。,5.1.4 对象的创建,要使用某一个类所定义的属性或方法时,必须先定义并创建这个类的一个对象,并用对象调用属性或方法,而不能直接用类去调用属性和方法。,定义对象的目的是声明某个对象属于某个类。创建对象是指在内存中按照类的模式开辟了一块区域,把属性和方法放到了这个区域中,系统这才可以从内存中调用它们。,定义对象的格式如下:类名 对象名,对象名,;例如:Car myCar1,myCar2,myCar3;,创建对象称为类的实例化,它的格式如下:对象名=new 类名();例如:myCar1=new Car();/创建对象myCar1,如果定义和创建对象放在同一个语句,格式如下:类名 对象名=new 类名();例如:Car myCar4=new Car();/定义并创建对象myCar4把几个同类对象的定义和初始化放到一个句子中,格式如下:类名 对象名1=new 类名(),对象名2=new 类名();例如:Car myCar1=new Car(),myCar2=new Car(),myCar3=new Car();这两个语句的意思是在内存中按类Car的格式开辟一个空间,其中既有属性空间又有方法空间,同类的不同对象占有不同的内存空间,它们互不干扰。,我们来比较一下简单数据类型、数组和对象创建后在内存中的不同,a是简单数据类型,只要定义后就在内存中开辟了一定的空间。b是数组的内存空间,数组是以对象的形式存在,所以以关键词new来创建,它在内存中开辟连续的大小相同的空间,每个内存空间的大小对应于所定义的简单数据类型。c是对象的内存空间,从图上可以看出对象也只是一种复杂的数据类型,它用不同数的bit存放不同的属性,再用不同数的bit来存放它的不同方法,由此组成一个内存段,内存段中的格式依据类的定义。,5.1.5 程序结构及使用对象的成员,这里有一个类的定义,只有一个属性:a,还有两个方法分别用设置和获取属性a的值。例5.1A 对象的创建和使用一public class SimpleClass/类的定义private int a;/属性public int getAttribute()/获取属性的方法return a;public void setAttribute(int x)/设置属性值的方法 a=x;,现在我们就用另一个类来创建上面类的对象,并使用该对象。,例5.1B 对象的创建和使用二public class UseSimpleClasspublic static void main()SimpleClass object1=new SimpleClass();/创建对象object1object1.setAttribute(9);/使用对象的方法prt(Object1.getAttribute(9);/把对象的方法作为参数 传递给方法prt()static void prt(String s)System.out.println(s);,对象的使用就是指使用对象的成员(属性和方法),如果要使用对象的属性和方法采用这样的结构:对象名.成员,其中的“.”代表调用。例如:上面程序中的object1.setAttribute(9)就是调用对象object1的方法setAttribute(),并把9作为形参。用“.”可以进行多层调用例如:如果一个对象a的属性还是一个对象,名为b,b有一个方法c(),当使用这个方法时,应为:();。如果层次更多,可能会有这样的现象:();。,5.1.6 修饰符,在定义类、属性和方法时,都要用到修饰符。修饰符位于语句的最前端,与后面的关键词以空格分隔,如果有多个修饰符,也同样以空格分隔。格式如下:修饰符1 修饰符2 修饰符n class 类名 修饰符1 修饰符2 修饰符n 数据类型 属性名;修饰符1 修饰符2 修饰符n 返回值类型 方法名(形参)修饰符有:访问控制符,static,abstract和final等,1.访问控制符,包是一种类的集合,集合中的类并不需要有严格的某种关系,如继承等,只是为了更容易地管理已存在的类而放到同一个包中。,类访问控制符,类访问控制符:public(公共类)和默认(friendly)一个类被定义为公共类,表示它能被其他所有的类访问和引用 一个类定义为友好类(即没有加访问控制符),表示该类只能被同一个包中的类访问和引用,而不可以被其他包中的类访问或使用,属性和方法的访问控制符,属性和方法的控制符:publicprivateprotectedprivate protected默认,public修饰的属性和方法就是公共属性和公共方法 private成为私有访问控制符,经它修饰的属性和方法只能被该类自身所访问或调用,而不能被其他类(包括该类的子类)访问或调用。要想访问该属性必须通过能得到该属性值的方法,如果该类中没有这样的方法,那这个属性将只能被这个类使用。例如:public class Car/定义一个公共类Carprivate int engineNumber;/定义私有属性发动机序列号:engineNumberpublic getEngineNumber()/定义公共方法来给出发动机序列号return engineNumber;/返回发动机序列号,protected称为保护访问控制符,它修饰的属性和方法比private修饰的有较大的可见域,它可以被同一个包中的其他类、不同包中该类的子类以及该类自身访问和引用。private protected称为私有保护访问控制符,经它修饰的属性和方法可以被该类自身和该类的子类访问和引用,不管子类是否在那个包中。默认访问控制符表示没有访问控制符的属性和方法,具有包内访问性,只能被同一个包中的其他类访问或引用,不在同一个包中的类不能访问它。,2.关键词static,实际中有很多时候,需要用类直接调用类的方法或属性。Java中用关键词static(静态的)来实现这一功能,static只能修饰属性和方法。原因:static修饰的属性和方法在类加载内存时就开辟了内存空间。,例5.2 静态变量的使用,程序代码如果改变一个类的静态属性值,那么所有这个类的对象的该属性也发生同样的变化,而改变一个对象的非静态属性值,不会对其他同类对象造成影响。,3.其他修饰符,abstract,final 抽象修饰符abstract可以修饰类和方法。final是最终修饰符,它可以修饰类、属性和方法以及自变量。volatile,synchronized volatile一般用于修饰属性,synchronized用于修饰方法或一个代码段。native native是用来修饰方法的,它表示该方法不是用Java语言写成的(通常是C,C+和汇编语言等),它要通过JNI(Java Native Interface)来与Java程序连接。,native定义方法的格式如下:native 返回值类型 方法名(形参);,例:class HelloWorld public native void displayHelloWorld();/定以一个native方法 public static void main(String args)new HelloWorld().displayHelloWorld();其中方法displayHelloWorld()是由C语言写成,4.多个修饰符一起使用,多数情况下,多个修饰符可以同时修饰一个目标(方法、属性、类等),例如:public abstract class Car 但有些时候修饰符间的意义是相斥时就不能放到一起修饰,例如:abstract不能与final共同修饰同一个类。abstract不能与private,static,final和native共同修饰同一个方法。abstract类中不能有私有属性或方法。private protected是一个修饰符。,5.1.7 再谈方法,例5.3 非静态方法的使用程序代码由于main()方法是程序的入口,一般在main()方法内创建自身类的对象。在其他方法中创建自身类的对象时,如果方法不是静态的就会出错。,例5.4 方法中传递对象,程序代码传递对象时只是传递了对象的地址,因此在其他方法中对形参对象的修改表现为原对象成员的改变。,5.1.8 对象间的赋值,对象间赋值只是把一个对象的地址给了另一个对象名,相当于给这个对象取了一个别名而已。例如:对象赋值:假设a、b都是类Class的两个对象。b=new Class();a=b;a和b都对应内存中同一个地址,例5.5 对象间赋值,程序代码程序的结果可以看到,不管改动哪一个对象的属性,另一个也会改变。,5.1.9 构造函数,我们先来讲一下为什么需要构造函数。假设在创建Car类的对象myCar1,myCar2和myCar3时,希望它们在创建时就有不同的颜色,那我们在创建对象的同时,对对象的颜色这个属性进行赋值,不然,它的值将是空。要对属性赋初始值就要用到构造函数。,构造函数有以下几个特点:,由于构建函数的名字必须与类名完全相同,所以方法首字母小写的推荐规则并不适用于构建函数。构造函数是给对象赋初值,所以没有返回值,但不需要用void来指明这一点。构造函数不能被程序显式调用,即读者不应该企图像其他方法一样地使用构造函数。构造函数可以在类中由编程者定义,如果编程者没有定义,系统将自动生成一个构造函数,来完成对象创建时的初始化工作,但这个构造函数只是一个有着和类名相同名字的空方法,属性将被赋予该数据类型的默认值。这样我们也明白了简单数据类型在作为对象的属性时可得到默认值,而作为自变量时必须初始化。构造函数可以通过重载(关于重载将在下一章讲述)实现不同的初始化方法,在这里只需知道重载是指几个同名的方法有不同个数或同个数不同类型的形式参数,调用时根据与之相对应的实际参数来决定调用哪一个方法。,例5.6 构造函数,这个例子中定义了一个类为Cat,它有两个构造函数,然后我们在另一个类中用不同的构造函数创建Cat类的两个对象,并且,这两个对象被创建时就有不同的属性值:颜色和重量。程序代码,静态初始化器,它只对类进行初始化而不是对象,因此它操作的一定是类的静态属性。它是在该类加载内存时系统自动调用的。它的格式也很特别,就是用static引导一对大括号,大括号内就是对属性初始化的语句组。例如:static myCarMaxSpeed=150;,例5.7 静态构造器的使用,这个程序中用一个静态初始化器给一个变量赋初值,然后每创建一个对象,它的值就加一,这样所有这个类的对象就可以有一个序列号。程序代码,5.1.10 对象有效范围和废物回收,Java本身提供了对象无用时自动清除的功能,同时它也提供了一个自动拉圾箱的方法,在清除对象时被调用 例如:Protected void finalize()close();,在Java里,收集和释放内存是一个叫自动废品回收站的线程的责任。例如:Strings;/没有分配内存 s=new String(“abcdefg”)/分配内存 s=“hijklmn”/重新分配内存(创建新对象),5.2 Java 应用程序的结构,5.2.1 应用程序结构例5.8 对程序JudgementAndOutput.java的修改一 程序代码这段程序将输入与判断输出分成两个方法,分别进行定义,例5.9 对程序JudgementAndOutput.java的修改二,程序代码上例由两个文件组成,例5.10 对程序JudgementAndOutput.java的修改三,程序代码上例中用类的嵌套,即在一个类中定义一个或多个类中类,由于类的实例化都是在方法的定义中,而且只需一个语句,因此我们看到的Java 应用程序是由类的定义构成的,其中有一个类含有main()方法,每个public类占有一个.java文件,一个程序可能含有多个文件,所以源程序的结构应如下:,文件1:import;public class 类名11 public static void main(String args)class 类名12文件2:import;public class 类名21 class 类名22文件n:import;public class 类名n1 class 类名n2 Java程序的多个类中一个类是含有main()方法的,我们称它为主类,程序就是从main()方法开始执行。,例5.11 直接引用其他.java文件定义的类,我们已经有了Input这个类(指的是public修饰的那个Input类),它能完成特定的功能,我们只要知道它的运行条件(如是否需要输入参数)和它的输出结果就能在其他程序中使用它。程序代码这个例子用来判断输入的字母代表哪个方向,用到Input类中的方法获取输入的字母。,5.2.2 命令行参数,所谓的命令行参数是指在命令行中执行某个Java程序时直接将一些参数发送给程序,通过一些特殊的处理,我们可以在程序中获取这些参数的值,并运用到程序的执行过程中。,例5.12 命令行参数的使用,这个程序用来把命令行的参数相加并输出。程序代码所谓命令行参数是指命令(如java CmdLineParam)以后的参数,它不包含命令本身。,5.3 练 习 题,1.选择题(1)关于对象成员占用内存的说法哪个正确?A.同一个类的对象共用同一段内存B.同一个类的对象使用不同的内存段,但静态成员共享相同的内存空间C.对象的方法不占用内存D.以上都不对,(2)下列说法哪个正确?A.不需要定义类,就能创建对象 B.对象中必须有属性和方法 C.属性必须是简单变量 D.属性可以是简单变量,也可以是一个对象,3.编程实现以下要求:(1)写一个类,它的实例表示从一副牌中打出牌。(2)写一个类,它的实例代表一副牌。(3)利用上面的两个类写一个程序,演示一副牌中所有的牌,结果如下:,Ace of DiamondsTwo of DiamondsTen of DiamondsJack of DiamondsQueen of DiamondsKing of DiamondsAce of ClubsKing of ClubsAce of HeartsKing of HeartsAce of SpadesKing of Spades,