• 1. 第5章 包、接口和异常 (时间:3次课,6学时)
  • 2. 第5章 包、接口和异常 教学提示:Java将相关的类组成包,有助于大型软件系统的管理。接口的设计和调用也是Java程序设计的重要技术。对各种异常的处理是程序设计中要解决的重要问题。Java采用了一种特殊的机制来处理异常。 本章主要介绍:和类相关的两个概念:包、接口,同时在最后还将介绍Java对异常的处理方法。
  • 3. 第5章 包、接口和异常 5.1 包 5.2 接口 5.3 异常及其处理 5.4 创建自定义的异常 5.5 课后练习
  • 4. 5.1 包 5.1.1 Java 包的用途 5.1.2 访问包成员 5.1.3 源文件的布局 5.1.4 classpath参数
  • 5. 5.1 包尽管类具有强大的功能,但仅仅一个类或少量的几个类根本无法满足应用程序的需要。通常的应用程序可能需要几十个类,复杂的应用程序需要上百个、甚至更多的类。Java将相关的类组成包,有助于大型软件系统的管理。
  • 6. 5.1.1 Java 包的用途1. 包的建立方法 Java包通过package 语句建立,基本语法是: package<顶层包名>[.子包名]; 例如: package cn.edu.jmu.graphics; 在定义类或接口的源文件开始处,通过package 语句,可以将相应的类或接口放入package所声明的包里。包是相关类和接口的集合,提供了访问级别控制和命名空间管理。
  • 7. 5.1.1 Java 包的用途2. 包的使用方法 每个源文件只能有一个包声明,并且一定要求放在源文件的开始位置。如果一个源文件没有包语句,则源文件所定义的类或接口被系统放入默认包中。包有层次,层次间由点分隔。 通过创建和使用包,程序员不仅可以很容易地确定哪些类和接口是相关的,也可以很容易地找到提供特定功能的类和接口,例如,与画图有关的类和接口在graphics 包中。
  • 8. 5.1.1 Java 包的用途3. 包的访问权限 通过声明类的访问级别,可以控制对类的访问权限。 类的访问级别分为默认级和public 级。定义类的默认访问级别不需要任何关键字,被声明为默认级的类只对同一个包中的类是可视的。也就是说,只有同一个包内的类实例可以访问这个类,外界不能访问它。如果用关键字public 定义类,不但同一个包里的其他类可以访问这个类,其他包中的类也可以访问它。换句话说,同一个包中的类,相互之间有不受限制的访问权限。而在不同包中,只有public 类可被访问。
  • 9. 5.1.1 Java 包的用途除public修饰符之外,用于访问控制的修饰符还有protected和private。protected或private仅用来定义方法或变量的访问控制级别。protected方法或protected变量仅对同一个包内的类或不同包中的子类来说是可视的。private方法和private变量对外部定义的类均不可视。表5-1表示了访问控制修饰符的使用范围和相应访问级别。需要说明的是,通常不建议采用默认方式定义方法或成员变量的访问级别。
  • 10. 5.1.1 Java 包的用途表5-1 访问控制表
  • 11. 5.1.1 Java 包的用途4. 包的命名方式 包提供了新的命名空间,既使所定义的类使用与其他包中的类相同的名字,只要同名类所属的包不同名,就不会引起冲突。原因是这些类的全程限定名称不同。类的全程限定名包含了类的各层包名。这实质上是应用了面向对象的概念,将类封装入包中。 Java建议反转Internet域名为包名。如域名为:www.jmu.edu.cn,包命名可以cn.edu.jmu开始,例如建立包cn.edu.jmu.timer,创建类cn.edu.jmu.timer.Time。
  • 12. 5.1.2 访问包成员对于包来说,只有它的public 成员可被外界访问。若外界想要访问包的public 类,有3种方式可以实现。 (1) 通过类的全程限定名访问该类。 (2) 通过import 语句导入该类。 (3) 通过import 语句导入整个包。 如果某个类只被访问一次,那么可以直接使用类的全名。
  • 13. 5.1.2 访问包成员虽然可以用import 语句导入一个包,但是否可以访问包中的类,还取决于该类的访问级别。需要再次强调的是,只有包的public 成员才对外界是可视的,参见表5-1。 为了方便程序员开发,Java 运行时系统自动导入3个完整的包: (1) 默认包,默认包没有名字。 (2) java.lang包。 (3) 当前所用。
  • 14. 5.1.3 源文件的布局Java平台依靠分级文件系统管理Java源文件和字节码文件。Java源文件是以.java为扩展名的文本文件。每个源文件称为一个编译单元,每个编译单元中有一个或者多个类,但至多只能有一个public 类,并且源文件必须与public 类同名。源文件存放的文件目录映射着相应类所属的包。例如:类Rectangle 的文件名 Rectangle.java,这个文件将被放置在名为graphics 的子目录下。graphics 目录可以存在于文件系统的任意位置,如图5.1所示。
  • 15. 5.1.3 源文件的布局 图5-1 Rectangle.java源文件的目录
  • 16. 5.1.3 源文件的布局如果依据Java 的习惯,以反转的域名定义包的名字,如:cn.edu.jmu.graphics.Graphic类,源文件名为Graphic.java,其源文件目录如图5-2所示。 源文件经编译之后产生字节码文件,与源文件同名,扩展名为.class,如图5-3所示。 按照好的编程习惯,应该将.java文件和.class文件分列在两个相互对应的目录结构下,如图5-4所示。
  • 17. 5.1.3 源文件的布局 图5-2 Graphic.java源文件的目录
  • 18. 5.1.3 源文件的布局 图5-3 .java文件和.class文件
  • 19. 5.1.3 源文件的布局 图5-4 java文件和.class文件的布局
  • 20. 5.1.3 源文件的布局以这样的模式组织源文件和字节码文件,有益于Java的编译器和解释器确定用户程序中所用到的类和接口的位置。编译器在编译程序时必须能够准确找到程序中出现的类,并对这些类进行类型匹配和语法检查等工作。同样的道理,解释器在运行程序时也必须能够确定相应的字节码文件的位置,以调用这些类的方法。通过设置classpath 环境变量可以帮助编译器和解释器确定类或接口的源文件以及字节码文件的位置。
  • 21. 5.1.4 classpath参数classpath参数用于设置Java包所存在的顶级目录。也就是说,通过classpath可以为Java包建立所依存的目录列表。编译和运行Java程序时,系统会自动从classpath 环境变量中读取包所在的目录。文件所在目录由系统通过classpath 中的目录和package 语句定义的目录合成。
  • 22. 5.1.4 classpath参数【例5.2】下面通过一个完整的实例程序说明classpath参数的作用,同时展示源文件和字节码文件的一种建议布局模式。本例包含两个类Time 和TestTime,TestTime 为主类。程序对用户输入的表示小时、分钟和秒钟的3个整型数,经过数据正确性验证,分别转换为通用时间表示格式和标准时间表示格式,通过对话框显示给用户,运行结果如图5-5所示。
  • 23. 5.1.4 classpath参数 图5-5 运行结果(例5.2)
  • 24. 5.1.4 classpath参数文件布局方式如下:创建D:\JavaSample目录存放Java程序,创建D:\JavaSample\src子目录存放源文件,创建D:\JavaSample\class 子目录存放编译后的字节码文件。具体实现方式是将文件TestTime.java 存放在D:\JavaSample\src 子目录下,为使src 子目录的结构与class 子目录结构相对应,创建D:\JavaSample\src\cn\edu\jmu\timer 子目录存放 Time.java 文件。类Time 和类TestTime 的布局如图5-6所示。
  • 25. 5.1.4 classpath参数 图5-6 Time类和TimeTest类的布局
  • 26. 5.1.4 classpath参数Time.java中的语句: package cn.edu.jmu.timer; 将Time类放入包cn.edu.jmu.timer中,源文件Time.java存放在与包相对应的目录结构下。在TestTime.java中通过语句: import cn.edu.jmu.timer.Time; 导入Time 类。 需要设置classpath 参数,规定程序中的包cn.edu.jmu.timer 编译所依存的顶级目录为D:\JavaSample\class,如: set classpath = D:\JavaSample\class; 编译: javac –d d:\JavaSample\class d:\JavaSample\src\cn\edu\jmu\timer\Time.java javac –d d:\JavaSample\class d:\JavaSample\src\TestTime.java 运行: java TestTime
  • 27. 5.1.4 classpath参数用户输入的时、分、秒数,分别转换为通用时间格式和标准时间格式,通过对话框显示给用户,运行结果如图5-5所示。现给出这两个Java文件的源代码。 // Time.java package cn.edu.jmu.timer; import java.text.DecimalFormat; //用于数据格式化 // 24小时制时间 public class Time extends Object { private int hour; // 0 ~ 23 private int minute; // 0 ~ 59 private int second; // 0 ~ 59 // Time类构造器,初始化每个实例对象的值为0 // 确保每个Time对象处于一致的状态
  • 28. 5.1.4 classpath参数 public Time() { setTime( 0, 0, 0 ); } // 数据的正确性验证,对无效数据取0值 public void setTime( int h, int m, int s ) { hour = ( ( h >= 0 && h < 24 ) ? h : 0 ); minute = ( ( m >= 0 && m < 60 ) ? m : 0 ); second = ( ( s >= 0 && s < 60 ) ? s : 0 ); } //将通用时间格式转换为字符串 public String toUniversalString() { DecimalFormat twoDigits = new DecimalFormat( "00" ); return twoDigits.format( hour ) + ":" + twoDigits.format( minute ) + ":" + twoDigits.format( second ); }
  • 29. 5.1.4 classpath参数 //将标准时间格式转换为字符串 public String toString() { DecimalFormat twoDigits = new DecimalFormat( "00" ); return ( (hour == 12 || hour == 0) ? 12 : hour % 12 ) + ":" + twoDigits.format( minute ) + ":" + twoDigits.format( second ) + ( hour < 12 ? " AM" : " PM" ); } } // TestTime.java // TestTime类需要导入Time类 import Javax.swing.JOptionPane; import cn.edu.jmu.timer.Time; // import 语句导入Time类 public class TestTime { public static void main( String args[] ) {
  • 30. 5.1.4 classpath参数 Time t = new Time(); t.setTime( 13, 27, 06 ); String output = "Universal time is: " + t.toUniversalString() + "\nStandard time is: " + t.toString(); JOptionPane.showMessageDialog( null, output, "Packaging Class Time1 for Reuse", JOptionPane.INFORMATION_MESSAGE ); System.exit( 0 ); } }
  • 31. 5.1.4 classpath参数特别要强调的是,如果没有正确设置classpath 参数,那么TestTime.java在编译时会出现找不到Time 类的错误。Java编译器严格按照classpath和包名所指定的路径寻找包。只要指定的路径下没有所需要的文件,即使该文件就在当前目录,Java也会报告文件找不到的错误。这点对初学者来说需要特别注意。
  • 32. 5.2 接 口5.2.1 接口能够解决的问题 5.2.2 接口的定义 5.2.3 Comparable 接口 5.2.4 回调
  • 33. 5.2 接 口接口是和类很相似而又有区别的一种结构,接口的设计和调用也是Java程序设计的重要技术。从结构上,接口有如下特点。 (1) 接口用关键字interface来定义,而不是用class。 (2) 接口中定义的变量全是最终的静态变量。 (3) 接口中没有自身的构造方法,而且定义的其他方法全是抽象方法,即只提供方法的定义,而没有提供方法的实现语句。 (4) 接口采用多重继承机制,而不是采用类的单一继承机制。
  • 34. 5.2.1 接口能够解决的问题当类只从一个类继承时称为单继承,Java 语言只允许单继承。如果需要多继承关系,可以通过Java语言中的接口实现。 抽象方法只有方法定义,没有方法体。如果一个类包含任何抽象方法,包括直接的和继承所得,则这个类必须是抽象的。如果一个类是抽象的,则不能创建此类的对象。抽象类强制要求它的所有子类重写自己的方法以覆盖抽象方法。 如果存在超类Animal,显然Cat 同时具有Animal 和Pet 的特性。就是说Cat 不只是一个Animal,还是一个Pet,除需要继承Animal 类,还期望能实现Pet 类。因为Java 只允许单继承,Cat 不能既继承Animal 又继承Pet。解决问题的方法是定义接口,并通过接口实现多继承。
  • 35. 5.2.2 接口的定义 1. 接口声明 一个完整的接口声明如下: [public] interface interfaceName [extends listOfSuperInterface] { ... } 在接口声明中,只有关键字interface和接口名是必需的,其他内容是可选的。public用来指明任意一个类都可以调用此接口。如果一个接口声明中没有关键字 public,那么只有那些与本接口在同一个包中的类才能访问它。
  • 36. 5.2.2 接口的定义 2. 接口体 接口体包含常量定义和方法定义两部分。常量定义和变量定义在形式上类似,但常量名要求用大写字母表示。其格式如下: type NAME =value; 其中,type可以是Java的任何一种数据类型,接口中的常量全都默认为是final和static属性,即使常量定义中没有注上这两个字也是如此。但有些程序中为了使可读性好,仍然写明final static属性。
  • 37. 5.2.2 接口的定义 方法的定义格式如下: returnType methodName([para1, para2, ...]){...}; 其中,returnType表示返回值类型,如果没有返回值,则用关键字void指明。后面方括号中的内容是可选的,用来列出入口参数。入口参数可能有多个,之间用逗号隔开;如果没有入口参数,则可省去这部分内容。 由于接口中都用抽象方法,即只对方法作定义而不提供方法的实现语句,所以,接口的方法定义中没有方法体。接口中所有的方法都默认为是abstract属性。
  • 38. 5.2.2 接口的定义上述程序段定义了一个接口Bigable,内含一个常量SUM,另外包含3个方法,每个方法都指明了其返回值类型,但接口的方法中没有方法体。 【例5.5】对接口中定义的方法进行实现(例子详见书141~143页) 运行结果如图5-8所示。
  • 39. 5.2.2 接口的定义 图5-8 运行结果(例5.5)
  • 40. 5.2.3 Comparable 接口经常需要对数据集合中的对象进行比较,若要比较对象,需要实现java.lang.Comparable 接口。Comparable 接口具有惟一的方法compareTo(Object),其定义为: public interface Comparable{ public int compareTo(Object o); }
  • 41. 5.2.3 Comparable 接口实现Comparable 接口的类的所有实例对象之间应该互相可比较,并具备全序关系。这种全序关系采用类的自然排序规则。 在Java 2中有包括Character、File、Long、ObjectStreamField、Short、String、Float、Integer、Byte、Double、BigInteger、BigDecimal、Date、CollationKey 在内的23 个类实现了Comparable 接口。表5-2为其中8种基本数据类型的自然排序规则。虽然有一些类共用同一种自然排序规则,但只有相互可比较的类才能进行排序。
  • 42. 5.2.3 Comparable 接口表5-2 基本数据类型的自然排序规则
  • 43. 5.2.4 回调软件模块之间总是存在着一定的接口,通过接口形成相互调用关系。习惯上,常把调用者称为客户方,被调用者称为服务方。从调用方式上,可以把它们分为三类:同步调用、回调和异步调用,如图5-9所示,其中A 表示客户方,B表示服务方。
  • 44. 5.2.4 回调图5-9 软件接口间的三种调用方式
  • 45. 5.2.4 回调同步调用是一种阻塞式调用,客户方要等待服务方执行完毕才返回,它是一种单向调用。回调是一种双向调用模式,也就是说,服务方在被调用时也会调用客户方。 异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,服务方在收到某种信息或发生某种事件时,会主动通知客户方,即通过接口调用客户方。
  • 46. 5.3 异常及其处理5.3.1 什么是异常 5.3.2 异常的层次结构 5.3.3 异常的处理
  • 47. 5.3 异常及其处理对各种异常的处理是程序设计中要解决的重要问题。Java采用了一种特殊的机制来处理异常。本节讲述这种机制的思想,并结合具体例子讲解Java怎样用try-catch-finally语句实现这种机制。最后,简要说明怎样自定义异常类型以扩充Java系统的异常处理功能。
  • 48. 5.3.1 什么是异常 用任何一种计算机语言设计的程序在运行时都可能出现各种错误,常见的错误如除数为0、文件不存在、文件不能打开、数组下标超过界限、内存不够用等。对于这种在运行中出现的错误,计算机系统中通常有两种处理办法。 由计算机系统本身直接检测程序错误,遇到错误时使程序终止运行。 由程序员在程序设计中兼顾错误检测、错误信息显示和出错处理。 在Java程序中,异常一般由以下两种原因引起。 (1) 程序中存在非法操作,最简单的例子就是除数为0的除法操作,这种原因常常是程序员出于无意或大意造成的,所以称为隐式异常。 (2) 程序员在程序中使用了throw语句引起的异常。
  • 49. 5.3.2 异常的层次结构Java程序中的异常以类的层次结构组织。Throwable是所有异常类的父类,它是Object的直接子类。Exception和Error是Throwable的直接子类,而RuntimeException是Exception的子类。 在系统包java.lang、java.util、java.io和java.net中声明的异常类是标准异常类。这些标准异常类分为两种:一种是RuntimeException子类,因为RuntimeException是不可检测的异常类,所以这些标准异常类也是不可检测的异常类;另一种是除了RuntimeException子类以外的其他Exception的子类,这些异常类是可检测的。
  • 50. 5.3.2 异常的层次结构1. 不可检测的标准异常类 (1) java.lang中的标准异常类 ArithmeticException:表示遇到了异常的算术问题,例如被0整除。 ArrayStoreException:试图把与数组类型不相符的值存入数组。 ClassCastException:试图把一个对象的引用强制转换为不合适的类型。 IndexOutOfBoundsException:下标越界。 NullPointerException:试图使用一个空的对象引用。 SecurityException:检测到了违反安全的行为。
  • 51. 5.3.2 异常的层次结构(2) java.util中的标准异常类 EmptyStackException:试图访问一个空堆栈中的元素。 NoSuchElementException:试图访问一个空向量中的元素。 2. 可检测的标准异常类 (1) java.lang ClassNotFoundException:具有指定名字的类或接口没有被发现。 CloneNotSupportedException:克隆一个没有实现Cloneable接口的类。 IllegalAccessException:试图用给出了完整的路径信息的字符串加载一个类,但是当前正在执行的方法无法访问指定类,因为该类不是public类型或在另一个包中。
  • 52. 5.3.2 异常的层次结构InstantiationException:试图使用Class的newInstance 方法创建一个对象实例,但指定的对象没有被实例化,因为它是一个接口、抽象类或者一个数组。 InterruptedException:当前的线程正在等待,而另一个线程使用了Thread的interrupt方法中断了当前线程。 (2) java.io IOException:申请I/O操作没有正常完成。 EOFException:在输入操作正常结束前遇到了文件结束符。 FileNotFoundException:在文件系统中,没有找到由文件名字符串指定的文件。 InterruptIOException:当前线程正在等待I/O操作完成,而另一个线程使用Thread的interrupt方法中断了当前线程。
  • 53. 5.3.2 异常的层次结构当一个异常被抛出(即产生了异常)时,应该如何处理呢?在Java语言中,使用语句try-catch-finally 进行异常处理,程序流程从引起异常的代码转移到最近的try语句的catch子句,语句如下所示: try {...}//被监视的代码段 , 一旦发生异常 , 则交由其后的catch代码段处理 catch (异常类型 e) {...} catch (异常类型 e) {...} ... finally{...}//最终处理
  • 54. 5.3.2 异常的层次结构把可能会发生异常情况的代码放在try语句段中,利用try语句对这组代码进行监视。如果发生了异常,就交由catch语句处理。catch语句在执行前,必须识别抛出的异常是否为catch能够捕获的异常。如果catch语句参数中声明的异常类与抛出的异常类相同,或者是它的父类,catch语句就可以捕获任何这种异常类的对象。
  • 55. 5.3.2 异常的层次结构如果希望在异常发生时能确保有一段代码被执行,那么应该使用finally子句。这样即使发生的异常与catch所能捕获的异常不匹配也会执行finally子句。 【例5.8】使用finally举例,程序如下。 public class CatchDemo{ public static void main(String args[]) { System.out.println("这是一个异常处理的例子\n"); try{ int i=10; i/=0; } catch (ArithmeticException e){ System.out.println("异常是:"+e.getMessage()); } finally{ System.out.println("finally语句被执行"); } } }
  • 56. 5.3.2 异常的层次结构在JCreator中运行结果如图5-10所示。 图5-10 运行结果(例5.8)
  • 57. 5.3.3 异常的处理1. 异常的捕获 在5.3.2节的例子中,已经用了try-catch-finally语句块,下面介绍try-catch-finally语句各部分的用法。 捕获异常是通过try-catch-finally语句实现的。 try{...} catch( ExceptionName1 e ){...} catch( ExceptionName2 e ){...} finally{...} (1) try 捕获异常的第一步是用try{…}选定捕获异常的范围,由try所限定的代码块中的语句在执行过程中可能会生成异常对象并抛出。 (2) catch 每个try代码块可以伴随一个或多个catch语句,用于处理try代码块中所生成的异常事件。catch语句只需要一个形式参数指明它所能够捕获的异常类型,这个类必须是Throwable的子类,运行时系统通过参数值把被抛出的异常对象传递给catch块。
  • 58. 5.3.3 异常的处理(3) finally 捕获异常的最后一步是通过finally语句为异常处理提供一个统一的出口,使得在控制流转到程序的其他部分以前,能够对程序的状态作统一的管理。不论在try代码块中是否发生了异常事件,finally块中的语句都会被执行。
  • 59. 5.3.3 异常的处理2. 异常的抛出 在异常发生时,可以对它进行捕获,也可以将它继续抛出。 【例5.11】对异常进行抛出举例,程序如下。 class CatchDemo2 { Public static void main(String args[]) throws ArithmeticException, ArrayIndexOutOfBoundsException { int a=args.length; System.out.println("\na="+a); int b=42/a; int c[]={1}; c[42]=99; } }
  • 60. 5.4 创建自定义的异常 Java提供的一些异常有时候不能满足编程的需求,比如规定用户输入数据的范围在20到30之间,但是Java并没有这个方面的异常。这个时候就可以应用自定义的异常来规范化客户的数据输入。 在Java中进行自定义异常时,自定义异常类必须是Throwable的直接或间接子类。下面的例子是关于自定义异常的。它通过继承Exception类而继承Throwable,即间接继承Throwable。
  • 61. 5.4 创建自定义的异常 【例5.12】自定义异常举例,程序如下。 class OutBoundsException extends Exception { OutBoundsException(String mes) { //调用超类的构造函数 super(mes); } } class check { String ChecktheNum(int n) throws OutBoundsException { Integer N=new Integer(n); if(n>30||n<20) throw new OutBoundsException("the number is out of bound!!"); else return "the number"+N.toString()+"is in the bound!!"; } } class Test
  • 62. 5.4 创建自定义的异常{ public static void main(String []args) { try { check c=new check(); System.out.println("以下是合法的数据的报告!"); System.out.println(c.ChecktheNum(25)); System.out.println("以下是非法的数据的报告!"); System.out.println(c.ChecktheNum(5)); } catch(OutBoundsException e) { System.out.println(e.toString()); } } } 运行结果如图5-13所示。
  • 63. 5.4 创建自定义的异常 图5-13 运行结果(例5.12)
  • 64. 5.5 课 后 练 习1. 填空题 (1) 声明接口的保留字是__________。 (2) 类的声明“public class Test extends Applet implements Runable{}”中,定义的类名是__________,其父类是__________;实现了__________接口。这个类的源程序必须保存为__________(写出包括扩展名的文件名)。 2. 选择题 (1) 接口是Java面向对象的实现机制之一,以下说法正确的是( )。 A. Java支持多重继承,一个类可以实现多个接口 B. Java只支持单重继承,一个类可以实现多个接口 C. Java只支持单重继承,一个类只可以实现一个接口 D. Java支持多重继承,但一个类只可以实现一个接口 (2) 关于接口的定义和实现,以下描述正确的是( )。 A. 接口定义中的方法都只有定义没有实现 B. 接口定义中的变量都必须写明final和static C. 如果一个接口由多个类来实现,则这些类在实现该接口中的方法时应采用统一 的代码 D. 如果一个类实现一个接口,则必须实现该接口中的所有方法,但方法未必声明 为public.
  • 65. 5.5 课 后 练 习3. 判断题 (1) 对每个异常,只能进行捕获。 ( ) (2) 接口中定义的方法可以是private型的。 ( ) 4. 简答题 (1) 按照Java习惯,程序员应该如何组织和命名包?如何布局源文件? (2) 设置classpath 参数的作用是什么? 5. 操作题 (1) 根据如图5-14所示的UML图设计完成编码TestAnimal.java,使输出结果符合样例: Fish swim in their tanks all day. Fluffy likes to play with string. Spiders catch flies in their webs to eat. This animal walks on 8 legs. This animal walks on 0 legs. Fish, of course, can't walk; they swim.
  • 66. 5.5 课 后 练 习(2) 编写MyPoint.java,定义点的数据结构为两个双精度数[x,y]并重写toString 方法,通过字符串连接运算,使输出点形式为: start point is start[x,y] end point is end[x,y] (3) 编写TestMyPoint.java,实例化MyPoint 为start 和end,输出start 和end 的状态。 (4) 编写方法distance()计算两点间的距离。
  • 67. 5.5 课 后 练 习 图5-14 UML图
  • 68. Q & A? Thanks!