1 / 138

Java 程序设计基础

Java 程序设计基础. 第 5 章 面向对象程序设计. www.avceit.cn. 1. 面向对象程序设计概述. 2. 类 (class). 3. 5. 类的特性. 包. 4. 接口 (interface). Contents. 第 5 章 面 向 对 象 程 序 设 计. 前面主要学习了 Java 语言的数据类型、控制结构、数组等基本知识。作为 Java 学习者,必须将自己的思维转入面向对象的轨道。 本章主要任务: 理解面向对象编程的基本概念 掌握类和对象的创建方法 了解成员变量和成员方法的特性 学习使用面向对象编程方式进行程序设计

dudley
Download Presentation

Java 程序设计基础

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java程序设计基础 第5章 面向对象程序设计 www.avceit.cn

  2. 1 面向对象程序设计概述 2 类(class) 3 5 类的特性 包 4 接口(interface) Contents

  3. 第5章 面 向 对 象 程 序 设 计 • 前面主要学习了Java语言的数据类型、控制结构、数组等基本知识。作为Java学习者,必须将自己的思维转入面向对象的轨道。 • 本章主要任务: • 理解面向对象编程的基本概念 • 掌握类和对象的创建方法 • 了解成员变量和成员方法的特性 • 学习使用面向对象编程方式进行程序设计 • 理解接口和包的概念

  4. 5.1 面向对象程序设计概述 • Java是一种面向对象的程序设计语言。 • 现实世界里的任何事物,都可以被看作对象。 • 对象是面向对象技术的一个基本概念。 • 类是组成java程序的基本元素。 下面逐一学习面向对象程序设计的有关概念。

  5. 5.2 类(class) • 5.2.1 类的声明 • 类是一组具有相同或相似属性和行为对象的抽象描述。 • 类封装了对象的属性和方法,它是用来定义对象的类型,而对象就是类的一个实例。 • 创建类的一般格式: • [修饰符] class 类名 [extends父类名] [implements接口名列表]{ • 成员变量声明 • 成员方法声明 • }

  6. 其中,class、extends和implements都是Java的关键字(保留字)。其中,class、extends和implements都是Java的关键字(保留字)。 • 类的修饰符主要有public、abstract 、final及缺省访问修饰符等四种。 • 注意:一个类可以同时有多个修饰符,但是不能有相同的修饰符。当一个类有多个修饰符时,这些修饰符无先后顺序,可任意排列。 • 在java中允许定义没有任何成员的空类。

  7. 【例5.1】 定义一个名为Box表示立方体的类,仅包含double类型的长length、宽width和高height三个成员变量。 • class Box{ • double length; • double width; • double height; • } • 通过例5.1,我们可以看到,在类中进行成员变量的声明与一般变量的声明形式完全相同,成员变量的类型可以是任意的,成员变量的名字在一个类中应该保证唯一性。例5.1中的类没有任何方法,下面再看一个有成员方法的类。

  8. 【例5.2】定义一个名为Box表示立方体的类,包含double类型的长length、宽width和高height三个成员变量以及设置立方体长、宽、高值的方法initBox()、计算立方体体积的方法getVol()。【例5.2】定义一个名为Box表示立方体的类,包含double类型的长length、宽width和高height三个成员变量以及设置立方体长、宽、高值的方法initBox()、计算立方体体积的方法getVol()。 class Box{ // 定义Box类 double length; double width; double height; double getVol(){ // 计算立方体体积的方法getVol() return length * width * height; } void initBox(double l,double w,double h){ // 初始化立方体长宽高值 length = l; width = w; height = h; } }

  9. 一旦定义了所需的类,就创建了一种新的数据类型,使用类类型定义的变量叫对象一旦定义了所需的类,就创建了一种新的数据类型,使用类类型定义的变量叫对象 • 如:Box box1; • 定义的box1是一个对类型为类Box的对象的引用,box1不是对象本身,可理解为指针,可以指向类Box的某一个具体的对象(实例)。

  10. 5.2.2 类对象 • 创建类的变量称为类的实例化。 • 类的对象是在程序运行中创建生成的,其所占的空间在程序运行中动态分配。当一个类的对象完成了它的使命,为节省资源,Java的垃圾回收程序就会自动收回这个对象所占的空间,即类对象有自己的生命周期。

  11. 1.创建对象 • 创建类的对象一般需要两步: • 第一步,声明该类型的一个变量; • 第二步,用new运算符为对象动态分配(即在运行时分配) 内存空间,并返回对它的一个引用,这个引用被存储在该变量中。 • 利用new创建类的对象的通用形式如下: • 类对象名 = new 类名(); • 例如,创建一个Box类的对象myBox可用以下语句 • Box myBox; • myBox = new Box();

  12. new运算符允许与类声明结合使用来创建一个类的对象,如上面两行语句可组合为:new运算符允许与类声明结合使用来创建一个类的对象,如上面两行语句可组合为: • Box myBox = new myBox(); • 定义好后,可以把myBox作为类Box的对象来使用,而实际上myBox仅是保存了实例对象的地址,利用它来间接的引用实例对象。

  13. 2.引用对象 • 创建了类的对象后,就可以对对象的各个成员进行访问,以进行各种处理。访问对象成员的通用形式为 • 类对象名 . 成员变量名 • 类对象名 . 成员方法名( ) //括号不能省略 • 运算符“. ”称为成员运算符,在类对象名和成员变量名、成员方法之间起到连接的作用,以此指明是哪个对象的成员。 • 从上面的访问形式,可以看出,要使用对象变量首先要构造对象,获得类对象名,即类变量名。

  14. 【例5.3】利用例5.1定义的Box类,计算长、宽、高分别为5、4、3的立方体体积。【例5.3】利用例5.1定义的Box类,计算长、宽、高分别为5、4、3的立方体体积。 public class BoxDemoOne{ public static void main(String args[]){ Box myBox = new Box(); double vol; myBox.length = 5; myBox.width = 4; myBox.height = 3; vol = myBox.length * myBox.width * myBox.height; System.out.println("立方体的体积是: " + vol); } }

  15. 注意:要编译成功,必须将例5.1定义的Box类置于本程序中,以生成Box.class和BoxDemoOne.class两个字节码文件,程序运行结果如下:注意:要编译成功,必须将例5.1定义的Box类置于本程序中,以生成Box.class和BoxDemoOne.class两个字节码文件,程序运行结果如下: • 长方体的体积是: 60.0 • 当程序需要更多的类对象时,可用new运算符多次创建该类的对象,然后按例5.3中的代码形式进行长方体体积的运算。这样一来,程序中对成员变量的访问赋值语句会很多,显得程序不够紧凑。更好的方法是在类定义中加入可对成员数据进行操作的成员方法(如例5.2所定义的类Box),可使程序更加有效率。

  16. 【例5.4】用例5.2中定义的类Box来计算长、宽、高分别为5、4、3和30、20、10的两个立方体的体积。【例5.4】用例5.2中定义的类Box来计算长、宽、高分别为5、4、3和30、20、10的两个立方体的体积。 public class BoxDemoTwo{ public static void main(String args[]){ Box myBox1 = new Box(); Box myBox2 = new Box(); double vol; myBox1.initBox(5,4,3); myBox2.initBox(30,20,10); vol = myBox1.getVol(); System.out.println("第一个立方体的体积是: " + vol); vol = myBox2.getVol(); System.out.println("第二个立方体的体积是: " + vol); } }

  17. 5.2.3 特殊的方法——构造方法 • 例5.2定义的Box类,专门定义了一个方法initBox()用于对成员变量length、width、height进行赋值初始化。如果在一个对象最初被创建时就能够把它的相关值设置好,程序将会更简单并且更明晰。Java语言允许对象在它们被创建时初始化自己。这种自动的初始化是通过使用一种特殊的方法——构造方法(constructor)来完成的。 • 构造方法的任务就是初始化一个对象的内部状态,以便使创建的实例变量能够完全初始化。它是一种特殊的成员方法,它的特殊性反映在以下几个方面: • 构造方法名称与类名完全相同 • 构造方法不返回任何值,也没有返回类型 • 每一个类可以有零个或多个构造方法 • 构造方法在创建对象时由Java编译器自动调用执行,一般不能显式直接调用

  18. 构造方法的通用声明格式如下 • [构造方法修饰符] 构造方法名([形式参数列表])[throws异常列表]{ • 方法体 • } • 构造方法修饰符有: • public private protected

  19. 【例5.5】利用构造方法重写例5.4的实例。 class Box{ // 定义Box类 double length; double width; double height; Box(double l,double w,double h){ // 利用构造方法初始化立方体长宽高值 System.out.println("Constructing Box"); length = l; width = w; height = h; } double getVol(){ // 计算立方体体积的方法getVol() return length * width * height; } }

  20. public class BoxDemoThree{ public static void main(String args[]){ Box myBox1 = new Box(5,4,3); // 在new执行前自动调用Box()方法 Box myBox2 = new Box(30,20,10); double vol; vol = myBox1.getVol(); System.out.println("第一个立方体的体积是: " + vol); vol = myBox2.getVol(); System.out.println("第二个立方体的体积是: " + vol); } }

  21. 类的构造方法 • 1、无参构造方法 • 一个类若没有任何用户自定义的构造方法,Java会自动提供一个空的无参数构造方法,在创建对象时,使用这个无参的构造方法为类对象的成员变量赋数据类型的默认值。 • 对于以下语句 • Box myBox = new Box(); • 利用new Box()调用构造方法Box()。 • 如果我们不为类定义一个构造方法,Java将为该类创建一个默认的构造方法(无参构造方法)。默认构造方法自动地将所有的实例变量初始化为零。默认构造方法对简单的类是足够的,但是对更复杂的类它就不能满足要求了。 • 一旦我们在某个类中定义了自己的构造方法,默认的构造方法将不再被使用。

  22. 2、有参构造方法 • 带有参数的构造方法能够实现这样的功能:当构造一个新对象时,类构造方法可以按需要将一些指定的参数传递给构造方法。 • 如例5.5所示: Box(double l,double w,double h){ System.out.println("Constructing Box"); length = l; width = w; height = h; }

  23. 【例5.6】带参数的构造方法应用实例。 class Point{ int x; int y; Point(int x,int y){ // 用户自定义带参数的构造方法Point() this.x=x; this.y=y; } } public class PointDemo{ public static void main(String args[]){ Point p=new Point(10,20); System.out.print("类Point中的实例变量(x,y) = ") ; System.out.println("( "+p.x+","+p.y+" )"); } } 思考此处为什么要使用this?

  24. 类的构造方法中的形式参数名与成员变量名完全相同,这样在使用时会产生混淆。在Java语言中,定义了关键字this来解决这个问题。关键字this表示当前对象,可在引用当前对象的所有方法内使用。类的构造方法中的形式参数名与成员变量名完全相同,这样在使用时会产生混淆。在Java语言中,定义了关键字this来解决这个问题。关键字this表示当前对象,可在引用当前对象的所有方法内使用。 • 当然,这样使用this有时还是会引起混淆。所以一些开发人员比较小心,一般不使用和局部变量、正式的自变量同名的隐藏的实例变量。

  25. 但关键字this仍然有其用武之地。如在某个类中有多个构造方法时,一个构造方法可以调用另外一个构造方法,调用的格式是但关键字this仍然有其用武之地。如在某个类中有多个构造方法时,一个构造方法可以调用另外一个构造方法,调用的格式是 this(实际参数表); • 该语句的功能是调用与this(指当前对象)中参数匹配的构造方法。 • 在Java语言中,允许构造方法重载,即一个类可以有多个构造方法。

  26. 【例5.7】构造方法的重载。 class OverloadBox{ double length; double width; double height; OverloadBox(double l,double w,double h){ length = l; width = w; height = h; } OverloadBox(double x){ length = x; width = x; height = x; } double getVol(){ return length * width * height; } }

  27. public class OverloadConstructorBoxDemo{ public static void main(String args[]){ OverloadBox myBox1 = new OverloadBox(30,20,10); OverloadBox myBox2 = new OverloadBox(10); double vol; vol = myBox1.getVol(); System.out.println("第一个立方体的体积是: " + vol); vol = myBox2.getVol(); System.out.println("第二个立方体的体积是: " + vol); } } 使用构造方法并非只是为了给对象赋初始值方便,更重要的是,它是确 保一个对象有正确起始状态的必要手段。另外,通过使用非public的构 造方法,可以防止程序被其他人错误地使用与扩展。

  28. 5.2.4 类和成员的修饰符 • 前面的内容中,给出了定义类及其成员变量的通用格式,在这些格式中,都使用了修饰符(modifier),其目的是用来对类和成员的使用做某些限定。 • 在Java中,一般将修饰符分为两类: • 访问控制符:public、protected、private、package • 作用是给予对象一定的访问权限,实现类和类中成员的信息隐藏。 • 非访问控制符:abstract、static、final、native、synchronized、 volatile、 transient • 某些修饰符只能应用于类的成员,而某些修饰符既可应用于类,也可应用于类的成员。

  29. 修饰符的作用范围

  30. public修饰符 • public(公共)修饰符用来修饰类、类的成员变量和成员方法。 • 用public修饰的对象能被所有的类访问;public修饰的成员变量可以被项目文件中的任何方法所访问。 • 由于public成员变量不受限制,这易使类的对象引起不希望的修改,建议成员变量尽量不要使用public修饰符。public修饰的方法可以由其他类访问。

  31. protected修饰符 • protected(受保护)修饰符用来修饰类的成员变量和成员方法。 • protected修饰的成员变量和成员方法,可以被本类和它的子类以及同一个包中的其他类访问。 • private修饰符 • private(私有)主要用来修饰类的成员变量和成员方法。private修饰的成员变量和成员方法只能在本类中被访问到,而不能被任何其它类(包括子类)所引用。这种保护方式通常是最为安全的,也是对类进行封装时使用的主要方法。

  32. package修饰符 • package(包)修饰的变量,称为包变量。 • 通常省略package关键字,即没有修饰符的成员就是包成员。 • 包成员可以被本类及本类所在包中的其他类访问。

  33. abstract修饰符 • abstract(抽象)用来修饰类、类的成员方法。abstract修饰的类不能被实例化,它包含有未实现的方法,需要子类继承。abstract修饰的方法为抽象方法,无方法体。抽象类被派生、抽象方法被子类实现后才有实际意义。 • 注意: • 抽象方法只能出现在抽象类中。 • 不能用abstract修饰构造方法、静态方法和私有方法,也不能覆盖父类中的抽象方法,只有返回值类型、方法名、方法参数,而不定义方法体的方法

  34. final修饰符 • final(最终)修饰符用来修饰类、成员方法和成员变量。final的含义为终极或最终,它修饰的类不能被继承,即final类无子类。 • final修饰的成员方法不能被覆盖,即子类的方法名不能与父类中用final修饰的方法名相同。

  35. final修饰的成员变量称为最终成员变量。一开始创建该变量时将其设定了一个值,在以后程序的运行过程当中,变量的值将一直保持这个值不变。如final修饰的成员变量称为最终成员变量。一开始创建该变量时将其设定了一个值,在以后程序的运行过程当中,变量的值将一直保持这个值不变。如 • static final double PI = 3.14159; • final int COUNTER = 10; • 为final变量的所有字符选择大写是一个普遍的编码约定。声明为final的变量在实例中不占用内存。实质上,一个final修饰的变量就是一个常量。

  36. Java中的常量必须是类的成员。对于最终成员变量,任何赋值都将导致编译错误。因为常量在说明以后就不能改变其值,所以常量必须要使用变量初始化来赋初值。无论是实例变量,还是类变量,都可以被声明成常量。Java中的常量必须是类的成员。对于最终成员变量,任何赋值都将导致编译错误。因为常量在说明以后就不能改变其值,所以常量必须要使用变量初始化来赋初值。无论是实例变量,还是类变量,都可以被声明成常量。 • final修饰符和static修饰符并不冲突。但abstract和final绝对不能同时作为一个类的修饰符,因为abstract修饰的类必须要有子类继承,而final修饰的类为终极类,不能有子类继承。

  37. 【例5.8】常用修饰符的使用。 class Person{ private int a = 10; } class Teacher extends Person{ public int b =50; protected double c = 100.0; } public class ModifierDemo{ public static void main(String args[]){ Person p = new Person(); Teacher t = new Teacher(); int i,j; double k; * i = p.a; j = t.b; k = t.c; * System.out.println("In Person, value of a is: " + i); System.out.println("In Teacher, value of b is: " + j); System.out.println("In Teacher, value of c is: " + k); } }

  38. 上述程序中,加“*”的两条语句试图访问私有成员a将会报错。如果我们注释掉这两行,本例执行结果如下上述程序中,加“*”的两条语句试图访问私有成员a将会报错。如果我们注释掉这两行,本例执行结果如下 • In Teacher, value of b is: 50 • In Teacher, value of c is: 100.0 • 成员b由于被public修饰,其值一定可以访问;成员c由于被protected修饰,在其子类及本包中可以访问到。

  39. static修饰符 • static(静态)修饰符用来修饰类的成员变量和成员方法,以使它们成为静态成员(又称为类成员)。静态成员存储于类的存储区,属于整个类,而不属于一个具体的对象。因为静态成员属于整个类,所以它被所有该类对象共享。在不同的类对象中访问静态成员,访问的是同一个。 • 用static修饰的成员变量又称为类变量,不加static修饰的成员变量又叫实例变量。实例变量依附于具体的对象实例,它的值因具体对象实例的不同而不同,而类变量为该类的所有对象所共享,它的值不因类的对象不同而不同。

  40. 用static修饰的方法为静态方法,又叫类方法;无static修饰的方法为实例方法。类方法是该类的所有对象共享的方法。用static修饰的方法为静态方法,又叫类方法;无static修饰的方法为实例方法。类方法是该类的所有对象共享的方法。 • 对静态成员的使用一般应注意以下两点: • 静态方法不能访问属于某个对象的成员变量,而只能处理属于整个类的成员变量,即静态方法只能处理静态变量。 • 可以使用两种方式调用静态成员,它们的作用相同。 • 变量:类名. 变量名 或 类对象. 变量名 • 方法:类名 . 方法名() 或 类对象 . 方法名()

  41. 【例5.9】静态成员的使用。 class StaticDemo{ static int A=100; static int B=200; static void callMe(){ System.out.println("A = "+A); } } class StaticByName{ public static void main(String args[]){ StaticDemo.callMe(); // 不需要创建对象,通过类名直接调用静态方法 System.out.println("B = "+StaticDemo.B); // 通过类名直接调用静态变量 } }

  42. synchronized修饰符 • synchronized(同步)修饰符用于修饰成员方法或块。在多线程程序中,对用于共享的方法和块加以互斥锁,使得任一时刻,synchronized修饰的方法或块只能由一个线程执行或操作。使用synchronized主要用以设置同步机制,以实现线程的同步。 • 详见第10章

  43. native修饰符 • native(本地)修饰符一般用来声明用其它语言如C、C++、FORTRAN、汇编等书写方法体并具体实现方法功能的特殊方法。native修饰的方法为本地方法,即方法实现与本机系统有关。native方法可应用于实时性强、执行效率高、运行速度要求较高的场合。 • 除了以上介绍的修饰符外,Java还为我们提供了transient(过渡变量)、volatile(易失变量)等修饰符,有兴趣的读者可利用Java API文档进一步了解掌握。

  44. 5.2.5 类的使用 • 私有成员的访问 • 在Java程序设计过程中,为了降低类间的耦合性,提高代码的安全性,可以为类成员指定private修饰符。用private修饰表示该成员只能在该类内部被访问。若需要在其它类中访问私有成员,只有通过取数和送数等操作方法来访问。对于这样的方法,我们常为其命名为getXxx()和setYxx()等形式。

  45. 【例5.10】私有成员的访问。 • class Box{ • private double length; • private double width; • private double height; • Box(double l,double w,double h){ • length = l; • width = w; • height = h; • } • double getLength(){ • return length; • }

  46. double getWidth(){ return width; } • double getHeight(){ return height; } • } • public class BoxDemoFour{ • public static void main(String args[]){ • Box myBox = new Box(6,5,4); • double vol; • vol = myBox.getLength() * myBox.getWidth() * myBox.getHeight(); • System.out.println("立方体的体积是: " + vol); • } • }

  47. 2.方法参数是类的对象 • 在Java语言中,方法的参数类型除了是基本类型外,还可以是引用类型——类。在类的对象中实际存储为对象的引用,因此在调用类参数时方法间传送的是引用。尽管Java采用值传送,引用从调用方法单向传送到被调方法,但由于调用方法与被调用方法对应类参数的引用相同,它们引用同一对象。所以,若在被调方法中修改了引用类型形式参数的取值,则调用方法对应的实际参数也将发生相应的变化。即调用方法与被调方法之间是“引用单向传送,数据双向传送”。 • 应用引用类型的方法参数,可在方法间传递数据。

  48. 例5.11 引用类型的方法参数是方法间传送数据的桥梁。 • class Box{ • double length; • double width; • double height; • double vol; • Box(Box box){ • this.length = box.length; • this.width = box.width; • this.height = box.height; } • Box(double l,double w,double h){ • length = l; • width = w; • height = h; } • Box(){ // 用-1表示一个未初始化的Box对象 • length = -1; • width = -1; • height = -1; }

  49. Box(double edge){ • length = width = height = edge; } • double getVol(Box bx){ • bx.vol = bx.length * bx.width * bx.height; } • } • public class RefParameterBox{ • public static void main(String args[]){ • Box myBox1 = new Box(30,20,10); • Box myBox2 = new Box(); • Box myCube = new Box(10); • Box myClone = new Box(myBox1);

  50. myBox1.getVol(myBox1); • myBox2.getVol(myBox2); • myCube.getVol(myCube); • myClone.getVol(myClone); • System.out.println("Volume of myBox1 is: "+myBox1.vol); • System.out.println("Volume of myBox2 is: "+myBox2.vol); • System.out.println("Volume of myCube is: "+myCube.vol); • System.out.println("Volume of myClone is: "+myClone.vol); • } • }

More Related