-
- 素材大小:
- 2.37 MB
- 素材授权:
- 免费下载
- 素材格式:
- .ppt
- 素材上传:
- lipeier
- 上传时间:
- 2019-01-11
- 素材编号:
- 221754
- 素材类别:
- 课件PPT
-
素材预览
这是ibm公司java培训ppt,包括了Java语言的发展历史,Java语言的主要特性,Java程序相关问题,Java程序的开发环境,Java程序的开发过程等内容,欢迎点击下载。
ibm公司java培训ppt是由红软PPT免费下载网推荐的一款课件PPT类型的PowerPoint.
第一章 Java语言概述 华中科技大学IBM技术中心 2008 主要内容提要 Java语言的发展历史 Java2 的版本划分 Java语言的主要特性 Java程序相关问题——Java虚拟机 Java虚拟机——在真实机器中用软件模拟实现的一种抽象的机器。(Java虚拟机规范) Java虚拟机主要由五个部分组成:指令系统、寄存器、栈、存储区、碎片回收区 解释和执行Java程序编译后产生的字节码 Java程序相关问题——Java API Java API是Java系统提供的预先定义好的软件组件的集合,它们提供了许多可供程序员调用的常用功能 丰富的API为程序员提供了极大的方便,但也是学习的难点 要学会使用Java API手册(The Java 2 Platform API Specification ) http://java.sun.com/j2se/1.5/docs/api/index.html Java程序相关问题—— Java程序的运行机制 Java程序相关问题——Java程序类型 Java应用程序(Java Application) 是独立完整的程序 在命令行调用独立的解释器软件即可运行 主类必须有main方法,这也是程序的入口 Java小程序 Java Applet——是指在客户端运行的Java小程序,一般来说客户端是指用户所使用的浏览器 Java Servlet——是在服务器端执行的Java小程序,为了能够支持Servlet的运行,服务器端必须安装包含Java虚拟机的服务器软件,这种能够支持服务端小程序的服务器一般被称为应用服务器 Java开发环境 JDK/J2SDK(Java Developer Kit) JDK1.02 JDK1.1.x JDK1.2/J2SDK1.3/J2SDK1.4/JDK5.0(J2SDK1.5) Java集成开发环境(IDE) NetBeans JBuilder Eclipse JCreator Forte for Java Visual J++ WSAD …… JDK的安装与设置 从http://java.sun.com/可以下载相关版 本的JDK(本课程采用J2SDK1.3以上版本) 在Windows平台上运行安装程序,以安装JDK 设置PATH(文件路径)参数。由于JDK提供的实用程序都在安装目录下的子目录bin下,为了能在任何目录下直接使用文件名调用这些程序,必须设置操作系统的文件路径参数 环境设置 在Windows环境下,为了快速进入指定目录的命令行窗口,可在注册表中增加项目: [HKEY_CLASSES_ROOT\Directory\shell\进入命令行\command] 默认值设为: cmd /k "cd %1" JDK的目录结构 JDK实用程序简介 javac:Java编译器,将Java源代码编译为字节码; java:Java解释器,用来解释执行Java程序的字节码文件; appletviewer(小程序浏览器):一种执行HTML文件上的Java小程序类的Java浏览器; javadoc:根据Java源代码及其说明语句生成的HTML文档; jdb:Java调试器,可以逐行地执行程序、设置断点和检查变量; javah:产生可以调用Java过程的C过程,或建立能被Java程序调用的C过程的头文件; javap:Java反汇编器,显示编译类文件中的可访问功能和数据,同时显示字节代码含义。 Java程序的开发过程 编辑源代码 编译源代码文件 运行程序 Java程序的开发过程——编辑源代码 一般情况下,我们可以使用系统平台下的任何文本编辑器进行源代码的编辑,在Windows平台下常用的是Window系统自带的“记事本”程序或“写字板”程序 Java源码大小写敏感 Java源码文件的扩展名:.java Java源程序文件也不能随意命名,其文件名必须与程序中主类的类名完全相同,包括大小写在内 Java程序的开发过程——编译源代码 使用JDK实用程序javac对源代码文件进行编译 C:\MyJava>javac MyFirstJavaApp.java 如果系统提示符再次出现并且没有任何消息产生,那么编译便成功了 如果有系统报错消息产生,则表示程序编译出错,程序员必须阅读报错信息,并根据这些信息对程序进行修改 程序成功编译后,在与源代码文件同一目录下会生成一个新的文件,其文件名与源代码文件名相同,扩展名为“.class”。这个文件就是源代码文件编译产生的程序字节码文件 MyFirstJava.class Java程序的开发过程——运行程序 要执行一个Java程序非常简单,只需在字节码文件所在目录下输入下列命令就可以了: java 字节码文件名 第2章 面向对象的编程概念 华中科技大学IBM技术中心 2006 主要内容提要 面向对象 vs. 面向过程 面向对象(OOP)——Object-Oriented Programming 用类class封装数据以及与数据相关的操作 用类的继承性来实现类的重用性 多态性 面向“对象”,由对象提供服务 面向过程(POP)——Procedure-Oriented Programming 以功能为组织单元 通过数据结构来描述具体的问题 数据在功能(函数)之间以参数的形式被传送 现实世界中的对象 现实世界是由对象构成的 现实世界中任何实体都可以看作是对象 现实世界中的对象有两个共同特征: 状态 行为 软件对象(Object) 软件对象是现实世界对象的抽象 软件对象同样具有状态和行为 定义:对象是变量和相关方法的软件组合 现实对象→软件对象 封装(Encapsulation) 封装性体现了面向对象程序设计的一个特性,将方法和数据组织在一起,隐藏其具体实现而对外体现出公共的接口 模块化 隐藏信息 消息(Message) 复杂的行为必须通过对象之间的交互来实现 软件对象与其它对象进行交互与通讯是通过互发消息来实现的 消息的组成 消息的目的对象 要执行的方法的名称 方法所需参数 消息的性质 同一对象可接收不同形式的多个消息,产生不同的响应 同一个消息可以发给不同的对象,所做出的响应可以截然不同 发送方不需要知道接受方如何对请求予以响应的 类(Class) 定义:类是蓝图或原型,它定义了所有某种类的对象的共有的变量和方法 类是具有共同属性和行为的对象的抽象与集合 实例(Instance) 定义:特定类所描述的一个具体对象 对象、类与实体的关系 继承(Inheritance) 广义地说,继承是指能够直接获得已有的性质和特性,而不必重复定义它们。在面向对象的软件技术中,继承是子类自动地共享父类中定义的数据和方法的机制。 单重继承与多重继承 单重继承:一个子类只有一个唯一确定的父类 单重继承所构成的类的关系结构是一棵树 多重继承:一个子类可以有多个不同的父类 多重继承所构成的类的关系结构是一个格 Java语言仅支持单重继承 继承的作用 使软件系统具有开放性 更好地进行抽象与分类 实现代码的复用 提高可维护性 类型(Type) 在面向数值的编程中,类型通常用作数据的表示。在Java这样的强类型语言中,在编译期,每一个变量和表达式都有一个类型与之相对应 Java中的类型:基本类型、类、接口 接口(Interface) 接口和类一样也是一种类型,也同样包含一些方法的定义。但与类不同的是:接口中所定义的所有方法都是抽象方法(即没有实现的方法)。 接口中所定义的方法由实现(implement)该接口的类来实现,一个类可以同时实现多个接口 接口机制使Java的面向对象编程变得更加灵活。解决了单重继承带来的问题 接口定义了对象的行为模型,相当于一个协议。实现接口的各个类负责实现接口所定义的行为。虽然实现细节各不相同,但对用户来说是一样的行为。 面向对象的示例 本例中包含很多对象:点、窗口、颜色、点击事件…… 代码:ClickMeApp.java , ClickMe.java,Spot.java Spot类 Spot对象 示例中的消息 示例中的继承和接口 第三章 Java语言基础 华中科技大学IBM技术中心 变量(Variable) 对象将它的状态存储在变量中 定义: 变量是一个由标识符命名的数据项 变量名必须是一个合法的标识符 --一个以字母开头的无限制的Unicode字符序列。 变量的声明: 类型 名称[ = 初始值]; int i; double pi = 3.1415926; String name; 数据类型 每个变量都必须有一个数据类型. 一个变量的数据类型决定了它能容纳的值和在它上面可以进行什么操作。 Java编程语言有两大类数据类型: 原始类型(primitive) 引用类(reference) Java的数据类型 原始类型 原始类型变量包含单个值,其大小和格式与它的类型匹配:数字、字符或布尔值。 Java语言没有unsigned类型 0xFFFF和0xFF谁大? Java语言必须强制类型转换 float f = 0.1; boolean b = 1; 引用类型 数组,类和接口就是引用数据类型.与原始类型变量的值不同的是,引用类型变量的值是对应变量代表的一个值或一组值的引用(也就是其地址) 在其他语言里引用被称为指针或者内存地址。Java不支持显示地使用地址,而是使用变量的名称代替。 变量的引用 通过变量名引用变量的值 简单名称:由单个标识符组成的名称 限定名称:通过类名或对象名引用改类或对象中的成员变量 System.out.println(i+spot.x); 作用范围 变量的作用范围是可以通过简单名称引用该变量的程序区域 作用范围也决定了系统为该变量创建和释放内存的时间 例子 最终变量 你可以在任意范围里将一个变量定义为最终变量(final) 最终变量的值一经初始化就不能改变 类似于C语言中的常量(const) 操作符、表达式、语句和块 第四章 对象基础和简单数据对象 华中科技大学IBM技术中心 主要内容 对象的生命周期 CreateObjectDeom 对象的创建 声明一个变量来引用对象 为了声明一个变量来引用对象,你可以使用类或者接口的名字作为变量的类型 声明并没有创建新对象。在对该引用变量赋值前,该引用为空,称为空引用(null) 实例化对象 new操作符通过为新对象分配内存来实例化一个类 new操作符需要一个后缀参数,即构造器的一个调用 new操作符返回一个对它所创建对象的引用,通常该引用被赋值给具有适当类型的引用变量 如果new操作符返回的引用没有被赋给任何变量,那么当new操作符所在的语句执行完后,将无法访问该对象 初始化对象 构造器(Constructor):是一个用来创建对象的特殊方法,用来初始化对象的属性。 构造器的名字与类名相同 构造器没有返回值 构造器所包含的语句用来对所创建的对象进行初始化 没有参数的构造器称为“无参构造器” 每个Java类都至少有一个构造器,如果该类没有显式地声明任何构造器,系统会默认地为该类提供一个不包含任何语句的无参构造器 对象创建的实例 问 题 构造器的重载(Overload) 一个类可以包含多个构造器,这种情况成为构造器的重载 同一个类中的多个构造器通过参数的数目及类型的不同来区分 对象的使用 对象的使用有两种方式 操作或者检查它的变量 调用它的方法 要使用对象的实例成员,首先需要得到该对象的引用 实例成员与类成员 实例成员包括实例变量与实例方法 实例成员依赖于实例存在 同一个类的不同实例都拥有一份实例变量的拷贝,对某个实例的实例变量的操作不影响到其它实例 实例变量遵循对象的生命周期,随着对象的创建而创建,随着对象的消亡而消亡 必须通过实例的引用来调用实例方法 类成员包括类变量与类方法 类成员不依赖于实例存在 同一个类的不同实例共享同一个类变量,对类变量的改变会影响到所有实例 类变量的生存期不依赖于对象,其它类可以不用通过创建该类的实例,直接通过类名访问它们。同样,类方法也可以直接通过类名访问。 实例成员与类成员 实例变量的引用 简单名称 当实例变量处在作用域内(即对象的类的代码内) 的时候 限定名称 objectReference.variableName 当实例变量处在作用域外时使用限定名称 关于变量访问的说明 建议不要通过其它对象或类直接操作对象的变量,可能引起无效值 理想情况下,类会提供一些方法,其他对象可以通过他们检查或修改变量,确保值有效,而且如果变量的类型和名称发生了变化,不会影响它的使用者 在某些情况下,可以允许对对象变量的直接访问,以使类更小更简单,也可使变量适用于更广泛范围; JAVA编程语言提供了一个访问控制机制,通过这种机制,类可以决定那些其它的类可以直接访问它的变量(第五章中介绍)。 调用对象的方法 使用限定名称来调用对象的方法 objectReference.methodName(argumentList); 或者 objectReference.methodName(); 关于方法调用 方法被声明为public,就可以被任何其它的类所访问。有时,类需要限制对它的方法的访问 类可以使用与控制变量访问相同的机制来对它的方法进行访问控制(第五章中介绍) 对象的清除 JAVA运行时环境在当对象不再被使用的时候清除它们,这个过程就是所谓的“垃圾收集”(garbage collection) Java的垃圾收集器自动扫描对象的动态内存区,对被引用的对象加标记,然后把没有引用的对象作为垃圾收集起来并释放。 垃圾收集器作为一个线程运行。当系统的内存用尽或程序中调用System.gc()要求进行垃圾收集时,垃圾收集线程与系统同步运行。否则垃圾收集器在系统空闲时异步地执行。 无用对象的判定 当某个对象不在被任何引用变量引用时,该对象是无用对象,将被清除。一般有如下两种情况: finalize()方法 在对对象进行垃圾收集前,Java运行时系统会自动调用对象的finalize()方法来释放系统资源。 某些情况下,程序员可能需要实现该方法来释放不由垃圾收集器所控制的资源。但这种情况非常少见 finalize()方法是在Object中有缺省实现,在用户自定义的类中,它可以被覆盖,但一般在最后要调用父类的finalize()方法来清除对象所使用的所有资源 问题一 下列程序的运行结果? 问题二 现有一个Point和Rectangle对象,代码执行后有多少引用指向它们?有没有对象需要垃圾收集? 字符和字符串 Java API提供了三个处理字符数据的类: Character:这个类的实例可以容纳单一的字符数值。该类还定义了一些简洁的方法来操作或者检查单一字符数据。 String:这个类用于处理由多个字符组成的不可变数据。 StringBuffer:这个类用于存储和操作由多个字符组成的可变数据。 字符类(Character) 字符类的对象包含单个字符值 当需要使用对象时,可以用字符对象替代原始的char类型的变量 字符类——构造器和方法 Character(char)-Character类唯一的构造器,它创建一个字符对象,其中包含由参数提供的值,一旦创建了Character对象,它包含的值就不能改变。 compareTo(Character)-这个实例方法比较两个字符对象包含的值,这个方法返回一个整数值,表示当前对象中的值是大于、等于还是小于参数所包含的值 字符类——构造器和方法 equals(Object)-这个实例方法比较当前对象包含的值与参数对象包含的值,如果两个对象包含的值相等,那么这个方法返回true toString()-这个实例方法将此对象转换为字符串 charValue()-这个实例方法以原始char值的形式返回此字符对象包含的值 isUpperCase()-这个实例方法判断一个原始char值是否是大写字母 字符类——例程 字符类——类方法 问题 字符串和字符串缓冲区 Java平台提供两个类String和StringBuffer,它们用于存储和操作字符串-由多个字符组成的字符数据。 String类用于其值不能改变的字符串; StringBuffer类用于被修改的字符串,通常用来动态的构造字符数据。 字符串是常量,比字符串缓冲区更高效,而且字符串可以被共享。 字符串(String) 使用字符串常量时,需要创建String对象,和其它对象不同,String对象可以通过简单赋值语句创建: String name = “Petter”; 此外,也可根据String类的构造函数创建String对象: String name = new String(“Petter”); 对于程序任何位置出现的双引号标记的字符串,系统都会自动创建一个String对象。 可通过String对象的方法对字符串进行操作 字符串——构造器 字符串的不可变性? String类用于其值不能改变的字符串 观察下列程序: 字符串的不可变性? 字符串缓冲区(StringBuffer) String对象表示的是不可更改的字符串对象,如果需要修改String对象所表示的内容,必须重新创建一个对象: String str = “Petter”; str = str + “ & Bob” + “ & Tom”; 当修改操作频繁,或字符串的值很大时,会额外分配大量内存 因此,Java语言引入了一个StringBuffer类,用来表示内容可以扩充和修改字符串对象 StringBuffer——构造器 必须使用new操作符创建字符串缓冲区 访问器方法 用于获取关于对象的信息的方法被称为访问器方法。 字符串和字符串缓冲区都可以使用的一个访问器方法就是length方法。 length方法返回字符串和字符串缓冲区中包含的字符数。 容量 在StringBuffer类中还有一个capacity()方法,它返回分配给这个字符串缓冲区的容量,而不是使用量。使用量会改变,但是容量始终是不变的。 通过索引得到字符 charAt()访问器方法,通过索引从字符串或者字符串缓冲区得到字符,索引值从零开始。 substring方法 如果要从字符串或者字符串缓冲区得到多个字符,可以使用substring方法。 String substring(int) String substring(int,int) search string类提供两个访问器方法,返回特定的字符或者子字符串在字符串中的位置。 indexOf()方法从字符串的开头查找; lastindexOf()方法从字符串的末尾查找; stringBuffer类不支持indexOf()和lastindexOf()方法。 search search example public class Filename { private String fullPath; private char pathSeparator, extensionSeparator; public Filename(String str, char sep, char ext) { fullPath = str; pathSeparator = sep; extensionSeparator = ext; } public String extension() { int dot = fullPath.lastIndexOf(extensionSeparator); return fullPath.substring(dot + 1); } public String filename() { int dot = fullPath.lastIndexOf(extensionSeparator); int sep = fullPath.lastIndexOf(pathSeparator); return fullPath.substring(sep + 1, dot); } public String path() { int sep = fullPath.lastIndexOf(pathSeparator); return fullPath.substring(0, sep); } } search example 比较字符串和字符串缓冲区 操作字符串 修改字符串缓冲区 数字类 Number类及其子类主要用于处理数字 Number类的对象包含了原始类型的数值并且提供了一些有用的变量和方法,用于对数值进行处理 类型包装器类(Type-Wrapper class) 数字类、Boolean、Character和void类统称为类型包装器类 在需要对象的地方,可将原始类型的值存储在类型包装器对象中 这些类定义了一些有用的变量,提供关于数据类型的一般信息 这些类还定义了一些有用的方法,用于将值转换为其他类型、转换为字符串等等 这些类用于反射,反射这种java机制允许程序收集关于JVM中任何对象或类的信息 此外,BigInteger和BigDecimal还扩展了原始数据类型 例程 数字的转换、格式化、高级算术功能 数组 数组是一个固定长度的结构,它存储多个相同类型的值 数组直接被JAVA语言所支持,所以没有一个数组类 数组的长度在数组创建的时候就已经确定。 数组元素就是数组中的一个数值,可以通过数组中的位置来访问它。 创建数组 声明一个引用变量来引用一个数组 格式:type[] 引用变量名 type 引用变量名[] (允许但不推荐) 数组变量的声明并不创建数组 创建一个数组 使用new操作符显示地创建数组 格式:new elementType[arraySize] 数组初始化器 可以使用简写的语法创建并初始化数组: type[] 引用变量名 = { 数组元素值…}; 使用数组 访问数组元素 引用变量名(数组名)[index] 得到数组大小 引用变量名(数组名).length 例程 对象数组 数组元素可以是基本类型也可以是引用类型 当数组元素是引用类型时(也即数组元素为对象时需要注意:数组元素也必须要被创建和初始化 数组的数组 数组的数组可以看作是“数组引用”的数组 与对象数组一样,必须显示地在数组中创建子数组 子数组的长度并不相同 例:int[ ][ ] aMatrix = new int[4][ ]; …… aMatrix[1] = new int[5]; aMatrix[2] = new int[10]; 复制数组 例程 问题 第六章 接口和包 华中科技大学IBM技术中心 主要内容提要 接口 vs 抽象类 接口不可以实现任何方法,而抽象类可以; 类可以实现多个接口,但父类仅只有一个; 接口和继承无关,不是类层次结构的一部分。无关的类可以实现相同接口。 定义接口 完整的接口定义规范 实例 定义一个股票监视器。一旦股票价格变化,立即通知观察者watcher。 Watcher是一个接口,它只有一个方法,valueChanged知道股票变化的类必须实现此方法。从而必须实现StockWatcher接口 不仅仅是StockMointer的超类,其它类只要实现此接口,就可以享受股票价格变化通知服务。 实例 接口功能不能简单扩大 例如:要加个报股价的方法在接口里,此时所有实现它的类不能正常工作。 用继承来扩大接口 如果需要增加接口的功能,可以利用继承来实现: 问题 实现java.util.Iterator接口的类必须实现哪些方法? Next, hasnext and remove 下面的接口有什么错误? 问题 如何更正上面接口的错误? 下面的接口是正确的吗? Java语言的包 引入的原因: 容易找到和使用类 避免名称冲突 控制访问 定义:包是一个相关的类和接口的集合,它可以提供访问保护和名称空间管理。 Java语言的包 Java平台中的类和接口是各种包的成员,这些类和接口是按照功能绑定的; 例如:基本的类在java.lang中; 再例如:用于输入和输出的类在java.io中。 使用包成员 只有公共的包成员可以从定义它们的包外访问,要从包外访问公共的包成员,必须采用以下的方法: 用成员的限定名引用; 导入包成员; 导入成员所属的整个包。 使用包成员 使用包名作为类名前缀 : java.util.Vector vc = new java.util.Vector() 加载需要使用的类 import java.util.Vector; …… Vector vc = new Vector(); 使用包成员 加载整个包 import java.util.*; …… Vector vc = new Vector(); 消除名称的二义性 使用成员的限定名; 使用环境变量 classpath set classpath=…… javac –classpath …… MyClass.java java –classpath …… MyClass 使用包成员 在使用import语句的时候,可以使用通配符一次导入一个包中的所有类,如: import java.util.*; 这样,我们在使用java.util包中的任何类时,就可以直接使用简单类名。需要注意的是,import语句要么导入一个类,要么导入一个完整包。不能使用通配符标记包的子集或多个包,下面三条语句均无法通过编译: import java.applet.A*; import java.*.*; import java.*.io; 使用包成员 为了简化代码,Java语言规定在以下情况时无需使用import语句导入包: 使用缺省包中的类 使用java.lang包中的类 使用和当前类在同一个包中的其他类 管理源代码文件 将类或者接口的源代码放在一个文本文件中,文件名为类或者接口的简单名; 将源代码文件放在一个目录中,目录名反映的是类或者接口所属的包的名称。 例如: 管理源代码文件 包成员的限定名称与文件的路径是对应的,它们的对应关系为: 管理类文件 与源代码文件一样,字节码文件也可以通过包来进行管理; 字节码文件不必和源代码文件位与相同的目录中,可以单独管理;这样做的目的可以隐藏源代码文件。 类路径 定义:类路径是一个目录或zip文件的有序列表,用于搜索类文件。 类路径中列出的每个目录都是包含包目录的顶层目录,编译器和解释器可以根据类的包名称和类名从顶层目录开始构造路径的其余部分。 例如:上图所示的目录结构的类路径项目包含classes,但是不包含com或者com以下的任何目录,编译器和解释器用.class文件的完整包名构造它的路径名。 问题 假设你已经写了一些类,并且需要将这些类放进三个包中,如下所示: 为了将这些类放到正确的包中,需要在每个源代码中增加什么代码? 问题 In Client.java add: package mygame.client; In Server.java add: package mygame.server;: In Utilities.java add: package mygame.shared; 问题 为了遵守“管理源代码文件和类文件”所述的目录结构,需要在开发目录下创建一些子目录,并且将源代码文件放到正确的子目录中,必须创建哪些子目录?各个源代码文件应该放在哪个子目录中? 第7章 异常处理 华中科技大学IBM技术中心 为什么要异常处理? 对于任何语言的程序设计而言,错误的发生总是不可避免的 为了加强程序的健壮性,程序设计时,必须充分考虑错误发生的可能性,并建立相应的处理机制。 什么是异常? 异常(Exception)又称为例外,是指在程序运行过程中发生的非正常事件,这些事件的发生会影响程序的正常执行。如: 进行数学中“无意义”的运算,例如除数为零、对负数求对数平方根等 对数组进行操作时,超出了数组的最大下标 程序所需进行的I/O操作不能正常执行,如所需访问的文件不存在 内存耗尽无法进行类的实例化 JVM崩溃 异常对象 在Java语言中,我们用异常对象来表示不同的异常。 所谓Java异常对象就是一个存放着相关错误信息的对象,如果方法运行时产生了异常,该方法就可以抛出一个异常对象 为了表示不同种类的异常,Java语言中定义了许多异常类。 方法的调用堆栈 Java程序在执行的过程中,形成了一个先进后出的调用堆栈,各方法之间依照调用先后的不同,由先至后的进入调用堆栈,堆栈的最上层即是当前被调用执行的方法。该方法执行完毕后,会将处理器控制权交还给调用他的方法,依此类推。 方法调用堆栈中异常对象的传递 当某一方法中的一个语句抛出一个异常时,如果该方法中没有处理该异常的语句,那么该方法就会中止执行,并将这个异常传递给堆栈中的下一层方法,直到某一方法中含有处理该异常的语句为止。如果该异常被传递至主方法,而主方法中仍然没有处理该异常的语句,则异常将会被抛至JVM,程序中断。 例 程 Java中的异常类 在Java语言中,任何的异常对象都是Throwable类的直接子类或间接子类的实例。Java的类库已经提供了一些常见的异常类,如果这些异常类不能够满足要求,用户也可以创建自己的异常类。 Exception类 Exception的子类表示了不同类型的异常,例如RuntimeException表示运行时异常,而IOException表示I/O问题引起的异常。 这些子类也可以被继承以对不同类型的异常进行细分,如RuntimeException还可细分为NullPointerException、ArithmeticException等;IOException还可细分为FileNotFoundException、EOFException等。 常见的异常类 ArithmeticException ArrayIndexOutOfBandsException IOException FileNotFoundException NullPointerException NumberFormatException Error类 Error类表示Java运行时产生的系统内部错误或资源耗尽等严重错误。 这种错误通常是程序无法控制和解决的,如果发生这种错误,通常的做法是通知用户并中止程序的执行。 常见的错误类 NoClassDefFoundError OutOfMemoryError VirtualMachineError 必检异常与非必检异常 RuntimeException类及其子类被称为“运行时异常” 一般发生在JRE内部 也称“非必检异常” 如NullPointerException 其他异常被成为“非运行时异常” 一般发生在JRE外部 也称“必检异常” 如IOException 异常处理的一般步骤 异常抛出 异常捕获 异常处理 抛出异常 方法中需要抛出异常时,可使用throw语句实现,具体步骤应该是: 选择合适的异常类; 创建该类的一个对象; 使用throw语句抛出该对象。 抛出异常 例如,某方法readFile()对文件进行读操作,根据前面章节的介绍可以知道:当进行I/O操作时,可能会产生I/O异常。所以,在方法readFile中如果读文件操作不成功,则应抛出I/O异常。如下列程序片断所示: 抛出异常 如果一个方法可能抛出多个必检异常,那么必须在方法的声明部分一一列出,多个异常间使用逗号进行分隔: 抛出异常 一个方法必须通过throws语句在方法的声明部分说明它可能抛出而并未捕获的所有的“必检异常”,如果没有这么做,将不能通过编译。 值得注意的是:如果在子类中覆盖了父类的某一方法,那么该子类方法不可以比被其覆盖的父类方法抛出更多的异常(但可以更少)。所以,如果被覆盖父类的方法没有抛出任何的“必检异常”,那么子类方法绝不可能抛出“必检异常”。 抛出异常 在下面的例子里,对于父类SuperClass而言,类SubClassA是正确的子类,而SubClassB则是错误的。 异常的捕获 要捕获一个异常,程序员只需要在程序中设置一个try/catch块,其格式如下: try{ 抛出异常的代码 }catch (某Exception类型 e){ 处理该异常类型的代码 }catch (某Exception类型 e){ 处理该异常类型的代码 } 异常的捕获 当try块中的某条代码抛出异常时:首先,自该语句的下一条语句起的所有try块中的剩余语句将被跳过不予执行;其次,程序执行catch子句进行异常捕获,异常捕获的目的是进行异常类型的匹配,并执行与所抛出的异常类型相对应的catch子句中的异常处理代码。 异常的捕获 需要注意的是:如果try块中没有任何的异常抛出,则所有的catch子句将会被跳过;如果try块中所抛出的异常对象类型与所有的catch子句中的所声明的异常类型都不匹配,则方法会立即中止,并将该异常对象继续抛出,沿调用堆栈传递。 example example 上面的例子中可能会产生数组越界异常,所以将其置于try块中,并在catch子句中对ArrayIndexOutOfBoundsException类型的异常进行捕获,并进行处理。 如果try块中可能抛出多个类型的异常,程序员可以使用多个catch子句对这些异常进行捕获,每种异常类型对应一个单独的catch子句。 需要注意的是,这些catch子句是顺序执行的。这意味着,异常对象总是被第一个catch子句首先捕获,如果类型不匹配,才会执行下一个catch子句。读者可以试着分析下面的程序片断,看看有什么样的问题存在。 问题 Java运行系统从上到下分别对每个catch语句处理的例外类型进行检测,直到类型匹配为止; catch语句的排列顺序应该是从子类到父类 finally 当一个方法的某条语句抛出异常后,该方法剩余的语句将无法继续执行。这种情况下,方法往往无法将其占用的资源进行释放。 解决方法: 在每个catch子句的异常处理代码中也加上资源释放的代码,但这种方法非常麻烦; Java语言的异常处理机制中提供了一个更好的方案-程序员可以使用finally子句来统一进行资源释放之类的工作。 finally finally子句的一般格式: finally 不论try块中的代码是否抛出异常及异常是否被捕获,finally子句中的代码一定会被执行: 如果try块中没有抛出任何异常,当try块中的代码执行结束后,finally中的代码将会被执行; 如果try块中抛出了一个异常且该异常被catch正常捕获,那么try块中自抛出异常的代码之后的所有代码将会被跳过,程序接着执行与抛出异常类型匹配的catch子句中的代码,最后执行finally子句中的代码。 如果try块中抛出了一个不能被任何catch子句捕获(匹配)的异常,try块中剩下的代码将会被跳过,程序接着执行finally子句中的代码,未被捕获的异常对象继续抛出,沿调用堆栈顺序传递。 问题 当调用上述方法m()时,try块中包含方法的return语句,返回值为1。然而,实际调用该方法后产生的返回值为0。这是因为在方法实际返回并结束前,finally子句中的内容无论如何要被执行,所以finally子句中的return语句使得该方法最终实际返回值为0。 example example 声明异常 一个方法不处理它产生的异常,而是沿着调用堆栈向上传递,由调用它的方法来处理这些异常,则需要声明异常。 声明异常的方法: returnType methodName([paramlist]) throws exceptionList 例如: void compute(int x) throws ArithmeticException{ … } example example 创建自己的异常类 Java语言中允许用户定义自己的异常类,这些用户自定义异常类必须是Throwable的直接子类或间接子类。 根据Java异常类的继承关系,用户最好将自己的异常类定义为Exception的子类,而不要将其定义为RuntimeException的子类。因为对于RuntimeException的子类而言,即使调用者不进行处理,编译程序也不会报错。将自定义异常类定义为Exception的子类,可以确保调用者对其进行处理。 example example 异常的优点 将错误处理代码与“常规”代码分离; 例7.7.1 将错误沿调用堆栈传递; 可以由感兴趣的方法来处理异常 对错误类型进行分组和区分。 说明的问题 方法也可以不对异常进行捕获而直接将其抛出,并在方法声明中进行说明,那么对方法产生的异常到底是应该直接进行捕获还是应该将其进行传递呢? 一般来说,对于方法的最终调用者而言,他必须捕获并处理该方法抛出的异常。而对于抛出异常的方法而言,应该对方法可能产生的异常进行区分,尽量避免一些异常的产生,捕获并处理那些你知道如何处理的异常,而对那些你不知道方法的调用者会如何处理的异常,最好将它们留给方法的调用者进行处理,这样会增加程序的灵活性。 说明的问题 需要特别指出的是,虽然异常处理机制为程序员提供了非常大的方便,但是作为一个好的程序员要尽量避免异常的过度使用。这是因为:异常对象的实例化和其后续处理工作是非常消耗资源的,过度的使用异常会明显影响程序的执行速度。所以,在使用异常处理时应该仔细考虑,只对有必要的异常情况使用异常,而不可以将异常泛化。 两段代码的比较 问题 问题 问题 public static void cat(File named) { RandomAccessFile input = null; String line = null; try { input = new RandomAccessFile(named, “r”); while ((line = input.readLine()) != null { System.out.println(line); } return; } finally { if (input != null) { input.close(); } } } 第八章 线程 华中科技大学IBM技术中心 主要内容 什么是线程 线程是程序内的一个单一的顺序控制流程,也被称为“轻型进程(lightweight process)” 或“执行上下文(execution context )” 线程用于分隔任务 线程类似于传统的顺序程序,都有一个执行的起点,经过一系列指令后到达终点。线程在执行过程中的任何时刻只能有一个执行点 几个相关概念 线程的作用 线程真正的神奇之处并不在于它处理顺序任务流程的作用,而是在于多个线程可以同时运行,并且在一个程序内执行不同的任务 演示排序程序 如何创建线程 继承Thread类 在构造函数中调用父类的构造函数 参考Thread类的构造函数 在run方法中实现任务处理功能 创建线程对象后,通过调用start()方法启动线程 继承Thread类 class PrintThread extends Thread { private int sleepTime; public PrintThread( String name ) { super( name ); sleepTime = (int) ( Math.random() * 5000 ); System.out.println( "Name: " + getName() + "; sleep: " + sleepTime ); } public void run() { try { System.out.println( getName() + " going to sleep" ); Thread.sleep( sleepTime ); } catch ( InterruptedException ie ) { System.err.println( ie.toString() ); } System.out.println( getName() + " done sleeping" ); } } 执行线程任务 public class ThreadTester { public static void main( String args[] ) { PrintThread thread1, thread2, thread3, thread4; thread1 = new PrintThread( "thread1" ); thread2 = new PrintThread( "thread2" ); thread3 = new PrintThread( "thread3" ); thread4 = new PrintThread( "thread4" ); System.out.println( "\nStarting threads" ); thread1.start(); thread2.start(); thread3.start(); thread4.start(); System.out.println( "Threads started\n" ); } } 实现Runnable接口 实现run方法,在该方法中实现任务处理功能 参考Runnable接口定义 创建实现Runnable接口的类对象 利用Thread类的构造函数创建线程对象 public Thread(Runnable target) 通过调用线程对象的start()方法启动线程 实现Runnable接口 class PrintRunnable implements Runnable { private int name; private int sleepTime; public PrintRunnable( String name ) { this.name = name; sleepTime = (int) ( Math.random() * 5000 ); System.out.println( "Name: " + name + "; sleep: " + sleepTime ); } public void run() { try { System.out.println( name + " going to sleep" ); Thread.sleep( sleepTime ); } catch ( InterruptedException ie ) { System.err.println( ie.toString() ); } System.out.println( name + " done sleeping" ); } } 执行线程任务 public class RunnableTester { public static void main( String args[] ) { PrintRunnable thread1, thread2, thread3, thread4; thread1 = new PrintRunnable ( "thread1" ); thread2 = new PrintRunnable ( "thread2" ); thread3 = new PrintRunnable ( "thread3" ); thread4 = new PrintRunnable ( "thread4" ); System.out.println( "\nStarting threads" ); new Thread(thread1).start(); new Thread(thread2).start(); new Thread(thread3).start(); new Thread(thread4).start(); System.out.println( "Threads started\n" ); } } 选择合适的方式创建线程 继承Thread类 简单直观 不能继承其他父类 实现Runnable接口 可继承其他父类 代码稍复杂 ClockApplet示例 ClockApplet示例 import java.applet.Applet; import java.awt.Graphics; import java.util.Date; public class ClockApplet extends Applet implements Runnable { private Thread clockThread = null; public void start() { if (clockThread ==null) { clockThread = new Thread(this); clockThread.start(); } } public void paint(Graphics g) { Date date = new Date(); g.drawString(date.toString(), 5, 10); } ClockApplet示例 public void run() { while (true) { repaint(); try { Thread.sleep(1000); } catch (InterruptedException e) { } } } } 线程的生存周期 线程状态的转换条件 可运行状态和不可运行状态转换条件 停止线程 正常终止 run()方法运行完毕 强行中止 调用线程对象的stop()方法 创建线程对象的上级线程停止 线程的优先级 Java线程优先级 范围从1-10,数字越高越能被优先执行 通过线程对象的setPriority()方法设置优先级 缺省优先级为5 三个常数:MAX_PRIORITY、MIN_PRIORITY、NORM_PRIORITY 线程的调度 大多数计算机只有一个CPU,因此一个时刻只有一个线程在运行,多个线程只能是“宏观上并行,微观上串行” 在有限个CPU的系统中确定多个线程的执行顺序称为线程的调度 Java语言采用了简单的“固定优先级调度算法”,高优先级的线程总是更容易得到CPU使用权。 只有当所有高优先级的线程停止或处于不可运行状态,低优先级的线程才能运行。 抢占式调度 Java语言的“抢占式调度策略” 当一个线程正在运行时,如果有更高优先级的线程处于“可运行”状态,系统将强制暂停低优先级的线程,使高优先级的线程“抢占”低优先级线程的CPU资源 自私的线程 线程如果不放弃CPU,其他同优先级的线程就很难得到运行 run() { while(true) { …… // yield(); } } 除非更高优先级的抢占CPU,或者…… 时间片策略 部分平台(如Windows)针对“自私线程”采用了时间片轮换策略 将CPU的运行时间划分成段,相同优先级的线程分别占用一段轮流执行 执行的顺序和轮换的时间不可预测 正确理解优先级和调度 线程调度策略和JRE运行平台直接相关 Java本身并不直接支持时间片 不要编写“自私的”线程 在适当的时候通过yield()方法放弃CPU yield()方法使线程由运行状态变为就绪状态 yield()方法放弃CPU后,只有同优先级的线程才能得到CPU,低优先级的线程仍不能运行 正确理解优先级和调度 在多任务环境中,如果完全依赖低优先级线程可能永远得不到运行机会,称为线程“饿死” 线程调度程序可能为低优先级线程分配CPU,以防止线程“饿死” 优先级只是用来提高多线程的调度效率,并不保证高优先级线程永远优先运行 不要依赖线程的优先级来设计对调度敏感的算法 正确理解优先级和调度 public class PriorityTest extends Thread { public PriorityTest(String name) { super(name); } public void run() { while(true) { int i; for(int j=0; j<100000; j++) for(int k=0; k<1000; k++) i = j + k; if (getPriority()
ibm产品ppt:这是ibm产品ppt,包括了Product Briefing,Marketing and Sales System,Product Briefing,Domino & Notes,Domino Designer开发工具,WebSphere Application Server包括三个版本等内容,欢迎点击下载。
ibm公司介绍ppt:这是ibm公司介绍ppt,包括了前言,外部环境,IBM营运状况,IBM组织,服务网,企业文化,公司愿景等内容,欢迎点击下载。
ibm智慧地球ppt:这是ibm智慧地球ppt,包括了智慧地球是什么?解释一下?智慧地球的核心,支撑技术,“智慧的十年”,另一种声音等内容,欢迎点击下载。