• 1. 抽象、封装与类教材4章 抽象与封装 Java的类 类的修饰符 域 方法 访问控制符 类的设计
  • 2. 抽 象所有编程语言都提供“抽象”功能,编程语言所能解决问题的复杂程度取决于抽象的种类和质量。 汇编语言对计算机(机器语言)是一步很小的抽象。 过程化语言(高级语言)对于汇编语言的抽象迈了一大步,但所考虑的仍然是机器的结构而非问题的结构。 面向对象的方法为程序员提供了一种表示问题空间元素的全新的方法,而且不受问题类型的约束,更加贴近人的思维方式,是以要解决的问题中所涉及到的各种对象为主要考虑因素。
  • 3. 对 象问题空间元素→方法空间中的表示:对象 “对象”是现实世界的实体或概念在计算机逻辑中的抽象表示。 “对象”就象是一台小“计算机”: 对象有状态 对象有你要求它执行的操作 现实世界中的对象: 它们都有自己的状态 它们又都有自己的行为 程序中的对象 用数据域(静态属性)表示状态 用方法(动态属性)实现行为
  • 4. 对象与过程考虑对象 —考虑过程:前者更有意义 设计对象 —设计过程:前者更富挑战性,尤其是设计可重用的对象。 面向对象的程序设计和问题求解力求符合人们日常自然的思维习惯,降低分解问题的难度和复杂性,提高整个求解过程的可控制性、可监测性和可维护性,从而达到以较小的代价和较高的效率获得较满意效果的目的。
  • 5. 封 装“ 封装”是一种组织软件的方法。其基本思想是把客观世界中联系紧密的元素及相关操作组织在一起,使其相互关系隐藏在内部(信息隐藏),而对外仅仅表现为与其他封装体间的接口,从而构造出具有独立含义的软件实现。 面向对象的程序设计中提出了一种全新的封装方法-类。
  • 6. 封 装每个类里都封装了相关的数据和操作。 封装特性把类内的数据保护得很严密,模块与模块间仅通过严格控制的界面进行交互,它们之间耦合和交叉大大减少,降低了开发过程的复杂性,提高了效率和质量,减少了可能的错误,也保证了程序中数据的完整性和安全性。
  • 7. 封装-软件复用封装使得对象: 对内成为一个结构完整、可自我管理、自我平衡、高度集中的整体。 对外则是一个功能明确、接口单一、可在各种合适的环境下都能独立工作的有机的单元。 类的封装特性使得类可重用性大为提高,这样的有机单元特别适宜构建大型标准化的应用软件系统,可以大幅度地提高生产效率。
  • 8. 系统定义的类(类库):已实现的Java程序模块,对应特定的基本功能和任务,提供与JVM(Java虚拟机)的接口; 作用:由于类库良好的可重用性,能有效地提高编程的效率和质量; 用户程序自定义的类 作用:针对特定的问题定义自己需要的类。 Java 的类
  • 9. 基础类库(JFC) 简介java.lang包(核心类库,缺省加载) 包括基本数据类型、基本数学函数、字符串处理、线程、异常处理类等。 java.io包(标准输入输出类库) 包含各种实现I/O 操作的类,如基本 I/O 流、文件 I/O 流、过滤 I/O 流、管道 I/O 流、随机 I/O 流等。 java.applet 包(Applet 的工具类库) java.awt包(图形用户界面 GUI 的类库) 包括:低级绘图操作,如 Graphics 类;各种组件和布局管理类; 用户交互和事件响应,如 Event 类。 java.awt.event包(事件处理类库)
  • 10. 基础类库(JFC) 简介java.awt.image 包(图像处理类库) java.net 包(实现网络功能的类库) 包括:底层网络通信,如实现套接字通信的 Socket 类、ServerSocket类;实现基于网络协议(FTP、邮件服务等)的服务;访问网上资源和进行CGI网关调用的 URL 类等。 java.sql 包(数据库连接 JDBC 的类库) 可访问不同种类的数据库,如 Oracle, DB2, SQLServer 等。
  • 11. 系统类使用的三种方式继承 如:public class myApplet extends Applet 实例化对象 如:TextField text = new TextField (“Hello !”) ; 直接使用系统类,如使用类的静态属性、静态方法 如:System.out.println(“How are you !”) ;
  • 12. 用 户 自 定 义 类类定义 [修饰符] class 类名 [ extends 父类名] [ implements 接口名(,接口名 …)] { 域:对象的状态,包括变量、数组或其它对象; 方法:对象的行为,相当C 的函数; } public class MyJavaApplication{ public static void main(String args[]){ System.out.println("Hello, Java world! "); } }
  • 13. 创 建 对 象创建对象(类的实例化) 例:Button btn=new Button(“计算”); 格式: 类名 对象名 = new 构造函数(参数列表); 算符“.”(访问对象的属性): System.out、Sytem.in 等; 创建的每个对象都拥有自己的成员变量,保存各自的状态,表明拥有独立的内存空间。
  • 14. 创 建 对 象—分配空间基本数据类型——直接分配内存空间 int i,j,k ; 类类型 ,如何分配空间? 定义类(新的数据类型) class MyDate { int day ; int month ; int year ; }
  • 15. 创 建 对 象—分配空间 MyDate d1 ; MyDate d1 = new MyDate() ;nulld1day month year000d1.day = 8 ; d1.month = 8; d1.year = 2008 ;0x01abcdef
  • 16. 创 建 对 象—分配空间 MyDate d1 ; MyDate d1 = new MyDate() ;nulld1day month year8820080x01abcdefd1.day = 8 ; d1.month = 8; d1.year = 2008 ;
  • 17. 构 造 函 数功能: 类的特殊方法,完成对象的初始化工作; 特点: (1) 只能在创建对象时,在 new 算符后调用(由系统自动调用),如: Button btn = new Button( “计算”); (2) 方法名与类名相同; (3) 无返回值(包括空类型);
  • 18. 构 造 函 数特点: (4) 一个类可以有多个构造函数,用来完成不同的初始化任务。不同构造函数的形式参数个数、类型、顺序不同; class UsePoint { Point point_A=new Point(); Point point_B=new Point(5,7); } class Point { int x,y; Point() { x =0;y=0;} Point(int new_x,int new_y) { x=new_x, y=new_y;} }
  • 19. 构 造 函 数特点: (5)如用户未定义构造函数,系统会构造一个缺省的无参数空构造函数,不执行任何操作。 class Point { int x, y ; } class Test { public static void main (String[] args) { Point cp = new Point( ); System.out.println (“x= “+ cp.x+ “; y= “+ cp.y) ; } }
  • 20. 例4-1 定义一个电话卡类 class PhoneCard { long cardNumber; private int password; double balance; String connectNumber; boolean connected; boolean performConnection(long cn, int pw) {// 电话接入 if (cn == cardNumber && pw == password) { connected = true; return true; } else { connected = false; return false; } }
  • 21. 例4-1 定义一个电话卡类 double getBalance() // 返回卡内金额; { if (connected) return balance; else return -1; } void performDial() // 计费; { if (connected) balance -= 0.5; } } //类结束
  • 22. 例4-2 UsePhoneCard.java class UsePhoneCard { public static void main(String args[]){ PhoneCard myCard = new PhoneCard(888888,1111,100.0,"200"); System.out.println(myCard.toString()); } } class PhoneCard { long cardNumber; private int password; double balance; String connectNumber; boolean connected;
  • 23. 例4-2 UsePhoneCard.java PhoneCard(long cn, int pw, double b, String s) { cardNumber = cn; password = pw; if(b > 0) balance = b; else System.exit(1); connectNumber =s ; connected = false; } boolean performConnection(long cn, int pw) {// 电话接入 if (cn == cardNumber && pw == password) { connected = true; return true; } else { connected = false; return false; } }
  • 24. 例4-2 UsePhoneCard.java double getBalance() { // 返回卡内金额; if (connected) return balance; else return -1; } void performDial() {// 计费; if (connected) balance -= 0.5; } String toString() { String s = "电话卡接入号码:"+connectNumber + “\n电话卡卡号:”+cardNumber +“\n电话卡密码"+password +"\n剩余余额:"+balance; if (connected) return(s+"\n电话已接通。"); else return(s+"\n电话没有接通。"); } }//类结束
  • 25. 类 的 修 饰 符类的访问修饰符,如:public 类的非访问修饰符, 如:abstract, final 抽象类 (abstract class) 问题: 1)什么是抽象类? 2)为什么要使用抽象类?
  • 26. 定义:指不能直接被实例化的类,是一个抽象概念,在问题域没有对应具体对象,因此一般作为其它类的父类。 交通工具自行车汽车空中交通工具海上交通工具陆地交通工具客机运输机什么是 抽象类?
  • 27. 为什么要使用 抽象类?引例:求各种图形的面积。//已有两个类Circle和Rectangle, 求面积。 class Circle { int r; Circle(int r_in) {r=r_in;} int area() {return 3.14*r*r; } } class Rectange { int width,height; Rectangle (int w, int h) {width=w,height=h;} int area() {return width*height; } }
  • 28. 假设有若干个Circle、Rectangle,希望计算它们的总面积,简单方法是用两个数组分别记录这些对象,再采用两个循环完成计算。 问题:如果以后添加了其它形状,比如:triangle、ellipses等,上述方法的扩展性差,每一个图形都必须有自己的数组和循环。 扩展性、维护性良好的方案:一种统一的表示,用一个数组shape[],接受所有图形进行计算(现有的、及以后可能增加的图形)
  • 29. abstract class Shape{ abstract float area(); } class Circle extends Shape { int r; Circle(int r_in) { r=r_in;} float area() { return 3.14*r*r; } } class Square extends Shape { int width,height; Rectangle (int w, int h){ width=w,height=h;} float area() {return width*height; } }
  • 30. public class Test { public static void main(String args[]) { Shape[] shapes = new Shape[3]; shapes[0] = new Triangle(3,4,5); shapes[1] = new Rectangular(4,5); shapes[2] = new Circle(2); System.out.println(“三角形面积为 " +shapes[0].area()); System.out.println(“矩形面积为 " + shapes[1].area()); System.out.println(“圆形面积为 " + shapes[2].area()); } }
  • 31. 最终类(final class)最终类没有子类(在类的层次关系树中,最终类必定是叶结点); 功能:将类的内容、属性和功能加以固定(出于安全、性能等方面考虑)
  • 32. 抽象类与最终类抽象类 最终类PersonEngineerSecretaryCustomerEmployeeVipCustManagerDirector
  • 33. 域域:对象的状态(类的静态属性),可以是简单的数据类型变量、数组甚至其它类的对象; class PhoneCard { long cardNumber; int password; double balance; String connectNumber; boolean connected; } 域的分类: 对像的域:没有修饰符或者用final修饰符,创 建类的对象时分配空间,访问用对象名.域名。 类的域:用static修饰符
  • 34. 静态域(static)属于类,不属于具体对象; 保存在类内存区域的公共存储单元,当类加载时即可访问(此时没有创建对象,但分配了空间); 为类的所有实例共享; 静态域的访问 类名.域名 或:对象名.域名 object b char dataobject d char dataObject c char datastatic int share_dataobject a char data访问的是相同的内存单元!!
  • 35. 例4-4 TestStaticField.java class PhoneCard200 { static String connectNumber="200"; static double additoryFee; long cardNumber; int password; double balance; boolean connected; } class TestStaticField { public static void main(String[] args) { System.out.println(PhoneCard200.additoryFee); PhoneCard200 my200_1 = new PhoneCard200(); PhoneCard200 my200_2 = new PhoneCard200(); my200_1.additoryFee = 0.1; System.out.println(my200_2.additoryFee);} }
  • 36. 类的初始化-静态初始化器由关键字static引导的一对大括号括起的语句组,用来完成类的初始化的工作。 与构造方法的区别: 构造方法是对每个新创建的对象初始化,而静态初始化器是对类自身进行初始化; 构造方法是在用new运算符产生新对象时由系统自动执行,而静态初始化器则是在它所属的类加载入内存时由系统调用执行; 不同于构造方法,静态初始化器不是方法,没有方法名、返回值和参数列表。
  • 37. 例4-5 TestStatic.java class PhoneCard200 { static long nextCardNumber; long cardNumber; static { nextCardNumber=111111; } PhoneCard200(){ cardNumber = ++nextCardNumber; } } class TestStatic { public static void main(String[] args) { PhoneCard200 my200_1 = new PhoneCard200(); PhoneCard200 my200_2 = new PhoneCard200(); System.out.println(my200_1.cardNumber); System.out.println(my200_2.cardNumber); } }
  • 38. 最终域(final)最终域:用final 修饰符定义的域; final域的值不能被修改,相当于一个常量; final域要指定数据类型及其取值; 注:由于所有类对象的final域值都一样,为节省空间,final域通常被同时声明为static(静态域)。 例: static final String connectNumber=“200” ; 而: static String connectNumber=“200” ,是定义静态域,但可以修改。
  • 39. 方 法方法:具有一定功能又相对独立的模块(函数)(类的动态属性); 修饰符 返回值类型 方法名(形参列表)[throws 异常列表] { 方法体; } 方法分类: 一般方法:没有任何修饰符,创建类的对象时分配空间,访问用对象名.方法名。 构造方法:创建对象时自动调用,不能显示访问。 抽象方法:用abstract修饰 静态方法:用static修饰 最终方法:用final修饰 …
  • 40. 抽象方法(abstract Function)抽象方法:用abstract修饰,只有方法头,没有方法体; abstract void performDial(); 注:只能在抽象类中定义抽象方法(反之亦然) 目的:为所有子类定义一个统一的接口(即一个名字、返回值和参数列表完全相同,但具体实现可以不同的方法)。
  • 41. 静态方法(类方法)静态方法 被 static 修饰的方法,也称为类方法; 使用类方法不用创建类的对象。调用这个方法时,可 直接使用类名调用,而不需使用某个具体的对象名。 非static的方法是对象方法(或称实例方法)。 类方法中不能访问对象的域,而只能访问静态域(static 域)、类方法的参数及方法中定义的变量。 类方法中不能直接调用本类中的实例方法,但可以调用 其他的static方法。 静态方法的调用 类名.方法名(或对象名.方法名,不建议使用)
  • 42. 静态方法(类方法)main方法是静态方法,这是为了系统在没有任何实例化对象之前可以运行一个应用程序。 如果main方法要调用本类的其它方法: 将这些方法设计成静态方法, 创建对象,使用对象方法。
  • 43. Integer类静态域和静态方法静态域 static int MAX_VALUE 返回int型数据的最大值 static int MIN_VALUE 返回int型数据的最小值 构造方法 Integer(int value) Integer(String s) 其他方法 int intValue(); float floatValue(); String toString(); static String toString(int i) static Int parseInt(String s) static Integer valueOf(String s)静态方法
  • 44. 静态方法(类方法)例例4-8 TestStatic.java public class TestStatic { public static void main(String args[]){ Integer i = new Integer(25); System.out.println(i.intValue()*2); System.out.println(i.floatValue()); System.out.println("i="+i.toString()); System.out.println(Integer.parseInt("100")*2); System.out.println(Integer.valueOf("100").intValue()*2); System.out.println(Integer.MAX_VALUE); } }
  • 45. 最终方法(final Function)特点:内部语句不能被更改,在继承时不能被子类覆盖; 作用:防止子类覆盖父类的关键方法(出于安全、正 确性考虑); 注意:私有方法(private)、final 类中的所有方法 都缺省为 final 方法。
  • 46. 本地方法(native)作用:声明用其他语言书写方法体、并具体实现其功 能的方法; 目的(优点): 1)利用已有代码; 2)执行效率; 缺点:跨平台性受影响
  • 47. 访问控制符访问控制符是一组限定类、属性和方法是否可以被程序其他部分访问的修饰符 。 类访问控制符-public 公共类:public类名,表明它可以被其他所有的类访问(访问之前必需要用import公共类所在的包)。 一般类:无public修饰的类,只能被同一包中的类所访问;一个包中的类不用说明可相互访问(需要在类的定义前声明所在的包)。
  • 48. 类成员(域和方法)的访问控制一个类作为整体对程序的其他部分可见,并不能代表类内的所有域和方法也同时对程序的其他部分可见,前者只是后者的必要条件。 域和方法的访问控制符 public公共域和公共方法,可被任何类使用。protected可被同包中其他类使用。 可被子类继承(包括位于不同包中的子类)。无访问限定符可被同包中其他类使用。private只限在本类内使用。
  • 49. 类成员(属性和方法)的访问控制公共类(public)默认类类成员访问控制符publicprotected缺省privatepublicprotected缺省private可以访问类成员的区域AB+CBDBBBD
  • 50. 访问控制一般原则本包使用,采用缺省方式; 供其他包使用,采用public控制符; 为了使对象具有良好的封装性,可将类的实例变量设计成私有,但为了使其它类或对象能够访问私有实例变量,本类必须提供访问私有变量的方法(公共方法)。 按照惯例: 读私有变量的方法取名为get… 写私有变量的方法取名为set…
  • 51. 访问控制符例public class Employee { private String name ; private char sex ; private int age ; private float salary ; public Employee(String n,char x, int a, float s){ name = n ; sex = x ; age = a ; salary = s ; } public int getAge() { return age ; } public void setAge(int a){ age=a ;} public String getInfo() { return "姓名:" + name + " 性别:" + sex + " 年龄:" + age ; } void upSalary(float inc) { salary = salary + inc ; } }其他类不能访问, 子类也不能继承
  • 52. 访问控制符例public class Test { //与Employee在同一包中 public static void main(String[] args){ Employee emp = new Employee("赵兵",'男',28,1500.0F); System.out.println(emp.age); //该语句出错 emp.setAge(29) ; System.out.println(emp.getAge()); System.out.println(emp.getInfo()); emp.upSalary(500); } }
  • 53. 能共用的情况: public abstract class trans … public final class Socket … 不能共用的情况: abstract不能与 final 同时修饰一个类; abstract不能与private, static, final或native 并列修饰同一个方法; abstract 类中不能有 private 域或方法(无意义); static 方法不能处理非 static域。修饰符的共用
  • 54. 类的设计OOP一切都是围绕着类与对象展开的,OOP实际上是定义类和使用类的过程,即定义一些类,利用它们创建对象和操纵对象,通过各对象的相互作用来实现程序的功能。 设计原则:将数据及处理数据的代码封装在一起,保护内部数据,并提供对外操作的接口。 电梯类定义(没有体现封装的类定义) class BadElevator{ public boolean doorOpen=false; //表示电梯门的状态 public int floor = 1; //表示电梯停靠层数 public final int TOP_FLOOR=5; //定义电梯最髙层 public final int BOTTOM_FLOOR=1; //定义电梯最低层 }
  • 55. 电梯操作(操作BadElevator类的对象) public class test1{ public static void main(String[] args) { BadElevator e1 = new BadElevator(); //创建一个电梯对象 e1.floor--; // 到地下室了 e1.floor++; e1.floor=7; // 没有7层 e1.doorOpen=true; //通过改变对象属性值实现开门动作 e1.doorOpen=false; //关门 e1.floor=1; // 到第一层 e1.doorOpen=true; // 门开,住户上下电梯。 e1.floor++; // 门还没关,电梯就开了。 e1.doorOpen=false ; e1.floor-- ; e1.floor-- ; } } 类的设计对象自身没有保护, 这样操作会产生很多误动作
  • 56. 类的设计电梯类定义(体现封装的类定义) public class Elevator { private boolean doorOpen=false; //门的开关状态 private int floor =1 ; //电梯停靠层数 private int weight = 0 ; //表示当前乘客总重量 final int CAPACITY=1000 ; //电梯乘客重量上限 final int TOP_FLOOR=5 ; //电梯最高停靠层数 final int BOTTOM_FLOOR=1 ; //电梯最低停靠层数 // 以下是方法定义 public void openDoor() { // 开门方法 doorOpen=true ; //通过公共方法操作私有属性 } 属 性 定 义
  • 57. 类的设计public void closeDoor() { //关门方法,关门时检查是否超重 checkWeightSensors(); //调用测试重量的方法 if (weight<=CAPACITY) //如果没有超重 doorOpen=false ; //关门 else //如果超重,则不关门,且通过响声提示 for(int counter=0;counter<10;counter++) System.out.print((char) 7) ; //ASCII码7为beep }
  • 58. 类的设计private void checkWeightSensors() {// 检查超重的方法 //通过随机数模拟乘客重量 weight=(int) (Math.random()*1500) ; //显示乘客重量 System.out.println("乘客重量是: " + weight); } public int getFloor() { return floor ; } //取当前停靠层方法 public boolean isOpen() { return doorOpen ; } //判断开门方法
  • 59. 类的设计public void goUp() { // 上升一层的方法定义 if(!doorOpen) { if(floor
  • 60. 类的设计public void goDown() { // 下降一层的方法定义 if(!doorOpen) { if(floor>BOTTOM_FLOOR) { floor-- ; //如果门已关、且没到低层,才能下降。 System.out.println(floor) ; } else System.out.println("已在底层"); } else System.out.println("门没关!"); }
  • 61. 类的设计public void setFloor(int goal) {//指定停靠层的方法定义 if(goal>=BOTTOM_FLOOR && goal =TOP_FLOOR){ while(floor!=goal) { if(floor
  • 62. 类的设计电梯操作(操作Elevator类的对象) public class Test2 { public static void main(String args[]) { Elevator e2 = new Elevator(); e2.openDoor(); e2.closeDoor(); e2.goDown(); e2.goUp(); e2.goUp(); e2.openDoor(); e2.closeDoor(); e2.goDown(); 通过接口,对电梯的任何操作都不会导致误动作。
  • 63. e2.openDoor(); e2.goDown(); e2.closeDoor(); e2.goDown(); e2.goDown(); int curFloor = e2.getFloor(); if (curFloor!=5 && !e2.isOpen()) e2.setFloor(5); e2.openDoor(); e2.closeDoor(); e2.setFloor(10); System.out.println("测试结束 "); } } 信息隐藏-封装(电梯例)
  • 64. 小 结抽象与封装 Java的类 系统的类:系统类的使用方法。 自定义的类:构造函数;对象的创建与使用。 类的修饰符:abstract, final 域: static域,final域…… 方法: static方法,final方法,abstract方法,本地方法…… 访问控制符: 类的访问控制符,public 类的成员访问控制符:public,private,protected 类的设计:类的设计原则
  • 65. 作 业P95 4-4, 4-6, 4-7, 4-8, 4-9,4-10 P96 4-11, 4-12, 4-14,4-21