Microsoft Word - 第3章.doc

Size: px
Start display at page:

Download "Microsoft Word - 第3章.doc"

Transcription

1 第 3 章 对象和类 在当今的计算机大型应用软件开发领域, 面向对象技术正在逐步取代面向过程的程序设计技术 本章将介绍面向对象的基本知识和 Java 实现面向对象程序设计的主要工具 类 如果读者缺乏关于面向对象程序设计的背景, 一定要仔细阅读本章 如果读者有 C++ 编程经验, 也要注意二者之间的区别, 毕竟 Java 在类的具体实现上与 C++ 有较大的差别 学习本章面向对象的相关知识, 主要内容有以下几点 : 面向对象的基本概念 ; 对象与类的理解 ; 成员变量的定义与使用 ; 方法的定义及实现 ; 方法调用 ; 构造方法与静态方法 ; 终结处理与垃圾回收 3.1 什么是面向对象 面向对象 (Object Oriented,OO) 是当前计算机界关心的重点, 它是 20 世纪 90 年代软件开发方法的主流 面向对象的概念和应用已超越了程序设计和软件开发, 扩展到很广的范围 例如, 数据库系统 交互式界面 应用结构 应用平台 分布式系统 网络管理结构 CAD 技术和人工智能等领域 面向对象是一种对现实世界理解和抽象的方法, 是计算机编程技术发展到一定阶段后的产物, 它是相对于面向过程而言的 通过面向对象的方式, 将现实世界的物抽象成对象, 现实世界中的关系抽象成类 继承等, 以更直观 清晰地完成对现实世界的抽象与数字建模 讨论面向对象方面的文章非常多 但是, 明确地给出 面向对象 的定义却非常少 最初, 面向对象 是专指在程序设计中采用封装 继承和抽象等设计方法 可是, 这个定义显然不能再适合现在的情况 面向对象的思想已经涉及到软件开发的各个方面 例如, 面向对象的分析 (Object Oriented Analysis,OOA) 面向对象的设计(Object Oriented Design, OOD) 以及经常说的面向对象的编程 (Object Oriented Programming,OOP) 许多有关面向对象的文章, 都只是讲述在面向对象的开发中所需要注意的问题, 或所采用的比较好的设计方法 看这些文章只有真正懂得什么是对象, 什么是面向对象, 才能最大程度地收获知识

2 第 3 章对象和类 说明 : 在本章中, 着重讨论 OOP, 有关 OOA 和 OOD 请读者查阅有关软件工程的书籍 OOP 从所处理的数据入手, 以数据为中心而不是以服务 ( 功能 ) 为中心来描述系统 它把编程问题视为一个数据集合, 因为数据相对于功能而言, 具有更强的稳定性 OOP 同结构化程序设计相比最大的区别就在于 : 前者首先关心的是所要处理的数据, 而后者首先关心的是功能 在计算机编程中使用 OOP 方法, 更利于从人理解的方式对于复杂系统的进行分析 设计与编程 同时能有效提高编程的效率, 通过封装技术, 消息机制可以像搭积木的一样快速开发出一个全新的系统 对象的理解 OOP 是一种围绕真实世界的概念来组织模型的程序设计方法, 它采用对象来描述问题空间的实体 可以说, 对象 这个概念是 OOP 最本质的概念之一, 在面向对象的编程过程中, 首先根据客户需求抽象出业务对象 ; 然后对需求进行合理分层, 构建相对独立的业务模块 ; 之后设计业务逻辑, 利用多态 继承 封装和抽象的编程思想, 实现业务需求 ; 最后通过整合各模块, 达到高内聚 低耦合的效果, 从而满足客户要求 但是, 如何给 对象 下一个严谨的定义, 却是一个棘手的问题, 目前还没有统一的认识 在现实生活中, 一般认为对象是行动或思考时作为目标的各种事物 对象所代表的本体可能是一个物理存在, 也可能是一个概念存在 例如一枝花 一个人 一项计划等 在使用计算机解决问题时, 对象是作为计算机模拟真实世界的一个抽象, 一个对象就是一个物理实体或逻辑实体, 它反映了系统为之保存信息和 ( 或 ) 与它交互的能力 在计算机程序中, 对象相当于一个 基本程序模块, 它包含了属性 ( 数据 ) 和加在这些数据上的操作 ( 行为 ) 对象的属性是描述对象的数据, 属性值的集合称为对象的状态 对象的行为则会修改这些数据值并改变对象的状态 因此, 在程序设计领域, 可以用 对象 = 数据 + 作用于这些数据上的操作 这一公式来表达 下面以一个生活中常见的例子来说明对象这个概念 例如 椅子 这个对象, 它是 家具 这个更大的一类对象的一个成员 椅子应该具有家具所具有的一些共性, 如 : 价格 重量和所有者等属性 它们的值也说明了椅子这个对象的状态 例如, 价格为 100 元, 重量为 5 公斤, 所有者是小王等 类似地, 家具中的桌子 沙发等对象也具有这些属性 这些对象所包含的成分可以用图 3.1 来说明 对象的操作是对对象属性的修改 在面向对象的程序设计中, 对象属性的修改只能通过对象的操作来进行, 这种操作又称为方法 比如上面的对象都有 所有者 这一个属性, 修改该属性的方法可能是 卖出, 一旦执行了 卖出 操作, 所有者 这个属性就会发生变化, 对象的状态也就发生了改变 现在的问题是, 所有的对象都有可能执行 卖出 操作, 那么如何具体区分卖出了哪个对象, 这是需要考虑的 面向对象的设计思路把 卖出 这个操作包含在对象里面, 执行 卖出 操作, 只对包含了该操作的对象有效 因此, 整个对象就会变成图 3.2 这个样子 由于对象椅子已经包含了 卖出 操作, 因此, 当执行 卖出 操作时, 对象外部的使用者并不需要关心它的实现细节, 只需要知道如何来调用该操作, 以及会获得怎样的结果就可以了, 甚至不需要知道它到底修改了哪个属性值 这样做不仅实现了模块化和信息 101

3 第 2 篇 Java 面向对象编程 隐藏, 有利于程序的可移植性和安全性, 也有利于对复杂对象的管理 图 3.1 对象的属性集合 图 3.2 封装了属性和操作的对象 什么是类 物以类聚 是人们区分 归纳客观事物的方法 在面向对象系统中, 人们不需要逐个去描述各个具体的对象, 而是关注具有同类特性的一类对象, 抽象出这样一类对象共有的结构和行为, 进行一般性描述, 这就引出了类的概念 椅子 桌子 沙发等对象都具有一些相同的特征, 由于这些相同的特征, 它们可以归为一类, 称为家具 因此, 家具就是一个类, 它的每个对象都有价格 重量及所有者这些属性 也可以将家具看成是产生椅子 桌子 沙发等对象的一个模板 椅子 桌子 沙发等对象的属性和行为都是由家具类所决定的 家具和椅子之间的关系就是类与类的成员对象之间的关系 类是具有共同属性 共同操作的对象的集合 而单个的对象则是所属类的一个成员, 或称为实例 (instance) 在描述一个类时, 定义了一组属性和操作, 而这些属性和操作可被该类所有的成员所继承, 如图 3.3 所示 图 3.3 由类到对象的继承图 3.3 表明, 对象会自动拥有它所属类的全部属性和操作 正因为这一点, 人们才会知道一种物品是家具时, 主动去询问它的价格 尺寸和材质等属性 对于初学者而言, 类和对象的概念最容易混淆 类属于类型的范畴, 用于描述对象的特性 对象属于值的范畴, 是类的实例 从集合的角度看, 类是对象的集合, 它们是从属 102

4 第 3 章对象和类 关系 也可以将类看成是一个抽象的概念, 而对象是一个具体的概念 例如苹果是一个类, 而 桌子上的那个苹果 则是一个对象 从编程的角度看, 类和对象的关系可以看成是数据类型和变量的关系 还可以认为类是一个静态的概念, 而对象是一个动态的概念, 它具有生命力 类和对象的关系可以用如图 3.4 所示这个实例来演示, 如图 3.4 所示 图 3.4 类与对象的关系 消息的定义 由上述内容可知, 对象的行为是通过其定义的一组方法来描述, 对象的结构特征是由它的属性来表现 但是, 对象不会无缘无故地执行某个操作, 只有在接受了其他对象的请求之后, 才会进行某一操作, 这种请求对象执行某一操作, 或是回答某些信息的要求称为消息 对象之间通过消息的传递来实现相互作用 消息一般有 3 个组成部分 : 消息接收者 ( 接收对象名 ) 接收对象应采用的方法以及方法所需要的参数 同时, 接收消息的对象在执行完相应的方法后, 可能会给发送者返回一些信息 例如, 教师向学生布置作业 07 级计算机 1 班做 5 道习题 其中, 教师和学生都是对象, 07 级计算机 1 班 是消息的接收者, 做习题 是要求目标对象 学生执行的方法, 5 道 是要求对象执行方法时所需要的参数 学生也可以向教师返回作业信息 这样, 对象之间通过消息机制, 建立起了相互关系 由于任何一个对象的所有行为都可以用方法来描述, 所以通过消息机制可以完全实现对象之间的交互 在 Java 程序设计中, 所需完成的功能任务就在对象之间的消息传递与相互作用之间完成 面向对象的基本特征 在上述面向对象的基本概念基础之上, 不可避免地要涉及到面向对象程序设计所具有的 4 个共同特征 : 抽象性 封装性 继承性和多态性 1. 抽象抽象是人们认识事物的常用方法, 比如地图的绘制 抽象的过程就是如何简化 概括 103

5 第 2 篇 Java 面向对象编程 所观察到的现实世界, 并为人们所用的过程 抽象是软件开发的基础 软件开发离不开现实环境, 但需要对信息细节进行提炼 抽象, 找到事物的本质和重要属性 抽象包括两个方面 : 过程抽象和数据抽象 过程抽象把一个系统按功能划分成若干个子系统, 进行 自顶向下逐步求精 的程序设计 数据抽象以数据为中心, 把数据类型和施加在该类型对象上的操作作为一个整体 ( 对象 ) 来进行描述, 形成抽象数据类型 ADT 所有编程语言的最终目的都是提供一种 抽象 方法 一种较有争议的说法是 : 解决问题的复杂程度直接取决于抽象的种类及质量 其中, 种类 是指准备对什么进行 抽象 汇编语言是对基础机器的少量抽象 后来的许多 命令式 语言 ( 如 FORTRAN BASIC 和 C) 是对汇编语言的一种抽象 与汇编语言相比, 这些语言已有了较大的进步, 但它们的抽象原理依然要求程序设计者着重考虑计算机的结构, 而非考虑问题本身的结构 在机器模型 ( 位于 方案空间 ) 与实际解决的问题模型 ( 位于 问题空间 ) 之间, 程序员必须建立起一种联系 这个过程要求人们付出较大的精力, 而且由于它脱离了编程语言本身的范围, 造成程序代码很难编写, 而且要花较大的代价进行维护 由此造成的副作用便是一门完善的 编程方法 学科 为机器建模的另一个方法是为要解决的问题制作模型 对一些早期语言来说, 如 LISP 和 APL, 它们的做法是 从不同的角度观察世界 所有问题都归纳为列表 或 所有问题都归纳为算法 PROLOG 则将所有问题都归纳为决策链 对于这些语言, 可以认为它们一部分是面向基于 强制 的编程, 另一部分则是专为处理图形符号设计的 每种方法都有自己特殊的用途, 适合解决某一类的问题 但只要超出了它们力所能及的范围, 就会显得非常笨拙 面向对象的程序设计在此基础上则跨出了一大步, 程序员可利用一些工具来表达问题空间内的元素 由于这种表达非常普遍, 所以不必受限于特定类型的问题 人们将问题空间中的元素以及它们在方案空间的表示物称作 对象 当然, 还有一些在问题空间没有对应体的其他对象 通过添加新的对象类型, 程序可进行灵活的调整, 以便与特定的问题配合 所以在阅读方案的描述代码时, 会读到对问题进行表达的话语 与以前的方法相比, 这无疑是一种更加灵活 更加强大的语言抽象方法 总之,OOP 允许人们根据问题, 而不是根据方案来描述问题 然而, 仍有一个联系途径回到计算机 每个对象都类似一台小计算机 ; 它们有自己的状态, 而且可要求它们进行特定的操作 与现实世界的 对象 或者 物体 相比, 编程 对象 与它们也存在共通的地方 : 它们都有自己的特征和行为 2. 封装封装是面向对象编程的特征之一, 也是类和对象的主要特征 封装将数据以及加在这些数据上的操作组织在一起, 成为有独立意义的构件 外部无法直接访问这些封装了的数据, 从而保证了这些数据的正确性 如果这些数据发生了差错, 也很容易定位错误是由哪个操作引起的 如果外部需要访问类里面的数据, 就必须通过接口 (Interface) 进行访问 接口规定了可对一个特定的对象发出哪些请求 当然, 必须在某个地方存在着一些代码, 以便满足这些请求 这些代码与那些隐藏起来的数据叫做 隐藏的实现 站在过程化程序编写 104

6 第 3 章对象和类 (Procedural Programming) 的角度, 整个问题并不显得复杂 一种类型含有与每种可能的请求关联起来的函数 一旦向对象发出一个特定的请求, 就会调用那个函数 通常将这个过程总结为向对象 发送一条消息 ( 提出一个请求 ) 对象的职责就是决定如何对这条消息作出反应 ( 执行相应的代码 ) 若任何人都能使用一个类的所有成员, 那么可对这个类做任何事情, 则没有办法强制他们遵守任何约束 所有东西都会暴露无遗 有两方面的原因促使了类的编制者控制对成员的访问 第一个原因是防止程序员接触他们不该接触的东西 通常是内部数据类型的设计思想 若只是为了解决特定的问题, 用户只需操作接口即可, 无需明白这些信息 类向用户提供的实际是一种服务, 因为他们很容易就可看出哪些对自己非常重要, 以及哪些可忽略不计 进行访问控制的第二个原因是允许库设计人员修改内部结构, 不用担心它会对客户程序员造成什么影响 例如, 编制者最开始可能设计了一个形式简单的类, 以便简化开发 后来又决定进行改写, 使其更快地运行 若接口与实现方法早已隔离开, 并分别受到保护, 就可放心做到这一点, 只要求用户重新链接一下即可 封装考虑的是内部实现, 抽象考虑的是外部行为 符合模块化的原则, 使得软件的可维护性 扩充性大为改观 3. 继承继承是一种联结类的层次模型, 并且允许和鼓励类的重用, 它提供了一种明确表述共性的方法 对象的一个新类可以从现有的类中派生, 这个过程称为类的继承 新类继承了原始类的特性, 新类称为原始类的派生类 ( 子类 ), 而原始类称为新类的基类 ( 父类 ) 派生类可以从它的基类那里继承方法和实例变量, 并且派生类可以修改或增加新的方法使之更适合特殊的需求 这也体现了大自然中一般与特殊的关系 继承性很好地解决了软件的可重用性问题 比如说, 所有的 Windows 应用程序都有一个窗口, 它们可以看作都是从一个窗口类派生出来的 但是有的应用程序用于文字处理, 有的应用程序用于绘图, 这是由于派生出了不同的子类, 各个子类添加了不同的特性 关于继承的详细讨论, 将在本书 4.1~4.2 节进行 4. 多态多态也叫多态性, 是指允许不同类的对象对同一消息作出响应 比如同样的加法, 把两个时间加在一起和把两个整数加在一起肯定完全不同 又比如, 同样的选择 编辑 和 粘贴 操作, 在字处理程序和绘图程序中有不同的效果 多态性包括参数化多态性和运行时多态性 多态性语言具有灵活 抽象 行为共享和代码共享的优势, 很好地解决了应用程序函数同名问题 关于多态性的讨论, 将在 4.4 节进行 最后, 以 Alan Kay 的话作为本节的结束语 他总结了 Smalltalk( 这是第一种成功的面向对象程序设计语言, 也是 Java 的基础语言 ) 的 5 大基本特征 通过这些特征, 读者可以理解 纯粹 的面向对象程序设计方法 (1) 所有东西都是对象 可将对象想象成一种新型变量, 它保存着数据, 但可要求它对自身进行操作 理论上讲, 可从要解决的问题上, 提出所有概念性的组件, 然后在程序 105

7 第 2 篇 Java 面向对象编程中将其表达为一个对象 (2) 程序是一大堆对象的组合 通过消息传递, 各对象知道自己该做些什么 为了向对象发出请求, 需向那个对象 发送一条消息 更具体地讲, 可将消息想象为一个调用请求, 它调用的是从属于目标对象的一个子例程或函数 (3) 每个对象都有自己的存储空间, 可容纳其他对象 或者说, 通过封装现有对象, 可制作出新型对象 所以, 尽管对象的概念非常简单, 但在程序中却可达到任意高的复杂程度 (4) 每个对象都有一种类型 根据语法, 每个对象都是某个 类 (Class) 的一个 实例 其中, 类 是 类型 (Type) 的同义词 一个类最重要的特征就是 能将什么消息发给它? (5) 同一类所有对象都能接收相同的消息 这实际是别有含义的一种说法, 读者不久便能理解 例如, 由于类型为 圆 (Circle) 的一个对象也属于类型为 形状 (Shape) 的一个对象, 所以一个 圆 完全能接收 形状 的消息 这意味着可让程序代码统一指挥 形状, 令其自动控制所有符合 形状 描述的对象, 其中自然包括 圆 这一特性称为对象的 可替换性, 是 OOP 最重要的概念之一 3.2 类与对象 3.1 节从理论角度阐述了对象和类的有关概念 类是组成 Java 程序的基本要素, 在 Java 中有两种类 : 一种是在 JDK 中已经设计好的类, 可以在程序中直接使用 ; 另一种需要程序员根据现有的任务, 自行设计和编写, 这被称为用户自定义类 本节将着重介绍在 Java 中如何来自定义类以及如何使用这些类 类的基本结构 在前两章的例子中已经定义了一些简单的类, 如 HelloWorldApp 类 : // 通过 class 关键字定义一个名为 HelloWorldApp 的类, 并声明为 public 型的 public class HelloWorldApp{ // 在 HelloWorldApp 类体中定义一个 main 主方法, 此方法是此类的执行入口 public static void main( String args[ ] ){ //main 方法体中执行一个控制台输出命令, 打印输出内容为 Hello World! 的字符串 System.out.println("Hello World!"); 这个类虽然非常简单, 但仍然可以看出, 一个类的实现至少包含两部分的内容 : classdeclaration { // 类的声明 classbody // 类体 下面分别对每一部分进行详细讲述 106

8 第 3 章对象和类 类的声明 一个最简单的类声明如下 : class classname 其中,class 是关键字, 用于定义类 classname 是类的名字, 它必须遵循用户标识符的定义规则 例如 : class Point 同时, 在类声明中还可以包含类的父类 ( 超类 ), 类所实现的接口以及访问权修饰符 abstract 或 final, 所以更一般的声明如下 : [ 类修饰符 ] class 类名 [extends 父类名 ] [implements 接口名列表 ] class extends 和 implements 都是关键字 类名 父类名和接口名列表都是用户标识符 父类 新类必须在已有类的基础上构造, 原有类即为父类, 新类即为子类 Java 中的每个类都有父类, 如果不含父类名, 则默认其父类为 Object 类 接口 接口也是一种复合数据类型, 它是在没有指定方法实现的情况下声明一组方法和常量的手段, 也是多态性的体现 修饰符 规定了本类的一些特殊属性, 它可以是下面这些关键字之一 : (1)final 最终类, 它不能拥有子类 如果没有此修饰符, 则可以被子类所继承 (2)abstract 抽象类, 类中的某些方法没有实现, 必须由其子类来实现 所以这种类不能被实例化 如果没有此修饰符, 则类中间所有的方法都必须实现 (3)public 公共类,public 表明本类可以被所属包以外的类访问 如果没有此修饰符, 则禁止这种外部访问, 只能被同一包中的其他类所访问 final 和 abstract 是互斥的, 其他情况下可以组合使用 下面声明了一个公共最终类, 它同时还是 Human 的子类, 并实现了 professor 接口 : public final class Teacher extends Human implements professor 创建类体 类体中定义了该类所有的变量和该类所支持的方法 通常变量在方法前面部分定义 ( 并不一定要求 ) 方法分为构造方法和成员方法, 如下所示 : public class classname { [membervariabledeclarations] // 定义成员变量 [constructordeclarations] // 定义构造方法 [methoddeclarations] // 定义成员方法 从以上代码中可以看出, 类体中有 3 个部分 : 成员变量 成员方法和构造方法 其中, 成员变量又被称作属性, 成员方法又被称作行为, 二者也可统称为类的成员 下例定义了一个 Point 类, 并且声明了它的两个变量 x y 坐标 定义了一个成员方法 107

9 第 2 篇 Java 面向对象编程 move(), 可以改变 x y 的值 定义了一个构造方法 Point(), 可以为 x y 赋初值 例 3.1 一个简单的 Point 类 // 文件名 Point.java, 程序编号 public class Point { int x,y; // 定义 Point 构造方法 Point(int ix, int iy){ x = ix; y = iy; // 定义普通的 move 方法 void move(int ix, int iy){ x += ix; y += iy; 类中所定义的变量和方法都是类的成员 对类的成员可以规定访问权限, 来限定其他对象对它的访问 访问权限有以下几种 :private protected pubic 和 friendly, 这些将在 3.3 节中详细讨论 同时, 对类的成员来说, 又可以分为实例成员和类 ( 静态 ) 成员两种, 这些将在 3.8 节中详细讨论 至此, 类完整的声明和定义形式已经全部给出 注意类体定义中, 并非每个部分都需要 一个最简单的类可能是下面这个样子, 它什么事情也不能做 class empty{ 对象的生命周期 定义类的最终目的是要使用它 一般情况下, 要使用类需要通过类的实例 对象来实现 在定义类时, 只是通知编译器需要准备多大的内存空间, 并没有为它分配内存空间 只有用类创建了对象后, 才会真正占用内存空间 Java 的对象就像有生命的事物一样, 也要经历 3 个阶段 : 对象的创建 对象的使用和对象的清除 这被称为对象的生命周期 对象的生命周期长度可用如下的表达式表示 : T = T1 + T2 +T3 其中,T1 表示对象的创建时间,T2 表示对象的使用时间, 而 T3 则表示其清除时间 由此可以看出, 只有 T2 才是真正有效的时间, 而 T1 和 T3 则是对象本身的开销 对象的创建 创建一个对象也被称为实例化一个类 它需要用到下面的语句 : 类名对象名 =new 构造方法名 ([ 参数列表 ]); 例如, 使用例 3.1 的 Point 类来创建一个对象 p: Point pt=new Point(1,2); 108

10 第 3 章对象和类 该语句创建了一个新对象, 它的名字叫做 pt new 是 Java 的关键字, 用于创建对象 表达式 new Point(1,2) 创建了一个 Point 类的实例对象, 它同时指明坐标值为 (1,2) 对象的引用被保存在变量 pt 中 它虽然是一条语句, 但实际上包括 3 个步骤 : 声明 实例化和初始化 一般情况下, 创建和使用对象都要经过这 3 个步骤 1. 声明对象 对象的声明和基本类型的数据声明在形式上是一样的 : 类名对象名 ; 对象名也是用户标识符, 和基本类型的变量遵循同样的命名规则和使用规则 例如, 声明一个 Point 类型的变量 pt: Point pt; 和 C++ 不同,Java 中像上面这样声明一个变量, 并不会分配一个完整的对象所需要的内存空间, 这一点也和简单数据类型的变量不同 它会将 pt 看成是一个引用变量, 并为它分配所需内存空间, 它所占用的空间远远小于一个 Point 对象所需要的空间 如此处理, 使得 Java 中声明一个对象的消耗很小, 但也有一个副作用, 就是对象不能马上使用, 还需要对它进行实例化 2. 实例化对象 Java 中使用 new 关键字创建一个新对象, 即进行实例化 格式如下 : new 构造方法 ([ 参数列表 ]) 实例化的过程就是为对象分配内存空间的过程, 此时, 对象才成为类的实例 new 所执行的具体操作是调用相应类中的构造方法 ( 包括祖先类的构造方法 ), 来完成内存分配以及变量的初始化工作, 然后将分配的内存地址返回给所定义的变量 使用 new 创建 Point 对象的示例如下 : pt = new Point(1,2); 用 new 来创建对象需要比较大的时间开销, 远远比声明一个对象的消耗要大得多 一些常见操作的时间消耗如表 3.1 所示 表 3.1 一些操作所耗费时间的对照表运算操作示例标准化时间运算操作示例标准化时间 本地赋值 i = n 1.0 新建对象 new Object() 980 实例赋值 this.i = n 1.2 新建数组 new int[10] 3100 方法调用 Funct() 5.9 从表 3.1 中可以看出, 新建一个对象需要 980 个单位的时间, 是本地赋值时间的 980 倍, 是方法调用时间的 166 倍, 而若新建一个数组所花费的时间就更多了 3. 初始化对象 当一个对象生成时, 通常要为这个对象确定初始状态, 这个过程就是对象的初始化 109

11 第 2 篇 Java 面向对象编程 由于创建对象是通过类及其祖先类的构造方法来进行的, 所以初始化工作也会在这里完成 注意到前面的这个说明 : 类名对象名 =new 构造方法名 ([ 参数列表 ]); 其中的参数列表就是传递给构造方法的一些值 构造方法获得这些值后, 就可以为成员变量赋初始值 比如 : Point pt=new Point(1,2); 它会将成员变量 x 和 y 分别赋值为 1 和 2 Java 还规定, 如果成员变量没有被显示地赋初值, 系统将自动为它们赋初值 具体规定为 : 所有的简单变量除 boolean 类型外均赋初值为 0,boolean 类型赋初值为 false, 其他类型的对象均赋初值为 null 对象的使用 创建对象之后, 就可以开始使用对象了 所谓使用对象, 就是通过消息来调用成员方法, 或者直接读取或修改成员变量, 二者的结果都是获取或改变对象的状态 下面简单介绍这两种方法 1. 对象变量的使用 要使用对象的变量, 需要先创建对象 如果成员变量的访问权限允许, 可以直接利用下面的方法 : 对象名. 成员变量名 仍以 Point 的对象 pt 为例, 可以这么使用它的成员变量 : pt.x=6; pt.y=6; 这样就将它的两个成员变量 x 和 y 都置为 6 说明 : 这样直接通过对象来使用成员变量, 违反封装原则, 除非确有必要, 否则最好不要使用 其实多数类的成员变量在定义时会用 private 来修饰, 根本就无法使用这种方法来访问 2. 对象方法的调用大多数的成员方法都是被设计供外部调用的 它的一般语法格式为 : 对象名. 成员方法名 ([ 参数列表 ]) 例如, 要将点 pt 从原来的坐标 (1,1) 移动到 (6,6), 这需要调用它的成员方法 move(): pt.move(5,5) 它的效果与前面的 pt.x=6;pt.y=6 完全一样, 不过这么做要安全得多, 符合封装原则 110

12 第 3 章对象和类 3.3 成员变量的定义与使用 成员变量又称为成员属性, 它是描述对象状态的数据, 是类中很重要的组成成分 本节详细讨论如何来定义成员变量 成员变量的访问权限, 以及静态成员变量与实例成员变量之间的区别 成员变量的定义 在第 2 章中, 已经介绍和使用过变量 不过那些变量都是定义在某个方法中, 被称为局部变量 成员变量是定义在类里面, 并和方法处于同一层次 定义成员变量的语法如下 : [ 变量修饰符 ] 类型说明符变量名 类的成员变量和在方法中所声明的局部变量都是用户标识符, 它们的命名规则相同 变量修饰符是可选项 一个没有变量修饰符的变量定义如下 : public class Cuber{ double width,height; int number; 成员变量的类型可以是 Java 中的任意数据类型, 包括基本类型 数组 类和接口 在一个类中, 成员变量应该是唯一的, 但是成员变量的名字可以和类中某个方法的名字相同, 例如 : public class Point{ int x, y; int x(){ return x; 其中, 方法 x() 和变量 x 具有相同的名字, 但笔者不赞成这样写, 因为这会引起不必要的混淆 可以用成员变量修饰符来规定变量的相关属性, 这些属性包括 : 成员变量的访问权限 一共有 4 种访问权限可供选择, 在 小节将详细介绍 成员变量是否为静态 默认情况下, 成员变量是实例成员, 在外部需要通过对象才能操作 如果用 static 修饰, 就成为了静态成员, 也称为类变量, 无需通过对象就可以操作 是否为常量 默认的是变量, 如果前面加上 final 关键字, 它就是一个常量 这些修饰符可以任意组合使用 加上修饰符的成员变量如下所示 : public class Cuber{ private double width,height; public static int count; public static final int COLORE=1; // 定义两个私有的成员变量 // 定义一个公共的静态类变量 // 定义一个公共的整型静态常量 111

13 第 2 篇 Java 面向对象编程虽然 Java 并没有规定, 成员变量必须定义在类的开始部分, 不过在实际编程中, 多数程序员将成员变量定义在成员方法的前面 成员变量的访问权限 访问权限修饰符声明了成员变量的访问权限 Java 提供的显示的访问权限修饰符有 3 种, 分别是 : 私有 (private) 保护(protected) 和公共 (public) 除此之外, 还有一种默认的访问权限 :friendly, 它并不是 Java 的关键字, 只有当变量前面没有写明任何访问权限修饰符时, 就默认以 friendly 作为访问权限 为了表达上的方便, 省略了其中 成员 两字, 将被这些修饰符所修饰的变量分别称为私有变量 保护变量和公共变量 下面分别讨论各个修饰符的用法 1. 公共变量 凡是被 public 修饰的成员变量, 都称为公共变量, 它可以被任何类所访问 即允许该变量所属的类中所有的方法访问, 也允许其他类在外部访问 如例 3.2 所示 例 3.2 公共变量使用示例 // 文件名 declarepublic.java, 程序编号 public class declarepublic{ public int publicvar=10; // 定义一个公共变量 在类 declarepublic 中声明了一个公共变量 publicvar, 它可以被任何类所访问 下面这段程序中, 类 otherclass 可以合法地修改变量 publicvar 的值, 而无论 otherclass 位于什么地方 // 文件名 otherclass.java, 程序编号 public class otherclass{ void change(){ declarepublic ca=new declarepublic(); ca.publicvar=20; // 创建一个 declarepublic 对象 // 通过对象名来访问它的公共变量, 正确 用 public 修饰的变量, 允许任何类在外部直接访问, 这破坏了封装的原则, 造成数据安全性能下降, 所以除非有特别的需要, 否则不要使用这种方案 2. 私有变量 凡是被 private 修饰的成员变量, 都称为私有变量 它只允许在本类的内部访问, 任何外部类都不能访问它 例 3.3 私有变量使用示例 // 文件名 declareprivate.java, 程序编号 public class declareprivate{ private int privatevar=10; void change(){ // 定义一个私有变量 112

14 第 3 章对象和类 privatevar=20; // 在本类中访问私有变量, 合法 如果企图在类的外部访问私有变量, 编译器将会报错 // 文件名 otherclass.java, 程序编号 public class otherclass{ void change(){ declareprivate ca=new declareprivate(); // 创建一个 declareprivate 对象 ca.privatevar=20; // 企图访问私有变量, 非法 为了让外部用户能够访问某些私有变量, 通常类的设计者会提供一些方法给外部调用, 这些方法被称为访问接口 下面是一个改写过的 declareprivate 类 // 文件名 declareprivate.java, 程序编号 public class declareprivate{ private int privatevar=10; void change(){ privatevar=20; // 定义一个私有变量 public int getprivatevar(){ // 定义一个接口, 返回私有变量 privatevar 的值 return privatevar; /** 定义一个接口, 可以设置 privatevar 的值能够在这里先检测 value 是否在允许的范围内, 然后再执行下面的语句 **/ public boolean setprivatevar(int value){ privatevar = value; return true; 私有变量很好地贯彻了封装原则, 所有的私有变量都只能通过程序员设计的接口来访问, 任何外部使用者都无法直接访问它, 所以具有很高的安全性 但是, 在下面这两种情况下, 需要使用 Java 另外提供的两种访问类型 通过接口访问私有变量, 将降低程序的性能, 在程序性能比较重要的情况下, 需要在安全性和效率间取得一个平衡 私有变量无法被子类继承, 当子类必须继承成员变量时, 需要使用其他的访问类型 3. 保护变量 凡是被 protected 修饰的变量, 都被称为保护变量 除了允许在本类的内部访问之外, 还允许它的子类以及同一个包中的其他类访问 子类是指从该类派生出来的类 包是 Java 中用于管理类的一种松散的集合 二者的详细情况将在第 4 章介绍 下面是一个简单的例子 例 3.4 保护变量使用示例 下面这个程序先定义一个名为 onlydemo 的包,declarProtected 类就属于这个包 113

15 第 2 篇 Java 面向对象编程 // 文件名 declareprotected.java, 程序编号 package onlydemo; public class declareprotected{ protected int protectedvar=10; // 定义一个保护变量 void change(){ protectedvar=20; // 合法 说明 : 读者编译这个文件时, 需要用这个命令 ( 下同 ): javac -d. 文件名 下面这个 otherclass 类也定义在 onlydemo 包中, 与 declareprotected 类同属于一个包 // 文件名 otherclass.java, 程序编号 package onlydemo; public class otherclass{ // 它也在包 onlydemo 中 void change(){ declareprotected ca=new declareprotected(); ca.protectedvar=20; // 合法 下面这个 deriveclass 类是 declareprotected 的子类, 它并不在 onlydemo 包中 它也可以访问保护变量 protectedvar, 但是只能通过继承的方式访问 // 文件名 declareprotected.java, 程序编号 import onlydemo.declareprotected; // 引入需要的包 public class deriveclass extends declareprotected{ // 定义一个子类 void change(){ // 合法, 改变的是 deriveclass 从 declarprotected 中所继承的 protectedvar 值 protectedvar=30; 说明 :import 是 Java 中的关键字, 用于引入某个包 这将在 4.7 节中详细介绍 子类如果不在父类的同一包中, 将无法通过 对象名. 变量名 的方式来访问 protected 类型的成员变量, 比如下面这种访问是非法的 // 文件名 deriveclass.java, 程序编号 import onlydemo.declareprotected; public class deriveclass extends declareprotected{ // 定义一个子类 void change(){ declareprotected ca=new declareprotected(); ca.protectedvar=30; // 错误, 不允许访问不在同一包中的保护变量 4. 默认访问变量 如果在变量前不加任何访问权修饰符, 它就具有默认的访问控制特性, 也称为 friendly 变量 它和保护变量非常像, 它只允许在同一个包中的其他类访问, 即便是子类, 如果和 114

16 第 3 章对象和类 父类不在同一包中, 也不能继承默认变量 ( 这是默认访问变量和保护变量的唯一区别 ) 因为它限定了访问权限只能在包中, 所以也有人称默认访问权限为包访问权限 例 3.5 默认访问变量使用示例 // 文件名 declaredefault.java, 程序编号 package onlydemo; // 本类定义在包中 public class declaredefault{ int defaultvar=10; // 定义一个默认访问变量 void change(){ defaultvar=20; // 合法 onlydemo 包中的其他类, 可以访问 defaultvar 变量 // 文件名 otherclass.java, 程序编号 package onlydemo; public class otherclass{ // 它也在包 onlydemo 中 void change(){ declaredefault ca=new declaredefault(); ca.defaultvar=20; // 合法 下面是它的子类, 也在 onlydemo 包中 它除了可以像包中其他类那样通过 对象名. 变量名 来访问默认变量, 还可以通过继承的方式来访问 // 文件名 deriveclass.java, 程序编号 package onlydemo; public class deriveclass extends declaredefault{ // 定义一个子类 void change(){ // 合法, 改变的是 deriveclass 从 declardefault 中所继承的 defaultvar 值 defaultvar=30; 如果子类不在 onlydemo 包中, 就不会继承默认变量, 也就无法像上面那样来访问 // 文件名 deriveclass.java, 程序编号 import onlydemo.declaredefault; public class deriveclass extends declaredefault{ // 定义一个子类 void change(){ defaultvar=30; // 非法, 这个变量没有继承下来 实例成员变量和静态成员变量 1. 实例成员变量 在 小节中, 所有的对象都是实例成员变量 它们的最大特色是 : 如果所属的对象没有被创建, 它们也就不存在 如果在类的外部使用它, 需要先创建一个对象, 然后通 115

17 第 2 篇 Java 面向对象编程 过 对象名. 变量名 来访问 前面所有的例子都遵循了这一规则 在类的内部, 实例成员方法也可以直接访问实例成员变量, 比如例 3.5, 具体原因, 将在 3.5 节中讲述 不同的对象, 拥有不同的实例成员变量, 它们互不干扰 例 3.6 不同对象的实例成员变量使用示例 // 文件名 instancevar.java, 程序编号 public class instancevar{ protected int instvar=0; // 定义一个实例成员变量 下面这个 showinstvar 类用两个对象来访问它的实例成员变量 // 文件名 showinstvar.java, 程序编号 public class showinstvar{ public static void main(string args[]){ instancevar one = new instancevar(); // 创建对象 one instancevar two = new instancevar(); // 创建对象 two // 分别为这两个对象的成员变量赋值 one.instvar = 100; two.instvar = 200; // 分别显示这两个对象的成员变量值 System.out.println("one.instVar="+one.instVar); System.out.println("two.instVar="+two.instVar); 程序 3.16 输出的结果如下 : one.instvar=100 two.instvar=200 从本例中明显地看出, 不同对象的成员变量是不相同的, 它们互不干涉 2. 静态成员变量 在某些情况下, 程序员希望定义一个成员变量, 可以独立于类的任何对象, 即所有的对象都共用同一个成员变量 由于 Java 中不能像 C 一样定义全局变量, 因此,Java 中引入了静态成员变量 在成员变量前加上 static 标识符就可以定义一个静态成员变量 相对于实例成员变量, 静态成员变量具有以下特点 : 它被类的所有对象共享, 因此又被称为类变量 它不是属于某个具体对象, 也不是保存在某个对象的内存区域中, 而是保存在类的公共存储单元 因此, 可以在类的对象被创建之前就能使用 它既可以通过 对象名. 变量名 的方式访问, 也可以通过 类名. 变量名 的方式访问 它们是完全等价的 例 3.7 静态成员变量使用示例 // 文件名 staticvar.java, 程序编号 public class staticvar{ protected static int stat=0; // 定义一个静态成员变量 116

18 第 3 章对象和类 下面这个程序使用不同的方法来访问这个静态变量 // 文件名 showstaticvar.java, 程序编号 public class showstaticvar{ public static void main(string args[]){ staticvar.stat=100; // 通过类名. 变量名访问静态变量, 无需创建对象 System.out.println("staticVar.stat="+staticVar.stat); staticvar one = new staticvar(); // 创建对象 one staticvar two = new staticvar(); // 创建对象 two // 分别为这两个对象的静态成员变量赋值 one.stat = 200; two.stat = 300; // 分别显示这两个对象的静态成员变量值 System.out.println("one.stat="+one.stat); System.out.println("two.stat="+two.stat); // 再通过类来显示静态变量的值 System.out.println("staticVar.stat="+staticVar.stat); 程序 3.18 输出结果如下 : staticvar.stat=100 one.stat=300 two.stat=300 staticvar.stat=300 从上述结果中可以看到, 静态变量 stat 是一个公共变量, 无论哪个对象改变了它的值, 对其他所有该类对象都有效 静态变量的一个重要作用是当作同类各个对象之间传递信息使用, 类似于 C 语言中的全局变量 但这样破坏了数据的封装原则, 往往会留下隐患, 所以使用这类变量时需要万分谨慎 静态变量的另一个用途是定义静态常量, 比如 : public static double PI = ; 这样的静态常量可以无需创建对象就直接使用, 省略了创建对象的步骤, 类似于 C 语言中用 define 定义的常量 这样定义常量, 不仅使用方便, 而且节省内存空间 在 JDK 中, 存在着大量的这种静态常量 说明 : 本节中所有的成员变量的类型都是基本类型, 其实它们也都可以是复合类型, 比如数组 类和接口等类型 3.4 方法的定义和实现 在类中, 除了变量以外, 另一个重要的组成成分就是方法 方法是用来实现类的行为, 其实相当于 C 语言中的函数, 但它一般只对类中的数据进行操作 一个方法, 通常只完成某一项具体的功能, 这样做使得程序结构清晰, 利于程序模块的重复使用 可以把方法看成一个 黑盒子, 方法的使用者只要将数据送进去就能得到结果, 而方 117

19 第 2 篇 Java 面向对象编程 法内部究竟是如何工作的, 外部程序是不知道的 外部程序所知道的仅限于输入给方法什么, 以及方法输出什么 Java 中没有限制一个类中所能拥有的方法的个数 如果说有什么限制, 就是只有 main 方法可以作为应用程序的入口 本书前面的例子已经使用过很多方法, 比如 System.out.println Math.random 以及 main 方法 其中, 某些方法 ( 比如前两个 ) 是系统已经定义在类中的标准方法, 可以直接拿来使用 ; 而另外一些方法 ( 比如 main 方法 ) 则需要由程序员自己来编写方法体, 被称为自定义方法 本节将讲述如何来声明和定义一个自定义方法 方法的声明 方法声明, 就是声明一种新的功能, 或者说创造一种新的功能 在 Java 中, 除了抽象方法之外, 它通常和方法的定义在一起, 位于方法体的前面 一个方法的声明, 通常格式如下 : [ 方法修饰符 ] [ 方法返回值类型 ] 方法名 ([ 形式参数表 ]) 方法修饰符和成员变量的修饰符一样, 有访问权限修饰符 final 和 static 3 种 访问权限修饰符又包括 private protected public 和默认 它们的含义也和成员变量中的完全相同 final 表示最终方法, 将在 4.6 节中讲述 static 表示静态方法, 将在 3.7 节中讲述 方法的返回值类型也和成员变量的数据类型一样, 可以是基本类型 :int char 和 double 等, 也可以是类类型 返回值类型可以是 void, 表示没有返回值 形式参数列表是方法可以接收的参数, 它由外部调用者提供具体的值 参数可以有多个, 中间用逗号分隔 也可以没有参数, 但圆括号不能省略 例 3.8 几个方法声明的例子 public int max(int a, int b) 本方法是一个公共方法, 将返回一个整型值 调用者需提供两个整型参数 private void setx(double x) 本方法是一个私有方法, 它没有返回值, 调用者需提供一个双精度参数 protected double getx() 本方法是一个保护方法, 它有一个双精度返回值, 调用者无需提供参数 创建方法体与 return 语句 方法体中包含了各种 Java 语句, 它是完成方法功能的主体 它紧跟在方法的声明之后, 用一对 { 括起来 方法体和方法的声明合起来, 称为方法的定义 方法体中除了可执行语句外, 也可以有属于本方法的局部变量 本小节以前的例子中, 118

20 第 3 章对象和类 多数都是这种情况 下面是一个简单的例子 例 3.9 方法体定义的例子 // 文件名 showmethod.java, 程序编号 public class showmethod{ private int x=0; // 下面这个方法有一个参数 ix public void setx(int ix){ int factor = 10; // 定义局部变量 factor x = factor * ix; // 使用参数 ix 给成员变量 x 赋值 // 下面这个方法参数列表为空 public int getx(){ return x; // 返回 x 的值给调用者 程序 3.19 不能直接由系统运行, 因为它没有 main 方法, 但它仍然是一个合法的类, 可以用来创建对象 在方法 getx() 中, 有一条语句 return x return 是 Java 中的关键字, 它构成的语法格式为 : return [ 表达式 ]; Java 规定, 任何一个返回值不为 void 的方法, 都必须至少有一条 return 语句 return 后面的表达式类型必须与返回类型相容 这里的 相容 是指 : 或者类型完全相同, 或者表达式的类型可以经过扩展类型转换成与返回类型相同的类型 否则编译器就会报错 如果是 void 类型的方法, 则可以不需要 return 语句 如果有 return 语句, 则 return 语句后面的表达式应为空 例 3.10 return 语句使用示例 1 // 文件名 showreturn_1.java, 程序编号 public class showreturn_1{ // 这个方法返回值为 int 类型 public int method_1( ){ return 1; // 合法,1 是整型数 // 这个返回类型为 double 类型 public double method_2(){ return 1; // 合法,1 可以自动转换成 double 类型 // 这个返回类型为 int 类型 public int method_3(){ return 1.0; // 错误,1.0 不能自动转换成 int 类型 // 这个返回类型为 void 类型 public void method_4(){ return ; // 合法 // 这个返回类型为 void 类型 public void method_5(){ return 1; // 错误, 不能有返回值 119

21 第 2 篇 Java 面向对象编程 在一个方法中, 如果没有 return 语句, 则该方法一直执行到最后一条语句完毕后, 返回调用者调用的位置 如果有 return 语句, 则只要执行到 return 语句, 立即返回调用者, 无论该 return 语句后面还有多少语句, 都不会被执行 一个方法中可以有多条 return 语句, 但一次调用时, 只能执行某一条 return 语句, 其余的无效 例 3.11 return 语句使用示例 2 // 文件名 showreturn_2.java, 程序编号 public class showreturn_2{ private int x = 0; // 下面这个方法虽有两条 return 语句, 但仍然是合法的 public boolean setx(int ix){ if (ix > 100) return false; // 若 ix>100, 则在这里返回, 下面的语句不被执行 x = ix; return true; // 若赋值成功, 从这里正常返回 // 下面这个方法有错误 public int getx(){ return x; // 返回 x 的值给调用者 x = 0; 局部变量和成员变量的区别 // 错误, 本语句永远也不会执行到 在方法内部可以定义变量, 被称为局部变量 局部变量的一般形式如下 : [ 变量修饰符 ] 变量类型变量名 ; 变量修饰符可以是 final, 表示这是常量 变量类型可以是 Java 中任意合法的基本类型或复合类型 变量名是用户自定义标识符, 遵循标识符的一般规则 可以在一行中定义多个局部变量, 以逗号分隔 定义变量时可以同时赋初值 局部变量必须要先定义后使用 例如, 下面就是一些局部变量的定义 : final double PI = ; int ix, iy; final int MAIL = 0; 从形式上看, 局部变量和类的成员变量十分相似, 但在使用上它们的区别很大 局部变量没有访问权限修饰符, 不能用 public private 和 protected 来修饰 这是因为它只能在定义它的方法内部使用 局部变量不能用 static 修饰, 没有 静态局部变量, 这是 Java 和 C/C++ 的一个细微差别 120

22 第 3 章对象和类 系统不会自动为局部变量赋初值, 但对于成员变量, 系统会自动赋初值 基本类型的初值为 0, 复合类型的初值为 null 局部变量的作用域仅限于定义它的方法, 在该方法的外部无法访问它 成员变量的作用域在整个类内部都是可见的, 所有成员方法都可以使用它 如果访问权限允许, 还可以在类的外部使用成员变量 局部变量的生存周期与方法的执行期相同 当方法执行到定义局部变量的语句时, 局部变量被创建 ; 执行到它所在的作用域的最后一条语句时, 局部变量被销毁 类的成员变量, 如果是实例成员变量, 则它和对象的生存期相同 而静态成员变量的生存期是整个程序运行期 在同一个方法中, 不允许有同名的局部变量 在不同的方法中, 可以有同名的局部变量, 它们互不干涉 局部变量可以和成员变量同名, 且在使用时, 局部变量具有更高的优先级 例 3.12 局部变量使用示例 // 文件名 localvariable.java, 程序编号 public class localvariable{ public void method_1(){ int va = 0; // 正确 public int pva; // 错误, 不能有访问权限 static int sa; // 错误, 不能是静态的 final int CONST = 10; // 正确, 可以是常量 double va =0.0; // 错误, 与前面的 va 同名 vb = 100.0; // 错误,vb 还未定义 double vb; vb = 100.0; // 正确, 现在可以使用了 public void method_2(){ va = 0; // 错误,method_1() 中的变量 va 在此不可用 int CONST = 100; // 正确, 它与 method_1() 中的 CONST 不同 例 3.13 局部变量与成员变量同名问题示例 // 文件名 localvsmember.java, 程序编号 public class localvsmember{ private int ivar = 100; public void method_1(){ int ivar; // 正确, 可以与成员变量同名 ivar = 200; // 这里访问的是局部变量 this.ivar = 300; // 这里访问的是成员变量 public void method_2(){ ivar = 400; // 这里访问的是成员变量 在程序 3.23 中, 同名的局部变量会屏蔽掉成员变量 为了访问被屏蔽的成员变量, 需要使用一个前缀 this, 它表示的是 本对象 关于 this 的详细用法, 将在 小节中 121

23 第 2 篇 Java 面向对象编程 介绍 方法的访问权限 方法与成员变量一样, 都是类的成员, 因此它和成员变量一样, 也有访问权限的问题 方法的访问权限也有 4 种 :public private protected 和默认, 而且它们和成员变量的规则 完全一样, 这里不再重复举例 关于成员的各种权限的访问规则, 可以总结成表 3.2 表 3.2 各种访问权限的规则 public protected 默 认 private 本类内部 同一包中的子类 同一包中非子类 不同包中的子类 继承访问 不同包中非子类 表 3.2 中的 表示可以访问, 表示不能访问 不在同一个包中的子类, 可 以继承父类中的 protected 成员方法和成员变量, 并且通过这种方式来访问 但不允许通过 对象名. 方法名 () 的方式来访问 从表 3.2 中可以看出, 在类的内部使用成员时, 根本无需考虑访问权限的问题 在外 部访问成员时,public 的限制最宽松,private 的限制最严格,protected 和默认的限制介于 两者之间 初学者不必死记这些访问限制, 通过大量的编程实践, 将逐步掌握其中的规律 3.5 方法的调用 多数情况下, 使用方法需要进行显式的方法调用 方法被调用之后, 就会执行方法体内部的语句, 完成预定义的功能 方法调用的形式 根据方法的调用者与被调用的方法所处的位置, 方法调用的形式可以分为两种 调用者和被调用方法位于同一类中, 形式如下 : [this.] 方法名 ([ 实际参数列表 ]) 在大多数情况下, 关键字 this 可以省略 调用者位于被调用方法所在类的外部, 形式如下 : 对象名. 方法名 ([ 实际参数列表 ]) 或者类名. 方法名 ([ 实际参数列表 ]) 实际参数列表是对应方法的形式参数列表, 可以是 0 个或多个变量或表达式, 如果超过 1 个, 需用逗号分隔 122

24 下面是方法调用的两个例子 例 3.14 同一类中调用方法示例 第 3 章对象和类 // 文件名 invokemethod.java, 程序编号 public class invokemethod{ public void showmsg(){ System.out.println("This is showmsg method"); public void callother(){ showmsg(); // 调用类中的另外一个方法, 这里也可以写成 this.showmsg() public static void main(string args[]){ // 创建对象 invokemethod ob = new invokemethod(); ob.callother(); // 调用 callother() 方法 程序的输出如下 : This is showmsg method 在程序 3.24 中, 方法 callother() 和方法 showmsg() 处在同一个类中, 所以调用后者时, 直接使用方法名就可以 在 main() 方法中, 调用 callother() 方法时, 需先创建一个对象 ob, 再用 对象名. 方法名 () 的格式来调用该方法, 这么做是因为 main() 方法是一个静态方法, 它由系统来调用 系统在调用它的时候, 并没有创建一个 invokemethod 的对象, 而 callother() 和 showmsg() 方法都是实例方法, 它们被调用时, 都必须有对象的存在 所以必须在 main 中先创建一个对象 ob, 才能调用这两个方法 从这一点来看,main 方法虽然处在 invokemethod 类的内部, 但它的表现却如同在类的 外部 一样 这么解释, 读者可能还会有疑惑 : 为什么 callother() 又能够直接调用 showmsg() 方法, 难道它能保证在调用后者时, 对象已经存在? 答案确实如此, 因为 callother() 本身是实例方法, 它在被执行时, 一定是有对象存在的 基于这个前提, 它才能够直接调用 showmsg() 方法 例 3.15 外部类调用方法示例 这里仍然利用程序 3.24, 另外再写一个类来使用 invokemethod 类中的两个方法 // 文件名 invokeother.java, 程序编号 public class invokeother{ public static void main(string args[]){ invokemethod ob = new invokemethod(); // 创建对象 ob.callother(); // 调用 callother() 方法 注意 : 需要将 invokemethod.java 和 invokeother.java 两个方法放在同一个目录下面, 然后分别编译 后面如无特殊说明, 需要用到两个或两个以上文件的, 都必须放在同一目录下编译 程序 3.25 和程序 3.24 的输出结果完全一样 细心的读者还会发现, 在 invokeother 类 123

25 第 2 篇 Java 面向对象编程中的 main() 方法和 invokemethod 类中的 main() 方法代码完全一样 在 3.7 和 3.8 节中, 还将进一步解释这一现象 在 invokeother 类中, 还可以调用 showmsg() 方法, 形式还是 ob.showmsg() 读者可以自己改动程序 3.25 查看效果 方法调用的参数 在定义一个方法时, 程序员可能会根据需要列出一个参数表, 这些参数被称为形式参数, 简称为形参 在调用方法时, 需要调用者提供与之相匹配的参数表, 被称为实际参数, 简称为实参 这里的匹配有两个条件 : 实参和形参的个数要相等 实参和形参对应位置上的数据类型要相容 即数据类型相同, 或者实参可以做自动类型转换转换成形参类型 在方法调用发生时, 系统会将实参的值按照位置关系一个一个传递给形参, 即第一个实参传给第一个形参, 第二个实参传给第二个形参, 这个过程中, 不会考虑形参和实参的名字 如图 3.5 所示 由于在 Java 中存在两种类型的数据 : 基本类型和复合类型 这两种类型的数据作为参数传递时, 是有区别的 本小节将分别介绍这两种情况 图 3.5 方法调用的传值过程 1. 基本类型作为参数 当方法的参数是基本类型 ( 包括整型 浮点和布尔型 ) 时, 它是通过传值方式进行调用的 这种传递方式的特点是 : 它所传递的实参的值是一个副本 单值传递 实参本质上是一个可求值的表达式, 它所求出来的值是一个基本类型 单向传递 方法内部可以修改形参的值, 但这种修改不会影响到对应的实参 直观来看, 传值过程相当于一个赋值过程, 实参是右值, 形参是左值 它们发生联系只在调用的那一瞬间, 以后二者之间再无关系 例 3.16 单向传值示例 // 文件名 invokebyvalue.java, 程序编号 public class invokebyvalue{ public void trychange(int ix){ ix = ix * 2; // 企图改变参数的值 public void showdiffer(){ int ix = 10; System.out.println(" 调用 trychange 方法之前,ix=" + ix); // 测试是否能改变实参的值 trychange(ix); System.out.println(" 调用 trychange 方法之后,ix=" + ix); public static void main(string args[]){ 124

26 第 3 章对象和类 invokebyvalue va = new invokebyvalue(); va.showdiffer(); 程序的输出如下 : 调用 trychange 方法之前,ix=10 调用 trychange 方法之后,ix=10 从本例中可以看出, 尽管在 trychange() 方法中, 改变了形参 ix 的值, 但对于实参 ix 并没有影响 从这个例子还可以看出, 形参实际上是一个局部变量, 它的作用域仅限于定义它的方法体内部, 实参的名字是否和它相同都没有影响 单向传值可以防止程序员在无意的情况下改变实参的值, 起到了降低程序间数据耦合度的作用 但在某些情况下, 单向传值却会阻碍某些功能的实现 比如, 要写一个方法实现两个参数交换值的功能 初学者可能会写成下面这个样子 : public void swap(int a, int b){ int t=a; a=b; b=t; 然后这样来调用它 : swap(a,b); 很不幸, 调用过后, 会发现,a 和 b 的值没有任何改变 因为在方法 swap 中交换的只是形参 a 和 b 的值, 这对于实参 a 和 b 来说, 没有任何影响 实际上, 在 Java 中, 没有任何简单的方法能够实现上述交换两个基本变量的值, 而只能把上面这段代码写在需要交换的地方 2. 复合类型作为参数 如果形式参数不是基本类型, 而是复合类型, 比如类类型, 那么实参和形参的表现行为和基本类型的参数会有一些区别 如果实参是一个类的对象, 那么在调用相应的方法时, 系统会将该对象的地址值传递给形参 例如, 有一个类 onlytest,actual 是它的一个对象作为实参,form 是它定义的形参对象, 则调用时的传值情形如图 3.6 所示 ( 假定类实例在内存中的存储地址为 0x00ff) 在 Java 中虽然没有 指针 这一概念, 程序员也不需要图 3.6 对象传值调用示例掌握它, 但在系统内部, 仍然是存在指针的 图 3.6 就是指针运用的示例 actual 和 form 指向了同一个对象实例, 其中任何一个变量改变类实例中的值, 都会对另外一个变量有所影响 对象的传值过程, 其实是借用了 C/C++ 中指针传值的方法, 造成的效果也完全相同 下面这个例子展示了对象传值的效果 例 3.17 对象传值示例 // 文件名 onlytest.java, 程序编号

27 第 2 篇 Java 面向对象编程 126 public class onlytest{ private int x = 0; // 设置成员变量 x 的值 public void setx(int ix){ x = ix; // 获取成员变量 x 的值 public int getx(){ return x; 下面这个程序使用上面这个类, 分别声明了一个实参和一个形参 // 文件名 invokebyobject.java, 程序编号 public class invokebyobject{ public void (onlytest form){ int t = form.getx(); // 获取对象 form 的成员变量 x 的值 form.setx(t*2); // 改变对象 form 的成员变量 x 的值 public void { onlytest actual = new onlytest(); actual.setx(100); System.out.println(" 调用 trychange 方法之前,x=" + actual.getx() ); // 测试是否能改变 actual 的成员变量值 trychange(actual); System.out.println(" 调用 trychange 方法之后,x=" + actual.getx() ); public static void main(string args[]){ invokebyobject va = new invokebyobject(); va.showdiffer(); 在程序 3.28 中,showDiffer() 方法先定义一个 actual 对象, 并将成员 x 的值置为 100 而后调用方法 trychange(), 它的形参 form 接收 actual 的值, 根据图 3.6 所示内容, 它们将共用同一个对象 在 trychange() 中改变了 form 的 x 值, 这一改变, 对 actual 也是有效的 程序的输出印证了这一点 : 调用 trychange 方法之前,x=100 调用 trychange 方法之后,x=200 由于 C++ 中提供了传值调用和引用调用两种方式, 于是有些程序员也认为 Java 的对象参数是采用的引用调用 这其实是一种误解,Java 采用的是传地址值的调用方式, 在某些情况下, 虽然和引用调用效果相同 ( 比如上例 ), 但在另外一些情形下, 还是可以看出两者的区别 下面这个例子说明了这一区别 例 3.18 对象传地址值而非引用示例 这里仍然使用例 3.17 中的类 onlytest, 再另外编写一个程序 tryswap // 文件名 tryswap.java, 程序编号 public class tryswap{ // 企图交换 a 和 b 的值 public void swap(onlytest a, onlytest b){ onlytest temp;

28 第 3 章对象和类 temp = a; a = b; b = temp; // 测试能否交换实参的值 public void showdiffer(){ onlytest ox = new onlytest(); // 创建两个对象 onlytest oy = new onlytest(); ox.setx(100); oy.setx(200); System.out.println(" 调用 swap() 方法之前的值 :"); System.out.println(" ox.x = " + ox.getx() + ", oy.x = " + oy.getx()); // 测试是否能交换 ox 和 oy 的值 swap(ox,oy); System.out.println(" 调用 swap() 方法之后的值 :"); System.out.println(" ox.x = " + ox.getx() + ", oy.x = " + oy.getx()); public static void main(string args[]){ tryswap va = new tryswap(); va.showdiffer(); 在方法 swap() 中, 形参是两个 onlytest 的对象 如果是引用调用, 那么交换这两个对象的值, 将对实参 ox 和 oy 产生影响 程序实际运行后输出结果如下 : 调用 swap() 方法之前的值 : ox.x = 100, oy.x = 200 调用 swap() 方法之后的值 : ox.x = 100, oy.x = 200 从以上输出结果中可以看出,ox 和 oy 的值没有受到丝毫影响, 因此它不是引用调用 调用过程可以用图 3.7 和图 3.8 来说明 图 3.7 调用 swap() 时的传值过程 图 3.8 执行 swap() 之后的情形 补充说明一下 : 若有对象 A 和 B, 执行语句 :A=B, 则 A 和 B 都指向了同一个对象, 它们的行为与上述参数传递的行为完全相同 注意 : 通过上述分析可以看出, 在 Java 中, 虽然没有出现显示的指针, 也没有指针这个概念, 但用普通类声明的变量, 本质上和 C/C++ 中的对象指针是一样的 而且, Java 中也没有和 C++ 中的引用类型完全等效的概念 最后总结一下方法参数的使用情况 : 方法不能修改一个基本数据类型的参数 ; 方法可以改变一个对象参数的状态 ; 127

29 第 2 篇 Java 面向对象编程 方法不允许让一个对象参数引用一个新的对象 隐含参数 this 回顾 小节中的例 3.13, 当方法中的局部变量和成员变量同名时, 局部变量会屏蔽掉同名的成员变量 为了访问该成员变量, 需要使用 this. 成员变量 的形式 这个 this 是 Java 定义中的一个关键字 为了让程序员能够在方法中使用 this,java 会将 this 作为一个隐含的参数传递给每一个实例方法 它其实是指向当前对象的一根指针, 直观地理解, 它就是表示 本对象 的意思 this 作为隐含参数传递, 最重要的作用是区分各个对象所拥有的成员 先来回顾 小节程序 3.27 中的类 onlytest, 它拥有一个成员变量 x, 两个方法 setx() 和 getx() 程序员可以使用这个类来创建若干个对象, 这些对象分别拥有自己的成员变量, 相互之间不会干扰 如例 3.19 所示 例 3.19 使用类 onlytest 创建多个对象示例 // 文件名 useonlytest.java, 程序编号 public class useonlytest{ public static void main(string args[]){ onlytest oa = new onlytest(); onlytest ob = new onlytest(); oa.setx(100); // 将成员变量 x 赋值为 100 ob.setx(200); // 将成员变量 x 赋值为 200 System.out.println( "oa 的成员变量 x= " + oa.getx() ); System.out.println( "ob 的成员变量 x= " + ob.getx() ); 程序中分别为两个对象 oa 和 ob 的成员变量赋了不同的值, 然后再分别显示它们的值 程序的输出结果如下 : oa 的成员变量 x= 100 ob 的成员变量 x= 200 这个结果完全在预料之中 但如果深入研究一下, 还是会存在一些疑问 : 到底系统是如何来管理这些对象的? 显然, 不同对象的成员变量一定是单独存放的, 那么当它们都调用 setx() 方法的时候, 这个方法如何知道要为哪一个对象的成员变量 x 赋值? 一种简单的解决办法, 是让每个对象的成员方法也单独存放, 并且和成员变量存放在一起, 它只处理本对象的成员变量 但这种方法实在是太笨, 因为为每个对象存储一套成员方法 ( 而且这些方法的执行语句是完全一样的 ) 需要大量的空间, 完全不符合代码重用的原则 所以, 所有对象共用一套成员方法显然要经济高效得多 但这样又会带来一个问题, 就是这些方法怎样才能区分目前要处理的是哪一个对象的成员变量 解决的答案就是 this 关键字 系统会将 this 指向当前对象, 然后作为参数传递给成员方法 在方法访问成员变量时, 系统会自动为成员变量加上一个 this 作为前缀, 这样就可以区分是哪个对象的成员变量 当然, 程序员也可以显式地加上 this 作前缀 比如,onlyTest 类与下面这种形式等价 : 128

30 第 3 章对象和类 public class onlytest{ private int x = 0; // 设置成员变量 x 的值 public void setx(int ix){ this.x = ix; // 显式地加上 this, 表示本对象的变量 x // 获取成员变量 x 的值 public int getx(){ return this.x; 对于方法 : public void setx(int ix) 系统会自动加上形参 this, 如下 : public void setx(onlytest this, int ix) 当通过 oa.setx(100) 来调用方法时, 系统生成的是 oa.setx(oa,100), 这样就很好地解决了区分各个对象成员的问题 3.6 构造方法 构造方法是类中一种特殊的方法, 它一般由系统在创建对象 ( 即类实例化 ) 时自动调用 构造方法是对象中第一个被执行的方法, 主要用于申请内存以及对类的成员变量进行初始化等操作 构造方法虽然也位于类里面, 但在很多情况下与普通成员方法表现不同, 所以也有人认为它不是成员方法, 而且将其称为 构造器 本书仍然沿用通常的称呼, 将其称为构造方法 构造方法的一般形式为 : 构造方法名 ([ 参数列表 ]){ [this([ 参数列表 ]);] [super([ 参数列表 ]); 语句序列 其中,this 是调用其他的构造方法,super 是调用父类的构造方法 它们都必须放在其他语句的前面 编写式构造方法要注意以下几点 构造方法的名字必须和类的名字完全相同 除了访问权修饰符之外, 不能有其他任何修饰符, 也就不能有返回值 尽管没有返回值, 但并不能用 void 修饰 构造方法不能用 static 和 final 来修饰 一般也不用 private 修饰, 这会导致无法在外部创建对象 构造方法不能由对象显式地调用 一般通过 new 关键字来调用, 或者用 this 和 super 来调用 构造方法的参数列表可以为空, 也可以有参数 根据参数的有无, 可以将构造方法分为无参数的构造方法和带参数的构造方法 129

31 第 2 篇 Java 面向对象编程 用户定义的类可以拥有多个构造方法, 但要求参数列表不同 当用户定义的类未提供任何构造方法时, 系统会自动为其提供一个无参数的构造方法 无参数构造方法的定义和使用 定义一个无参数的构造方法, 从语法上来讲很简单, 请看下面的示例 例 3.20 无参数的构造方法示例 // 文件名 constructnopara.java, 程序编号 public class constructnopara{ private int x = 0; // 定义一个无参数的构造方法, 它必须和类同名 public constructnopara(){ System.out.println(" 这是无参数的构造方法 "); x = 100; // 为成员变量赋值 // 获取成员变量 x 的值 public int getx(){ return x; public static void main(string args[]){ constructnopara oa = new constructnopara(); System.out.println("x = " + oa.getx() ); // 隐式调用无参数的构造方法 // 输出成员变量 x 的值 调用构造方法使用的是 new constructnopara(), 这是一种隐式的调用方法, 不能写成 oa.constructnopara() 的形式 注意到成员变量 x, 它在定义的时候已经赋了初值 在构造方法中, 先是输出一条信息, 然后再次为 x 赋值 由于构造方法的执行在定义成员变量之后, 它会覆盖掉原来 x 的初值, 所以 x 的值为 100 程序的输出结果如下: 这是无参数的构造方法 x = 100 对于初学者而言, 最容易犯的错误是在构造方法之前加上 void, 变成下面这个样子 : public class constructnopara{ private int x = 0; // 试图定义一个无参数的构造方法 public void constructnopara(){ // 这里加了一个 void System.out.println(" 这是无参数的构造方法 "); x = 100; // 为成员变量赋值 // 获取成员变量 x 的值 public int getx(){ return x; public static void main(string args[]){ constructnopara oa = new constructnopara(); // 隐式调用无参数的构造方法 130

32 第 3 章对象和类 System.out.println("x = " + oa.getx() ); // 输出成员变量 x 的值 这个程序仍然可以通过编译, 但运行结果可能会出人意料 它的输出结果如下 : x = 0 这表明, 程序员自己定义的无参数的构造方法根本就没有执行 这是因为加上 void 修饰符之后,constructNoPara() 不再是一个构造方法, 而成了一个普通方法 语句 constructnopara oa = new constructnopara(); 并不是调用程序员自己定义的 构造方法, 而是调用了系统提供的默认的无参数的构造方法, 这个方法其实什么事情也没做, 自然也就不会更改 x 的值 说明 :C++ 程序员不会犯此类错误 因为在 C++ 中, 如果在构造方法前面加上 void, 编译器将报错 注意 : 构造方法前的访问权限修饰符同样有 4 种, 但通常不会是 private 类型 因为用它来修饰的话, 将无法在外部使用该构造方法 带参数构造方法的定义和使用 在很多时候, 需要根据不同的情况为成员变量赋不同的初值, 这就需要传递参数给构造方法 因此,Java 中允许定义带参数的构造方法, 而且这种带参数的构造方法还可以定义多个 ( 前提是参数列表有区别 ), 这种现象被称为构造方法的重载 Java 规定, 如果程序员一个构造方法都不定义, 那么系统会自动为其加上一个不带参数的构造方法 如果程序员至少定义了一个构造方法, 那么系统不会再提供不带参数的构造方法 当用 new 来创建对象时, 需要提供类型相容的参数, 否则编译器将报错 例 3.21 带参数的构造方法示例 // 文件名 constructwithpara.java, 程序编号 public class constructwithpara{ private int x = 0; // 定义一个带参数的构造方法 public constructwithpara(int ix){ System.out.println(" 这是带参数的构造方法 "); x = ix; // 为成员变量赋值 // 获取成员变量 x 的值 public int getx(){ return x; public static void main(string args[]){ constructwithpara oa = new constructwithpara(100); System.out.println("x = " + oa.getx() ); // 隐式调用带参数的构造方法 131

33 第 2 篇 Java 面向对象编程 这个程序的流程和程序 3.31 完全一样, 只是其中的构造方法多了一个参数而已 程序运行的结果如下 : 这是带参数的构造方法 x = 100 这个程序从表面上看没有什么问题, 但实际上它存在着一个很大的隐患 如果将类 constructwithpara 提供给其他的程序员使用, 使用者很有可能会按照一般的习惯这么来创建一个对象 : constructwithpara oa = new constructwithpara(); 试图使用 x 的默认值 但这样是无法通过编译的, 因为系统不会再为 constructwithpara 类提供无参数的构造方法 当此类被其他类继承时, 这一问题显得越发严重, 它甚至会导致根本无法写出一个子类 因此, 强烈建议程序员在定义带参数的构造方法时, 也要定义一个不带参数的构造方法, 即便这个方法什么事情也不做 所以程序 3.32 应该改成下面这个样子 : // 文件名 constructwithpara.java, 程序编号 public class constructwithpara{ private int x = 0; // 定义一个带参数的构造方法 public constructwithpara(int ix){ System.out.println(" 这是带参数的构造方法 "); x = ix; // 为成员变量赋值 // 定义一个不带参数的构造方法 public constructwithpara(){ // 获取成员变量 x 的值 public int getx(){ return x; public static void main(string args[]){ constructwithpara oa = new constructwithpara(100); System.out.println("x = " + oa.getx() ); this 关键字和构造方法的调用 // 隐式调用带参数的构造方法 在 小节中, 已经介绍了 this 关键字的作用 作为隐含参数指向本对象 其实 this 关键字还有一个作用, 就是用来显示地调用构造方法 它的使用格式如下 : this([ 参数列表 ]) 系统将根据参数列表来决定调用哪一个构造方法 使用 this 时还需注意下面几点 用 this 调用构造方法时, 该语句只能用在构造方法中 this 语句必须是构造方法中的第一条语句 132

34 第 3 章对象和类 和 new 不同,this 虽然可以调用构造方法, 但它只是执行构造方法中的语句, 并不会创建对象 例 3.22 用 this 调用构造方法示例 这里仍然使用程序 3.33, 并在无参数的构造方法中加上 this 语句来为 x 赋初值 // 文件名 constructwithpara.java, 程序编号 public class constructwithpara{ private int x = 0; // 定义一个带参数的构造方法 public constructwithpara(int ix){ System.out.println(" 这是带参数的构造方法 "); x = ix; // 为成员变量赋值 // 定义一个不带参数的构造方法 public constructwithpara(){ this(100); // 调用带参数的构造方法为 x 赋值 System.out.println(" 这是无参数的构造方法 "); // 获取成员变量 x 的值 public int getx(){ return x; public static void main(string args[]){ constructwithpara oa = new constructwithpara(); // 隐式调用无参数的构造方法 System.out.println("x = " + oa.getx() ); 在 main() 方法中利用无参数的构造方法来创建对象, 而在无参数的构造方法中, 用 this 来调用带参数的构造方法, 然后再输出一条信息 程序输出结果如下 : 这是带参数的构造方法这是无参数的构造方法 x = 100 在 constructwithpara() 方法中, 特别注意不要写成下面这个样子 : public constructwithpara(){ System.out.println(" 这是无参数的构造方法 "); this(100); // 调用带参数的构造方法为 x 赋值 这样编译会出错, 因为 this 调用构造方法只能作为第一条语句 读者可能会觉得程序 3.34 用 this 调用另外一个构造方法为 x 赋值过于麻烦, 不如直接为 x 赋值更简单 当然, 这只是一个示例程序, 这么做的原因在于 : 很多情况下, 多个构造方法可能会做相同的事情, 只是参数有点区别, 这就可以将这段相同的代码单独抽取出来成为一个构造方法, 然后使用 this 来调用它 3.7 静态方法 前面已经介绍过, 成员变量分为实例变量和静态变量 其中实例变量属于某一个具体 133

35 第 2 篇 Java 面向对象编程的实例, 必须在类实例化后才真正存在, 不同的对象拥有不同的实例变量 而静态变量被该类所有的对象公有 ( 相当于全局变量 ), 不需要实例化就已经存在 方法也可分为实例方法和静态方法 其中, 实例方法必须在类实例化之后通过对象来调用, 而静态方法可以在类实例化之前就使用 与成员变量不同的是 : 无论哪种方法, 在内存中只有一份 无论该类有多少个实例, 都共用同一个方法 本节以前的例子中, 除了 main() 方法, 其余的方法都是实例方法, 而 main() 则是一个静态方法, 所以它才能够被系统直接调用 静态方法的声明和定义 定义一个静态方法和定义一个实例方法, 在形式上并没有什么区别, 只是在声明的头部, 需要加上一个关键字 static 它的一般语法形式如下: [ 访问权限修饰符 ] static [ 返回值类型 ] 方法名 ([ 参数列表 ]){ 语句序列 例如下面是一个静态的方法 : public static void stfun(){ System.out.println(" 这是一个静态方法 "); 静态方法和实例方法的区别 静态方法和实例方法的区别主要体现在以下两个方面 在外部调用静态方法时, 可以使用 类名. 方法名 的方式, 也可以使用 对象名. 方法名 的方式 ; 而实例方法只有后面这种方式 也就是说, 调用静态方法可以无需创建对象 静态方法在访问本类的成员时, 只允许访问静态成员 ( 即静态成员变量和静态方法 ), 而不允许访问实例成员变量和实例方法 ; 实例方法则无此限制 下面几个例子展示了这一区别 例 3.23 调用静态方法示例 134 // 文件名 hasstaticmethod.java, 程序编号 public class hasstaticmethod{ // 定义一个静态方法 public static void callme(){ System.out.println("This is a static method."); 下面这个程序使用两种形式来调用静态方法 // 文件名 invokestaticmethod.java, 程序编号 public class invokestaticmethod{ public static void main(string args[]){ hasstaticmethod.callme(); // 不创建对象, 直接调用静态方法

36 第 3 章对象和类 hasstaticmethod oa = new hasstaticmethod(); // 创建一个对象 oa.callme(); // 利用对象来调用静态方法 程序 3.36 两次调用静态方法, 都是允许的, 程序的输出如下 : This is a static method. This is a static method. 允许不创建对象而调用静态方法, 是 Java 为了减少程序员调用某些常用方法时的麻烦, 而允许程序员按照传统的 C 语言中使用函数的方式来使用方法 典型的例子是前面某些程序中使用 Math.ramdon() 来获取随机数 例 3.24 静态方法访问成员变量示例 // 文件名 accessmember.java, 程序编号 class accessmember{ private static int sa; // 定义一个静态成员变量 private int ia; // 定义一个实例成员变量 // 下面定义一个静态方法 static void statmethod(){ int i = 0; // 正确, 可以有自己的局部变量 sa = 10; // 正确, 静态方法可以使用静态变量 otherstat(); // 正确, 可以调用静态方法 ia = 20; // 错误, 不能使用实例变量 insmethod(); // 错误, 不能调用实例方法 static void otherstat(){ // 下面定义一个实例方法 void insmethod(){ int i = 0; sa = 15; ia = 30; statmethod(); // 正确, 可以有自己的局部变量 // 正确, 可以使用静态变量 // 正确, 可以使用实例变量 // 正确, 可以调用静态方法 本例其实可以概括成一句话 : 静态方法只能访问静态成员, 实例方法可以访问静态和实例成员 之所以不允许静态方法访问实例成员变量, 是因为实例成员变量是属于某个对象的, 而静态方法在执行时, 并不一定存在对象 同样, 因为实例方法可以访问实例成员变量, 如果允许静态方法调用实例方法, 将间接地允许它使用实例成员变量, 所以它也不能调用实例方法 基于同样的道理, 静态方法中也不能使用关键字 this main() 方法是一个典型的静态方法, 它同样遵循一般静态方法的规则, 所以它可以由系统在创建对象之前就调用 下面这个程序有个错误, 请读者仔细查看 public class haserror{ int insvar = 100; // 这里定义的非静态变量, 不能在静态的 main 主方法中引用 public static void main(string args[]){ 135

37 第 2 篇 Java 面向对象编程 System.out.println("insVar = " + insvar); 静态代码块 在类中, 可以将某一块代码声明为静态的, 这样的程序块叫静态初始化段 静态代码块的一般形式如下 : static { 语句序列 静态代码块只能定义在类里面, 它独立于任何方法, 不能定义在方法里面 静态代码块里面的变量都是局部变量, 只在本块内有效 静态代码块会在类被加载时自动执行, 而无论加载者是 JVM 还是其他的类 一个类中允许定义多个静态代码块, 执行的顺序根据定义的顺序进行 静态代码块只能访问类的静态成员, 而不允许访问实例成员 例 3.25 静态代码块运行示例 1 // 文件名 staticblock.java, 程序编号 public class staticblock{ // 定义一个普通的 main() 方法 public static void main(string args[]){ System.out.println("This is main method."); // 定义一个静态代码块 static{ System.out.println("This is static block."); int stvar = 0; // 这是一个局部变量, 只在本块内有效 编译通过后, 用 java 命令加载本程序, 会得到如下输出结果 : This is static block. This is main method. 从以上输出结果中可以看出, 静态代码块甚至在 main() 方法之前就被执行 在 main() 方法中可以完成的任务在静态代码块中都可以完成 但是二者在执行上仍然有一些区别, 请看下例 例 3.26 静态代码块和 main() 方法的区别 这里仍然使用例 3.25 中的 staticblock 类, 然后新定义一个类来使用它 // 文件名 usestaticblock.java, 程序编号 public class usestaticbolck{ public static void main(string args[]){ new staticblock(); // 创建一个 staticblock 的对象 136

38 第 3 章对象和类 本程序没有像以前的程序那样, 在创建对象时使用一个变量来接收对象, 因为这个程序在后面并不需要用到这个变量 程序的输出如下 : This is static block. 这一次, 只执行了静态代码块,main() 方法在这种情况下是不会被执行的 最后来写一个复杂一点的静态代码块的例子, 它综合体现了静态代码块的使用方法, 请读者注意注释说明 例 3.27 静态代码块使用示例 2 // 文件名 staticblock.java, 程序编号 public class staticblock{ static int stmember = 100; // 定义静态成员变量 public static void main(string args[]){ System.out.println("This is main method."); // 第一个静态代码块 static{ System.out.println("This is first static block."); stmember = 200; // 访问静态成员变量 staticblock oa = new staticblock(); // 创建对象 System.out.println("stMember = " + oa.stmember); statfun(); // 调用静态方法 // 定义一个静态方法 static void statfun(){ System.out.println("This is a static method."); // 第二个静态代码块 static{ System.out.println("This is second static block."); 程序运行的结果如下 : This is first static block. stmember = 200 This is a static method. This is second static block. This is main method 再论静态成员变量 在前面的 小节中已经介绍过静态成员变量, 不过那里的静态成员变量都是一些基本类型 Java 允许以类作为静态成员变量的类型, 那么静态成员变量就是一个对象 如果是基本数据类型的静态成员变量, 在类的外部可以不必创建对象就直接使用 但如果静态成员是对象, 问题就要复杂得多 因为对象所属的类, 既可能有静态成员, 也可能有实例成员 而其中的实例成员必须要在对象实例化后才能使用, 问题的核心在于 : 系统是否会为静态的类变量创建实例 137

39 第 2 篇 Java 面向对象编程 例 3.28 对象作为静态成员使用示例 // 文件名 supplytest.java, 程序编号 public class supplytest{ // 定义一个静态方法供测试用 public static void statshow(){ System.out.println(" 这是静态方法 "); // 定义一个实例方法供测试用 public void instshow(){ System.out.println(" 这是实例方法 "); 下面这个程序中, 定义了一个 supplytest 类型的变量, 作为静态成员, 没有显式地实例化它 // 文件名 hasstatmember.java, 程序编号 public class hasstatmember{ static supplytest stvar; // 定义一个静态成员 public static void main(string args[]){ stvar.statshow(); // 调用静态方法 stvar.instshow(); // 调用实例方法 这个程序可以编译通过, 但它运行的结果如下 : 这是静态方法 Exception in thread "main" java.lang.nullpointerexception at hasstatmember.main(hasstatmember.java:5) 从运行结果中可以看出, 静态方法被正常执行, 但实例方法不能执行, 原因是未创建对象实例 这说明尽管 stvar 被声明成 static 类型, 系统仍然不会自动为它创建对象, 所以程序 3.42 必须改成如下内容才能正常运行 // 文件名 hasstatmember.java, 程序编号 public class hasstatmember{ static supplytest stvar = new supplytest(); public static void main(string args[]){ stvar.statshow(); stvar.instshow(); 程序的输出结果是 : 这是静态方法这是实例方法 // 定义一个静态成员并实例化它 // 调用静态方法 // 调用实例方法 从输出结果中可以看出,stVar 的实例化是在定义时完成的, 这意味着在 hasstatmember 类的外部可以像在内部一样使用它 下面这个程序演示了对 stvar 的使用形式 // 文件名 usestvar.java, 程序编号

40 第 3 章对象和类 public class usestvar{ public static void main(string args[]){ hasstatmember.stvar.statshow(); // 调用静态方法 hasstatmember.stvar.instshow(); // 调用实例方法 程序的输出结果如下 : 这是静态方法这是实例方法 无论是静态方法还是实例方法, 都是通过 类名. 静态变量名. 方法名 的形式来使用的 读者可能会觉得这种形式有点眼熟 确实如此, 前面大量使用的 System.out.println 就是这种形式 其中,System 是系统预定义好的一个类,out 是它的一个静态成员,println 是 out 的一个实例方法 3.8 main() 方法和命令行参数 main() 方法是一个重要而又特殊的方法 它是 Java 应用程序的入口,JVM 在运行字节码文件时, 做完初始化之后, 就会查找 main() 方法, 从这里开始整个程序的运行 main() 方法是静态方法, 它由类共有而不是属于类的某个实例, 所以系统可以直接调用 main() 方法而无需创建它所属的类的实例 ( 实际上这也是做不到的 ) 因此在运行 main() 方法时, 只能使用该类中的静态成员, 如果要使用实例成员, 需要先创建该类的实例对象, 然后用对象来访问实例成员 main() 方法只能被系统调用, 不能被其他任何方法或类调用, 这是它和一般静态方法的区别 例 3.29 main() 方法使用示例 // 文件名 showmain.java, 程序编号 public class showmain{ private static int sx = 100; private int ix = 200; public static void main(string args[]){ System.out.println("sx=" + sx); // 正确, 可以访问静态成员 showmain oa = new showmain(); // 创建本类的一个实例对象 System.out.println("oa.ix=" + oa.ix); // 通过对象来访问实例成员 程序的输出结果如下 : sx=100 oa.ix=200 在 main() 方法的括号里面并不为空, 它有一个形式参数 String args[] 其中,String 是 Java 预定义的字符串类,args[] 是一个数组, 它有若干个元素, 每个元素都是一个字符串 由于 main() 方法只能由系统调用, 因此它的参数也只能由系统传递给它 系统所传递的参数则来自于用户的输入, 对于控制台程序而言, 在命令行执行一个程序通常的形式是 : 139

41 第 2 篇 Java 面向对象编程 java 类名 [ 参数列表 ] 其中的参数列表中可以容纳多个参数, 参数间以空格或制表符隔开, 它们被称为命令行参数 系统传递给 main() 方法的实际参数正是这些命令行参数 由于 Java 中数组的下标是从 0 开始的, 所以形式参数中的 args[0],,args[n-1] 依次对应第 1,,n 个参数 下面这个例子展示了 main() 方法是如何接收这些命令行参数的 例 3.30 命令行参数使用示例 // 文件名 getlinepara.java, 程序编号 class getlinepara{ public static void main(string args[]) { // 依次获取命令行参数并输出 for(int i=0;i<args.length;i++) System.out.println(" 第 "+i+" 个参数是 :"+args[i]); 在程序的第 4 行, 用到了一个属性 :args.length 在 Java 中, 数组也是预定义的类, 它拥有属性 length, 用来描述当前数组所拥有的元素 若命令行中没有参数, 则该值为 0, 否则就是参数的个数 若在命令行输入下列命令 : java getlinepara one two three four 相应的输出为 : 第 0 个参数是 :one 第 1 个参数是 :two 第 2 个参数是 :three 第 3 个参数是 :four 注意 : 和 C/C++ 不同,Java 的命令行参数中不包括被执行程序本身 在命令行参数中, 各个参数之间以空格分隔, 但在某些情况下, 这种处理方式并不合适 比如需要程序处理一个在某目录下的文件, 但是该目录中间有空格, 这就会导致程序无法得到正确的文件路径 例如, 在命令行输入 : java getlinepara c:\my Document\test.java 相应的输出为 : 第 0 个参数是 :c:\my 第 1 个参数是 :Document\test.java 它把一个参数拆成两个来处理, 显然不符合程序员的设想 在这种情况下, 用户需要将命令行参数用双引号括起来 上面的命令应该写成这个样子 : java getlinepara "c:\my Document\test.java" 相应的输出结果为 : 第 0 个参数是 :c:\my Document\test.java 140

42 第 3 章对象和类 3.9 终结处理与垃圾回收 对象的释放和垃圾收集机制 Java 通过一个 垃圾收集机制 来解决对象释放后的内存管理问题 当一个对象不再被引用的时候, 垃圾收集机制会收回它占领的空间, 供以后的新对象使用 Java 有堆内存和栈内存之分, 其中堆是一个运行时数据区, 类的实例 ( 对象 ) 从中分配空间 Java 虚拟机 (JVM) 的堆中储存着正在运行的应用程序所建立的所有对象, 这些对象通过 new newarray anewarray 和 multianewarray 等指令建立, 但是它们不需要程序代码来显式地释放 一般来说, 堆是由垃圾回收来负责的, 尽管 JVM 规范并不要求特殊的垃圾回收技术, 甚至根本就不需要垃圾回收, 但是由于内存的有限性,JVM 在实现的时候都有一个由垃圾回收所管理的堆 垃圾回收是一种动态存储管理技术, 它自动地释放不再被程序引用的对象, 按照特定的垃圾收集算法来实现资源自动回收的功能 在 C++ 中, 对象所占的内存在程序结束运行之前一直被占用, 在明确释放之前不能分配给其他对象 ; 而在 Java 中, 当没有对象引用指向原先分配给某个对象的内存时, 该内存便成为垃圾 JVM 的一个系统级线程会自动释放该内存块 垃圾收集意味着程序不再需要的对象是 无用信息, 这些信息将被丢弃 当一个对象不再被引用的时候, 内存回收它占用的空间, 以便空间被后来的新对象使用 事实上, 除了释放没用的对象, 垃圾收集也可以清除内存记录碎片 由于创建对象和垃圾收集器释放丢弃对象所占的内存空间, 内存会出现碎片 碎片是分配给对象的内存块之间的空闲内存洞 碎片整理将所占用的堆内存移到堆的一端,JVM 将整理出的内存分配给新的对象 垃圾收集能自动释放内存空间, 减轻编程的负担 这使 Java 虚拟机具有一些优点 首先, 它能使编程效率提高 在没有垃圾收集机制的时候, 可能要花许多时间来解决一个难懂的存储器问题 在用 Java 语言编程的时候, 靠垃圾收集机制可大大缩短时间 ; 其次是它保护程序的完整性, 垃圾收集是 Java 语言安全性策略的一个重要部分 垃圾收集的一个潜在的缺点是它的开销影响程序性能 Java 虚拟机必须追踪运行程序中有用的对象, 而且最终释放没用的对象 这一个过程需要花费处理器的时间 其次垃圾收集算法的不完备性, 早先采用的某些垃圾收集算法就不能保证 100% 收集到所有的废弃内存 当然随着垃圾收集算法的不断改进以及软硬件运行效率的不断提升, 这些问题都可以迎刃而解 为了节省存储空间, 对象在不再需要之后就应该被释放掉 Java 和 C++ 一个显著的区别就是对象的释放是自动的, 无需程序员操心 这极大地降低了程序员编程上的负担, 也使得内存泄漏发生的风险降到最低 finalize() 终结处理方法 像 C++ 这样的语言, 有显示的析构器方法, 其中放置了一些当对象不再使用时所需要用到的清理代码, 最常见的是回收分配给对象的内存空间 由于 Java 有自动垃圾收集机制, 141

43 第 2 篇 Java 面向对象编程 不需要程序员干预, 所以 Java 不支持析构器 垃圾收集器只知道释放那些由 new 分配的内存, 所以不知道如何释放对象的 特殊 内存, 如果对象使用了内存之外的其他资源, 如没有使用 new 创建的内存区域, 当这类资源不再需要的时候,JVM 将无法自动释放 为解决这个问题,Java 提供了一个 finalize() 方法, 又称为结束方法 它是从 Object 类中继承下来的, 每一个类都拥有此方法 它的工作原理是 : 一旦垃圾收集器准备好释放对象占用的存储空间, 它首先调用 finalize() 方法, 而且只有在下一次垃圾收集过程中, 才会真正回收对象所占用的内存 所以如果使用 finalize() 方法, 就可以在垃圾收集期间进行一些重要的清除或清扫工作 也就是说这个方法会在垃圾收集器清除对象之前被调用, 如果用户觉得有必要, 可以重写此方法, 完成预定义的任务 它的声明形式如下 : protected void finalize(){ 语句序列 但是, 程序员无法预测垃圾回收器会在何时启用, 也就无法预测结束方法的执行时机, 所以不要使用本方法来回收任何短缺的资源 如果某个资源在使用完毕后必须立刻回收, 那么类的设计者需要提供一个 dispose 或 close 这样的方法, 用来做相应的操作 类的使用者一旦有必要结束掉对象, 就可以直接显示地调用这些方法 Java 垃圾回收的工作原理 要理解 Java 垃圾回收的工作原理, 先要了解一下 Java 分配对象的方式 Java 的堆更像一个传送带, 每分配一个新对象, 它就往前移动一格 这意味着对象存储空间的分配速度相当快 Java 的 堆指针 只是简单地移动到尚未分配的领域 也就是说, 分配空间的时候, 堆指针 只管依次往前移动而不管后面的对象是否还要被释放掉 如果可用内存耗尽之前程序就退出就再好不过了, 这样的话垃圾回收器压根就不会被激活 但是由于 堆指针 只管依次往前移动, 内存总会有被耗尽的时间, 此时垃圾回收器就开始释放内存 JVM 会判断当堆栈或静态存储区没有对这个对象的引用时, 就表示这个对象已经没有存在的意义了, 它就应该被回收了 有两种方法来判定这个对象有没有被引用 : 第一种是遍历堆上的对象找引用 ; 第二种是遍历堆栈或静态存储区的引用找对象 前者的实现叫做 引用计数法, 意思就是当有引用连接至对象时, 引用计数加 1, 当引用离开作用域或被置为 null 时, 引用计数减 1 这种方法有个缺陷, 如果对象之间存在循环引用, 可能会出现 对象应该被回收, 但引用计数却不为零 的情况 Java 采用的是后者, 在这种方式下,Java 虚拟机采用一种 自适应 的垃圾回收技术, 对于找到非垃圾的存活对象,Java 有两种方式 一种是 停止 - 复制 理论上是先暂停程序的运行( 所以它不属于后台回收模式 ), 然后将所有存活的对象从当前堆复制到另一个堆, 没有被复制的全是垃圾 当对象被复制到新堆上时, 它们是一个挨着一个的, 所以新堆保持紧凑排列 ( 这也是为什么分配对象的时候 堆指针 只管依次往前移动 ) 然后就可以按前述方法简单 直接地分配内存了 这将导致大量内存复制行为, 内存分配是以较大的 块 为单位的 有了块之后, 垃圾回 142

44 第 3 章对象和类 收器就可以不往堆里复制对象了, 而是直接就可以往废弃的块里复制对象 另一种是 标记 - 清扫 它的思路同样是从堆栈和静态存储区出发, 遍历所有的引用, 进而找出所有存活的对象 每当它找到一个存活对象, 就会给对象一个标记 这个过程中不会回收任何对象 只有全部标记完成时, 没有标记的对象将被释放, 不会发生任何复制工作, 所以剩下的堆空间是不连续的, 然后垃圾回收器重新整理剩余的对象, 使它们是连续排列的 当垃圾回收器第一次启动时, 它执行的是 停止 - 复制 方式, 因为这个时刻内存有太多的垃圾 然后 Java 虚拟机会进行监视, 如果所有对象都很稳定, 垃圾回收器的效率降低的话, 就切换到 标记 - 清扫 方式 ; 同样,Java 虚拟机会跟踪 标记 - 清扫 效果, 要是堆空间出现很多碎片, 就会切换到 停止 - 复制 方式 这就是所谓的 自适应 技术 实质上, 停止 - 复制 和 标记 - 清扫 无非就是 在大量的垃圾中找干净的东西和在大量干净的东西里找垃圾 不同的环境用不同的方式, 这样做完全是为了提高效率, 要知道, 无论哪种方式,Java 都会先暂停程序的运行, 所以, 垃圾回收器的效率其实是很低的 Java 用效率换回了 C++ 没有的垃圾回收器和运行时的灵活是十分明智的, 而且通过垃圾回收器对对象重新排列, 实现了一种高速的 有无限空间可供分配的堆模型 3.10 本地方法 如果应用程序需要使用系统特性或设备, 比如, 调用操作系统的 API 函数, 可能使用 Java 编写这样的代码是非常麻烦甚至是不可能的 在这种情况下, 需要调用其他语言 ( 比如 C/C++) 编写的代码, 这些代码被称为本地 (native) 方法或本机方法 全面讨论本地方法的编写是一件细致而繁琐的工作, 本节不打算过于深入地讨论某些细节, 仅举一个简单的例子来说明如何使用本地方法 在阅读本节之前, 读者必须具有 C 语言编程的经验, 否则就只能跳过本节了 ( 这并不影响后续章节的阅读 ) 例 3.31 用 Java 语言来调用一个 C 函数, 打印出消息 Hello,Native World! 首先, 必须在一个类中声明本地方法, 这需要用到一个关键字 native 下面是用 Java 编写的程序 // 文件名 HelloNative.java, 程序编号 public class HelloNative{ public native static void greeting(); 在本程序中, 将本地方法声明为 static 类型 本地方法既可以是静态方法, 也可以是实例方法 虽然这个方法不带任何参数, 但本地方法是允许带参数的 不过参数传递是件比较麻烦的事情, 尤其是当参数是对象时 具体细节请读者查阅 JDK 手册 本地方法只需要方法的声明部分, 不需要定义部分 因为它的定义是由其他语言来完成的 然后编写一个相应的 C 函数 程序员必须完全按照 JVM 所规定的方式来给函数命名, 这些命名规则包括 : 143

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d

More information

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP:  ******************* * 关于 Java 测试试题 ****** ******************* * 关于 Java 测试试题 ******************* 問 1 运行下面的程序, 选出一个正确的运行结果 public class Sample { public static void main(string[] args) { int[] test = { 1, 2, 3, 4, 5 ; for(int i = 1 ; i System.out.print(test[i]);

More information

软件工程文档编制

软件工程文档编制 实训抽象类 一 实训目标 掌握抽象类的定义 使用 掌握运行时多态 二 知识点 抽象类的语法格式如下 : public abstract class ClassName abstract void 方法名称 ( 参数 ); // 非抽象方法的实现代码 在使用抽象类时需要注意如下几点 : 1 抽象类不能被实例化, 实例化的工作应该交由它的子类来完成 2 抽象方法必须由子类来进行重写 3 只要包含一个抽象方法的抽象类,

More information

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 类的复用 组合 (composition): has-a 关系 class MyType { public int i; public double d; public char c; public void set(double x) { d =

More information

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票

OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3 提交时间 3 月 29 日晚 9 点 Piazza Project 2 投票 复习 创建对象 构造函数 函数重载 : 函数 = 函数名 + 参数列表 public class MyType { int i; double d; char c; void set(double x)

More information

1 下列类头定义中, 正确的是 面向对象程序设计网络课程 A class x { } B public x extends y { } C public class x extends y {.} D class x extends y implements y1 { } 2 现有两个类 A B,

1 下列类头定义中, 正确的是 面向对象程序设计网络课程 A class x { } B public x extends y { } C public class x extends y {.} D class x extends y implements y1 { } 2 现有两个类 A B, 1 下列类头定义中, 正确的是 A class x B public x extends y C public class x extends y. D class x extends y implements y1 2 现有两个类 A B, 以下描述中表示 B 继承自 A 的是 (D ) A) class A extends B B) class B implements A C) class A

More information

无类继承.key

无类继承.key 无类继承 JavaScript 面向对象的根基 周爱 民 / aimingoo aiming@gmail.com https://aimingoo.github.io https://github.com/aimingoo rand = new Person("Rand McKinnon",... https://docs.oracle.com/cd/e19957-01/816-6408-10/object.htm#1193255

More information

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢   学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 Email: 51141201063@ecnu.cn 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料 OOP with Java Java 类型 引用 不可变类型 对象存储位置 作用域 OOP

More information

模板

模板 制作人 : 张刚 目录 类和对象 面向对象程序设计基本特征 类的声明 构造方法 成员变量和方法 封装 继承 多态 包 访问控制 final static 抽象类和接口 内部类 沈阳工业大学软件学院 Java 课程教研组 Page 2 核心知识点 类 对象 三个基本特征 类的基本结构 成员变量 构造方法 成员方法 类实例 对象创建和操作 沈阳工业大学软件学院 Java 课程教研组 Page 3 1.

More information

Microsoft Word - 新1-12.doc

Microsoft Word - 新1-12.doc 实训 5 面向对象编程练习 实训 5 面向对象编程练习 5.1 实训目的 通过编程和上机实验理解 Java 语言是如何体现面向对象编程基本思想 以及如何创建类 和对象 了解成员变量和成员方法的特性 5.2 实训要求 编写一个体现面向对象思想的程序 编写一个创建对象和使用对象的方法的程序 5.3 实训内容 5.3.1 创建对象并使用对象 1 定义一个 Person 类 可以在应用程序中使用该类 成员属性

More information

chap07.key

chap07.key #include void two(); void three(); int main() printf("i'm in main.\n"); two(); return 0; void two() printf("i'm in two.\n"); three(); void three() printf("i'm in three.\n"); void, int 标识符逗号分隔,

More information

Guava学习之Resources

Guava学习之Resources Resources 提供提供操作 classpath 路径下所有资源的方法 除非另有说明, 否则类中所有方法的参数都不能为 null 虽然有些方法的参数是 URL 类型的, 但是这些方法实现通常不是以 HTTP 完成的 ; 同时这些资源也非 classpath 路径下的 下面两个函数都是根据资源的名称得到其绝对路径, 从函数里面可以看出,Resources 类中的 getresource 函数都是基于

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc 第 3 章 lambda 表达式及其应用 lambda 表达式是 Java 8 提供的一种新特性, 它使得 Java 也能像 C# 和 C++ 语言一样进行简单的 函数式编程, 这不仅简化了某些通用结构的实现方式, 也大大增强了 Java 语言的表达功能 3.1 lambda 表达式简介 lambda 表达式是基于数学中的 λ 演算得名, 本质上就是一个没有方法名的匿名方法 例如, 有一个方法定义如下

More information

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 odps-sdk 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基 开放数据处理服务 ODPS SDK SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基础功能的主体接口, 搜索关键词 "odpssdk-core" 一些

More information

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 月 3 日 1 1 INPUTOUTPUT 1 InputOutput 题目描述 用 cin 输入你的姓名 ( 没有空格 ) 和年龄 ( 整数 ), 并用 cout 输出 输入输出符合以下范例 输入 master 999 输出 I am master, 999 years old. 注意 "," 后面有一个空格,"." 结束,

More information

教案模板4-2

教案模板4-2 传智播客 Java 基础入门 教学设计 课程名称 : Java 基础入门 授课年级 : 2014 年级 授课学期 : 2014 学年第一学期 教师姓名 : 某某老师 2014 年 02 月 09 日 课题名称第 3 章面向对象上 计划学时 6 课时 Java 是一种面向对象的语言, 认识面向对象的编程思想对于 Java 学习至关重 内容分析 要 在面向对象中, 有两个重要的概念, 分别是类和对象,

More information

Microsoft Word - word模板-教师.doc

Microsoft Word - word模板-教师.doc 传智播客 Java 基础入门 教学设计 课程名称 : Java 基础入门 授课年级 : 2014 年级 授课学期 : 2014 学年第一学期 教师姓名 : 某某老师 2014 年 02 月 09 日 课题名称内容分析教学目标及基本要求重点及措施难点及措施 计划第 3 章面向对象上 6 课时学时 Java 是一种面向对象的语言, 认识面向对象的编程思想对于 Java 学习至关重要 在面向对象中, 有两个重要的概念,

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 Java 包 创建包 : package 语句, 包结构与目录结构一致 使用包 : import restaurant/ - people/ - Cook.class - Waiter.class - tools/ - Fork.class - Table.class

More information

Microsoft PowerPoint - 08_OO_CJC.ppt

Microsoft PowerPoint - 08_OO_CJC.ppt C++ 中的 Hello World! C 程序设计语言 第 8 章 OO 与 C++ Java C# 孙志岗 sun@hit.edu.cn http://sunner.cn 兼容 C 语言的 : #include int main() printf("hello,, world!\n"); return 0; 更具 C++ 味道的 : #include int

More information

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式]

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式] 用户定义类型 User-defined Datatypes classes and structs 几何向量 (Geometry Vector) 二维平面上的向量由起点和终点构成 每个点包含两个坐标 (x, y), 因此一个向量需要四个实数表示 Start= (0.9,1.5) Start= (0.4,0.8) int main() { double xstart = 0.4; double xend

More information

新・解きながら学ぶJava

新・解きながら学ぶJava 481! 41, 74!= 40, 270 " 4 % 23, 25 %% 121 %c 425 %d 121 %o 121 %x 121 & 199 && 48 ' 81, 425 ( ) 14, 17 ( ) 128 ( ) 183 * 23 */ 3, 390 ++ 79 ++ 80 += 93 + 22 + 23 + 279 + 14 + 124 + 7, 148, 16 -- 79 --

More information

Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式]

Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式] 函数 Function 如何重用代码 How to reuse code 3 4 = 3*3*3*3 3 4,6 5 : 拷贝 - 粘帖代码 (Copy-paste code) 3 4,6 5,12 10 : 拷贝 - 粘帖代码 (Copy-paste code) Bad! 使用函数 (with a function) 使用函数 (with a function) 使用函数 (with a function)

More information

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx 运算符重载 Operator Overloading class Point { public: ; double x_, y_; Why Operator Overloading? Point (double x =0, double y = 0):x_(x),y_(y) { int main(){ Point a(1., 2), b(3,4); Point c = a + b; return 0;

More information

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例 帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例 这篇文章主要介绍了帝国 CMS 下在 PHP 文件中调用数据库类执行 SQL 语句实例, 本文还详细介绍了帝国 CMS 数据库类中的一些常用方法, 需要的朋友可以参考下 例 1: 连接 MYSQL 数据库例子 (a.php)

More information

OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点

OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 推迟至 4 月 25 日晚 9 点 复习 Protected 可以被子类 / 同一包中的类访问, 不能被其他类访问 弱化的 private 同时赋予 package access class MyType { public int i; public double d; public

More information

OOP with Java 通知 : Project 2 提交时间 : 3 月 15 日晚 9 点

OOP with Java 通知 : Project 2 提交时间 : 3 月 15 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 : Project 2 提交时间 : 3 月 15 日晚 9 点 复习 : Java 类型 基本类型 boolean, char, 封装 (wrappers) 类 (class) 定义 class MyType { int i; double d; 数据 (Fields) char c; void set(double

More information

Microsoft Word - 第2章.doc

Microsoft Word - 第2章.doc 2 第第 2 章 学习第 1 章后, 读者已经对 Java 语言有了初步的了解, 本章将具体解析 Java 类的组成元素 任何一个 Java 类, 都有 5 种基本组成元素 : 属性 方法 构造方法 块和内部类 其中属性 方法 构造方法是使用最多的元素, 而块 内部类使用较少 本章将对各种元素进行学习 Java 类基本结构 2.1 类 类 Java 类的声明形式 访问权限修饰符 修饰符 class

More information

Microsoft PowerPoint - 07 派生数据类型

Microsoft PowerPoint - 07 派生数据类型 能源与动力工程学院 目录 派生类型 陈 斌 固有数据类型 数值型 (numerical) 整型 INTEGER 实型 REAL 复数型 COMPLEX 非数值型 字符型 CHARACTER 逻辑型 ( 布尔型 )LOGICAL 自定义数据类型 ( 派生类型, derived type) 派生类型是指用户利用 Fortran 系统内部类型, 如整型 实型 复数型 逻辑型 字符型等的组合自行创建出一个新的数据类型,

More information

OOP with Java 通知 : Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢

OOP with Java 通知 : Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 : Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 Email: 51141201063@ecnu.cn 复习 : Java 类型 基本类型 boolean, char, 封装 (wrappers) 类 (class) 定义 class MyType { int i;

More information

Guava学习之CharSequenceReader

Guava学习之CharSequenceReader CharSequenceReader 类是以 CharSequence 的形式读取字符 CharSequenceReader 类继承自 Reader 类, 除了 remaining() hasremaining() 以及 checkopen() 函数之后, 其他的函数都是重写 Reader 类中的函数 CharSequenceReader 类声明没有用 public 关键字, 所以我们暂时还不能调用这个类

More information

PowerPoint 演示文稿

PowerPoint 演示文稿 The BitCoin Scripting Language 交易实例 交易结构 "result": { "txid": "921a dd24", "hash": "921a dd24", "version": 1, "size": 226, "locktime": 0, "vin": [ ], "vout": [ ], "blockhash": "0000000000000000002c510d

More information

res/layout 目录下的 main.xml 源码 : <?xml version="1.0" encoding="utf 8"?> <TabHost android:layout_height="fill_parent" xml

res/layout 目录下的 main.xml 源码 : <?xml version=1.0 encoding=utf 8?> <TabHost android:layout_height=fill_parent xml 拓展训练 1- 界面布局 1. 界面布局的重要性做应用程序, 界面是最基本的 Andorid 的界面, 需要写在 res/layout 的 xml 里面, 一般情况下一个 xml 对应一个界面 Android 界面布局有点像写 html( 连注释代码的方式都一样 ), 要先给 Android 定框架, 然后再在框架里面放控件,Android 提供了几种框架,AbsoluteLayout,LinearLayout,

More information

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式]

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式] 指针 Pointers 变量指针与指针变量 Pointer of a variable 变量与内存 (Variables and Memory) 当你声明一个变量时, 计算机将给该变量一个内存, 可以存储变量的值 当你使用变量时, 计算机将做两步操作 : - 根据变量名查找其对应的地址 ; - 通过地址对该地址的变量内容进行读 (retrieve) 或写 (set) 变量的地址称为变量的指针! C++

More information

chp4

chp4 Java 软件开发基础 4. 面向对象的程序设计基础 4.1 面向对象基础 对象 现实世界中复杂的对象是由许多小的 简单的对象组成的 客观存在的物体就是最基本的对象 不同的物体有共性, 共性存在于个性之中, 物体的个性又继承了共性 对象的状态属性 对象蕴含着许多信息, 可以用一组状态来表征 对象的行为操作 对象内部含有对数据的操作, 即对象的行为操作 某类事物的抽象 某类对象是对现实世界具有共同特性的某类事物的抽象

More information

01_Service

01_Service 移动平台应用软件开发 Service 主讲 : 张齐勋 zhangqx@ss.pku.edu.cn 移动平台应用软件开发 课程建设小组 北京大学 二零一七年 什么是 Service 与 Activity 一样, 同属 Android 基本组件 后台运行, 不与用户交互, 没有可视化界面 最常见的 Service 如 : 在后台播放歌曲 后台执行文件的下载 同样需在 AndroidManifest.xml

More information

姓名 : 年级专业 : 学号 : 凡年级专业 姓名 学号错写 漏写或字迹不清者, 成绩按零分记 密 封 线 java 较难 试卷 总分 题号 一 二 三 四 五 题分 得分 D 国际通信协议 4 下面选项中, 不是面向对象的特征的是 ( ) A 封装 B 继承 得分 一 单选题 ( 每题 3 分,

姓名 : 年级专业 : 学号 : 凡年级专业 姓名 学号错写 漏写或字迹不清者, 成绩按零分记 密 封 线 java 较难 试卷 总分 题号 一 二 三 四 五 题分 得分 D 国际通信协议 4 下面选项中, 不是面向对象的特征的是 ( ) A 封装 B 继承 得分 一 单选题 ( 每题 3 分, java 较难 试卷 总分 题号 一 二 三 四 五 题分 D 国际通信协议 4 下面选项中, 不是面向对象的特征的是 ( ) A 封装 B 继承 一 单选题 ( 每题 3 分, 共计 15 分 ) 1 下列修饰符中, 成员内部类被 ( ) 修饰后, 可以被外界访问 C 多态 D 重构 5 下列关于构造方法重载的说法中, 错误的是 () A 不同构造方法中调用本类其它的构造方法时, 需要使用 this([

More information

第3 章 类 对象与方法 3.1 类 类的定义 在 Objective-C 中 每个类的定义包括两个部分 接口 interface 和实现 implementation 接口部 分定义在.h 文件中 包含类的声明 属性以及方法 主要作用是对外提供访问接口 实现部分定义在.m 文件中 主要

第3 章 类 对象与方法 3.1 类 类的定义 在 Objective-C 中 每个类的定义包括两个部分 接口 interface 和实现 implementation 接口部 分定义在.h 文件中 包含类的声明 属性以及方法 主要作用是对外提供访问接口 实现部分定义在.m 文件中 主要 第3 章 类 对象与方法 3.1 类 3.1.1 类的定义 在 Objective-C 中 每个类的定义包括两个部分 接口 interface 和实现 implementation 接口部 分定义在.h 文件中 包含类的声明 属性以及方法 主要作用是对外提供访问接口 实现部分定义在.m 文件中 主要用于方法的功能实现 这种定义类的方法 好处在于将公共声明 接口 与代码实现分开 对外屏蔽了功能实现的细节

More information

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款

使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款 JAVA 程 序 设 计 ( 肆 ) 徐 东 / 数 学 系 使 用 Java 语 言 模 拟 保 险 箱 容 量 门 板 厚 度 箱 体 厚 度 属 性 锁 具 类 型 开 保 险 箱 关 保 险 箱 动 作 存 取 款 使 用 Java class 代 表 保 险 箱 public class SaveBox 类 名 类 类 体 实 现 封 装 性 使 用 class SaveBox 代 表 保

More information

OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac)

OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac) OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac) 复习 面向对象编程 将实际问题分解成不同的对象 不的对象提供不同的服务 对象之间可以传递消息 例子小李深夜

More information

《计算概论》课程 第十九讲 C 程序设计语言应用

《计算概论》课程 第十九讲  C 程序设计语言应用 Java 高级技术 课程第二讲 Java 语言的面向对象特性 (2) 李戈 北京大学信息科学技术学院软件研究所 2010 年 3 月 21 日 课程助教 : 前言 黎育龙 (10817195@pub.ss.pku.edu.cn) Email 标题 :Java 高级技术 + 题目 请不要把作业发到我的信箱 ; 新的课程网站 http://www.ontoedu.pku.edu.cn/index.jsp

More information

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 4 月 19 日晚 9 点 复习 Protected 可以被子类 / 同一包中的类访问, 不能被其他类访问 弱化的 private 同时赋予 package access class MyType { public int i; public double d; public char

More information

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1 1 TEMPLATE 1 Template 描述 使用模板函数求最大值 使用如下 main 函数对程序进行测试 int main() { double a, b; cin >> a >> b; cout c >> d; cout

More information

工程项目进度管理 西北工业大学管理学院 黄柯鑫博士 甘特图 A B C D E F G 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 甘特图的优点 : 直观明了 ( 图形化概要 ); 简单易懂 ( 易于理解 ); 应用广泛 ( 技术通用 ) 甘特图的缺点 : 不能清晰表示活动间的逻辑关系 WBS 责任分配矩阵 ( 负责〇审批

More information

Microsoft Word - JCS5.doc

Microsoft Word - JCS5.doc 第 5 章进一步讨论对象和类 5.1 抽象数据类型 5.1.1 概述 绝大多数程序设计语言都预定义了一些基本数据类型, 并相应定义了对那些类型的实例执行的操作 比如, 对整型 实型等数值类型, 有加 减 乘 除等操作 ; 对逻辑类型, 有逻辑与 逻辑或 逻辑非等操作 对于用户自定义的复合数据类型, 需要由程序员自己定义一些方法, 对该类型的实例进行所需的操作 在早期许多程序设计语言中, 复合数据类型及其相关操作的代码之间没有特殊的联系

More information

IDEO_HCD_0716

IDEO_HCD_0716 IDEO HCD Toolkit Tencent CDC ...? Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC Tencent CDC

More information

Struts2自定义类型转换.doc

Struts2自定义类型转换.doc Struts2 自定义类型转换 原理 struts2 的自定义类型转换机制为复杂类型的输入输出处理提供了便捷.struts2 已经为我们提供了几乎所有的 primitive 类型以及常用类型 ( 如 Date) 的类型转换器, 我们也可以为我们自定义类添加自定义类型转化器. struts2 为我们提供了一个类型转化器的入口 : ognl.defaulttypeconverter, 或继承 org.apache.struts2.util.strutstypeconverter,

More information

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 4: 5 月 2 日晚 9 点 复习 Protected 可以被子类 / 同一包中的类访问, 不能被其他类访问 弱化的 private 同时赋予 package access class MyType { public int i; public double d; public char

More information

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 310-065Big5 Title : Sun Certified Programmer for the Java 2 Platform, SE 6.0 Version : Demo 1 / 14 1. 35. String #name = "Jane Doe"; 36. int

More information

# # # # # # # # #

# # # # # # # # # 实现政治问责的三条道路 马 骏 建立一个对人民负责的政府是现代国家治理的核心问题 实现这一目标 需要解决两个最基本的问题 谁来使用权力 如何使用权力 选举制度是解决前一问题相对较好的制度 而预算制度是解决第二个问题最好的制度 通过历史比较分析 可以总结出三条实现政治问责的道路 世纪的欧洲道路 从建国到进步时代改革的美国道路以及雏形初现的中国道路 这意味着 西方经验并不是唯一的实现政治问责的道路 相对于西方经验来说

More information

拦截器(Interceptor)的学习

拦截器(Interceptor)的学习 二 拦截器 (Interceptor) 的学习 拦截器可以监听程序的一个或所有方法 拦截器对方法调用流提供了细粒度控制 可以在无状态会话 bean 有状态会话 bean 和消息驱动 bean 上使用它们 拦截器可以是同一 bean 类中的方法或是一个外部类 下面介绍如何在 Session Bean 类中使用外部拦截器类 @Interceptors 注释指定一个或多个在外部类中定义的拦截器 下面拦截器

More information

OOP with Java 通知 Project 3: 4 月 19 日晚 9 点

OOP with Java 通知 Project 3: 4 月 19 日晚 9 点 OOP with Java Yuanbin Wu cs@ecnu OOP with Java 通知 Project 3: 4 月 19 日晚 9 点 复习 Upcasting 同一基类的不同子类可以被视为同一类型 ( 基类 ) 放宽类型一致性 简化接口 class A{ class B{ A a = new A(); B b = new B(); // A a = new B(); compile

More information

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌

内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌 语 言 程 序 设 计 郑 莉 胡 家 威 编 著 清 华 大 学 逸 夫 图 书 馆 北 京 内 容 简 介 本 书 是 一 本 关 于 语 言 程 序 设 计 的 教 材, 涵 盖 了 语 言 的 基 本 语 法 和 编 程 技 术, 其 中 包 含 了 作 者 对 语 言 多 年 开 发 经 验 的 总 结, 目 的 是 让 初 学 的 读 者 感 受 到 语 言 的 魅 力, 并 掌 握 语

More information

运算符重载 为什么要 运算符重载 那些运算符可以重载, 哪些不可以 如何实现运算符重载 实现方式 : 成员函数与非成员函数 类型转换 怎样实现对象与基本数据类型数据的运算 2

运算符重载 为什么要 运算符重载 那些运算符可以重载, 哪些不可以 如何实现运算符重载 实现方式 : 成员函数与非成员函数 类型转换 怎样实现对象与基本数据类型数据的运算 2 第十一讲 运算符重载 与类型转换 运算符重载 为什么要 运算符重载 那些运算符可以重载, 哪些不可以 如何实现运算符重载 实现方式 : 成员函数与非成员函数 类型转换 怎样实现对象与基本数据类型数据的运算 2 为什么要运算符重载 预定义的运算符只针对基本数据类型, 若要对类的对象进行类似的运算, 需要重新定义运算符的功能 运算符重载实质就是函数重载 : 对已有的运算符赋予多重含义, 使得同一个运算符作用于不同类型的数据时导致不同的行为

More information

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat

2. AOP 底层技术实现 小风 Java 实战系列教程 关键词 : 代理模式 代理模型分为两种 : 1) 接口代理 (JDK 动态代理 ) 2) 子类代理 (Cglib 子类代理 ) 需求 :CustomerService 业务类, 有 save,update 方法, 希望在 save,updat 本章学习目标 小风 Java 实战系列教程 AOP 思想概述 AOP 底层技术实现 AOP 术语介绍 SpringAOP 的 XML 方式 HelloWorld SpringAOP 的 XML 方式配置细节 SpringAOP 的注解方式 SpringAOP 的零配置方式 1. AOP 思想概述 1.1. AOP 思想简介 1.2. AOP 的作用 2. AOP 底层技术实现 小风 Java 实战系列教程

More information

使用MapReduce读取XML文件

使用MapReduce读取XML文件 使用 MapReduce 读取 XML 文件 XML( 可扩展标记语言, 英语 :extensible Markup Language, 简称 : XML) 是一种标记语言, 也是行业标准数据交换交换格式, 它很适合在系统之间进行数据存储和交换 ( 话说 Hadoop H ive 等的配置文件就是 XML 格式的 ) 本文将介绍如何使用 MapReduce 来读取 XML 文件 但是 Had oop

More information

Chapter 9: Objects and Classes

Chapter 9: Objects and Classes Fortran Algol Pascal Modula-2 BCPL C Simula SmallTalk C++ Ada Java C# C Fortran 5.1 message A B 5.2 1 class Vehicle subclass Car object mycar public class Vehicle extends Object{ public int WheelNum

More information

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple

// HDevelopTemplateWPF projects located under %HALCONEXAMPLES%\c# using System; using HalconDotNet; public partial class HDevelopExport public HTuple halcon 与 C# 混合编程之 Halcon 代码调用 写在前面 完成 halcon 与 C# 混合编程的环境配置后, 进行界面布局设计构思每一个按钮所需要实现 的功能, 将 Halcon 导出的代码复制至相应的 C# 模块下即可 halcon 源程序 : dev_open_window(0, 0, 512, 512, 'black', WindowHandle) read_image (Image,

More information

没有幻灯片标题

没有幻灯片标题 指针作为函数参数 : 原因 : 1 需要修改一个或多个值,( 用 return 语句不能解决问题 ) 2 执行效率的角度 使用方法 : 在函数原型以及函数首部中需要声明能够接受指针值的形参, 具体的写法为 : 数据类型 * 形参名 如果有多个指针型形参, 则用逗号分隔, 例如 : void swap(int *p1, int *p2) 它说明了形参 p1 p2 是指向整型变量的指针 在函数调用时,

More information

public class Phone { String brand; double price; void call(){ System.out.println("hi,how are you doing"); 案例 3-2 对象的创建及对象内存图 1 考核知识点对象的创建和引用 掌握创建对象的方式

public class Phone { String brand; double price; void call(){ System.out.println(hi,how are you doing); 案例 3-2 对象的创建及对象内存图 1 考核知识点对象的创建和引用 掌握创建对象的方式 第三章补充案例 案例 3-1 类的定义 1 考核知识点类的定义 掌握类定义的格式 掌握如何在类中定义成员变量和成员方法 3 需求分析在程序中, 设计一个表示学生的类, 该类具有以下属性和方法 : 该类具有表示姓名的属性 name 该类具有表示年龄的属性 age 该类具有表示说话行为的方法 speak, 并且用于输出学生的姓名和年龄 1) 使用 class 关键字定义一个表示学生类型的类, 类名为 Student

More information

三种方法实现Hadoop(MapReduce)全局排序(1)

三种方法实现Hadoop(MapReduce)全局排序(1) 三种方法实现 Hadoop(MapReduce) 全局排序 () 三种方法实现 Hadoop(MapReduce) 全局排序 () 我们可能会有些需求要求 MapReduce 的输出全局有序, 这里说的有序是指 Key 全局有序 但是我们知道,MapReduce 默认只是保证同一个分区内的 Key 是有序的, 但是不保证全局有序 基于此, 本文提供三种方法来对 MapReduce 的输出进行全局排序

More information

重勘信息的哲学含义 ¼ ½ ¾ ¼ ½ ¾

重勘信息的哲学含义 ¼ ½ ¾ ¼ ½ ¾ 重勘信息的哲学含义 肖 峰 信息不能以任何方式归结为物质 它既不是物质内在既成的东西 也不是纯粹的自然现象 更不是可以离开主体而独立存在的纯客观现象或无处不在的普遍现象 哲学含义上的信息是一种非物质的存在 是主体对对象的感知 辨识和建构 也是生命控制系统尤其是神经系统的一种机能 信息与 意义 关联 是一种属人的认识现象 不存在所谓的 本体论信息 而只存在认识论意义上的信息 信息的哲学含义应与信息的日常用法具有连续性

More information

JAVA 单元 2.1 四则运算机 ( 一 ) 单元教学进度设计 教学环节 教学内容 教师学生活动活动 反馈 反馈课前作业完成情况 反馈加分 1. 下面哪些是合法的变量名? ( ) A.2variable 答案 :DEG B..variable2 解答 : C.._whatavariable A:/

JAVA 单元 2.1 四则运算机 ( 一 ) 单元教学进度设计 教学环节 教学内容 教师学生活动活动 反馈 反馈课前作业完成情况 反馈加分 1. 下面哪些是合法的变量名? ( ) A.2variable 答案 :DEG B..variable2 解答 : C.._whatavariable A:/ 单元 2.1 四则运算机 ( 一 ) 单元教学进度设计 教学环节 教学内容 教师学生活动活动 反馈 反馈课前作业完成情况 反馈加分 1. 下面哪些是合法的变量名? ( ) A.2variable 答案 :DEG B..variable2 解答 : C.._whatavariable A:// 不能以数字开头 D._3_ B:// 不能用点和空格 提问 抢答 E.$anothervar C: // 不能用点和空格

More information

javaexample-02.pdf

javaexample-02.pdf n e w. s t a t i c s t a t i c 3 1 3 2 p u b l i c p r i v a t e p r o t e c t e d j a v a. l a n g. O b j e c t O b j e c t Rect R e c t x 1 y 1 x 2 y 2 R e c t t o S t r i n g ( ) j a v a. l a n g. O

More information

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc

Fun Time (1) What happens in memory? 1 i n t i ; 2 s h o r t j ; 3 double k ; 4 char c = a ; 5 i = 3; j = 2; 6 k = i j ; H.-T. Lin (NTU CSIE) Referenc References (Section 5.2) Hsuan-Tien Lin Deptartment of CSIE, NTU OOP Class, March 15-16, 2010 H.-T. Lin (NTU CSIE) References OOP 03/15-16/2010 0 / 22 Fun Time (1) What happens in memory? 1 i n t i ; 2

More information

1intro.pptx

1intro.pptx 欢迎学习 大仕老师 1 第 1 章 JAVA 语言与面向对象的程序设计 1.1 Java 语言简介 1.2 面向对象程序设计 2 Java 语言简介 3 认识 Java Java 历史与发展 5 Java 是最热门的语言之一 数据来源 :IEEE Spectrum 6 6 0.1 Java 的发展历程 Internet 发展中的两次飞跃 : p www p Java Java 的出现 p 1990

More information

Microsoft PowerPoint - 04-Inheritance.ppt

Microsoft PowerPoint - 04-Inheritance.ppt 继承 派生与多态性 1 本章主要内容 类的继承与派生 类成员的访问控制 简单继承与多重继承 派生类的构造 析构函数 多态性 2 1 类的继承与派生 保持已有类的特性, 并在其基础上产生新的类, 称新类继承了已有类的特征, 或称已有类派生出新类 被继承的已有类称为基类 ( 或父类 ) 派生出的新类称为派生类 派生类将自动继承基类的所有特性 ( 属性和方法 ) 派生类可以定义新的特性 ( 属性和方法 )

More information

chp5_1

chp5_1 Java 软件设计基础 5. 继承与多态 类的封装 类的特性 Java 程序设计的基本单位是类, 类是用来创建具体对象的模板, 有以下三个重要特性 : 封装 Java 语言中, 对象就是对一组变量和相关方法的封装 (Encapsulation), 通过对对象的封装, 实现模块化和信息隐藏 通过对类的成员辅以一定的访问限制, 实现类中成员的信息隐藏 继承 继承 (inheritance) 允许创建分等级层次的类,

More information

Microsoft PowerPoint - 01_Introduction.ppt

Microsoft PowerPoint - 01_Introduction.ppt Hello, World C 程序设计语言 第 1 章章观其大略 孙志岗 sun@hit.edu.cn http://sunner.cn prf("hello,, world\n"); 超级无敌考考你 : 如何把 hello 和 world 分别打印在两行? 2004-12-19 A Tutorial Introduction 2 hello.c 打印华氏温度与摄氏温度对照表 计算公式 : C=(5/9)(

More information

器之 间 向一致时为正 相反时则为负 ③大量电荷的定向移动形成电 流 单个电荷的定向移动同样形成电流 3 电势与电势差 1 陈述概念 电场中某点处 电荷的电势能 E p 与电荷量 q Ep 的比值叫做该点处的电势 表达式为 V 电场中两点之间的 q 电势之差叫做电势差 表达式为 UAB V A VB 2 理解概念 电势差是电场中任意两点之间的电势之差 与参考点的选择无关 电势是反映电场能的性质的物理量

More information

设计模式 Design Patterns

设计模式 Design Patterns 丁勇 Email:18442056@QQ.com 组件技术概述 现在软件开发都已经转向了基于组件的开发, 目前具备代表性的组件技术有微软的 COM COM+, 有 Sun 的 Bean 和 EJB(Enterprise Bean), 另外还有 CORBA(Common Object Request Broker Architecture, 公 共对象请求代理结构 ) Bean Bean 规范将 软件组件

More information

KillTest 质量更高 服务更好 学习资料 半年免费更新服务

KillTest 质量更高 服务更好 学习资料   半年免费更新服务 KillTest 质量更高 服务更好 学习资料 http://www.killtest.cn 半年免费更新服务 Exam : 310-055Big5 Title : Sun Certified Programmer for the Java 2 Platform.SE 5.0 Version : Demo 1 / 22 1. 11. public static void parse(string str)

More information

Microsoft Word - 第5章.doc

Microsoft Word - 第5章.doc 第 5 章 面向对象编程 除了基本的类和对象,Java 语言的面向对象编程还包括抽象类 接口 内部类及包等高级特性 通过对这些高级特性的支持,Java 语言全面实现了面向对象的编程 本章将进一步深入介绍 Java 语言面向对象编程方面的知识 5.1 类的三大特性 第 4 章介绍了有关类定义的基本知识 面向对象中的类还具有封装 继承与多态的特性, 这也是面向对象编程所具有的重要特点 Java 语言对类的封装

More information

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复 获取将导致上次获取的 access_token 失效 接入方可以使用 AppID 和 AppSecret

More information

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入

詞 彙 表 編 號 詞 彙 描 述 1 預 約 人 資 料 中 文 姓 名 英 文 姓 名 身 份 證 字 號 預 約 人 電 話 性 別 2 付 款 資 料 信 用 卡 別 信 用 卡 號 信 用 卡 有 效 日 期 3 住 房 條 件 入 住 日 期 退 房 日 期 人 數 房 間 數 量 入 100 年 特 種 考 試 地 方 政 府 公 務 人 員 考 試 試 題 等 別 : 三 等 考 試 類 科 : 資 訊 處 理 科 目 : 系 統 分 析 與 設 計 一 請 參 考 下 列 旅 館 管 理 系 統 的 使 用 案 例 圖 (Use Case Diagram) 撰 寫 預 約 房 間 的 使 用 案 例 規 格 書 (Use Case Specification), 繪 出 入

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc CHAPTER3 面向对象程序设计 第 3 章 Java 语言是一种面向对象的高级程序语言 应用面向对象语言求解问题的基本思路是, 首先分析问题并建立相应的对象, 然后通过这些对象以及它们之间的配合解决问题, 其中每个对象在计算机中占用一定的内存, 同时能够完成一定的功能 这种基本思想实际上是模拟现实生活求解问题的一般过程 在现实生活中, 任何一个人或任何一种物体都可以被认为是对象 例如, 人一般拥有手

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc CHAPTER3 第 3 章 面向对象程序设计 Java 语言是一种面向对象的高级程序语言 应用面向对象语言求解问题的基本思路是 : 首先分析问题并建立相应的对象, 然后通过这些对象以及它们之间的配合解决问题, 其中每个对象在计算机中占用一定的内存, 同时能够完成一定的功能 这种基本思想实际上是模拟现实生活求解问题的一般过程 在现实生活中, 任何一个人或任何一种物体都可以被认为是对象 例如 : 人一般拥有手

More information

Spring3.x开发入门

Spring3.x开发入门 Spring Bean 管理 Spring 的工厂类 课程安排 Spring 的 Bean 管理 (XML 方式 ) Spring 的属性注入 (XML 方式 ) Spring 的 Bean 管理 ( 注解方式 ) Spring 的属性注入 ( 注解方式 ) Spring 的工厂类 Spring 的 Bean 管理 (XML 方式 ) 三种实例化 Bean 的方式 使用类构造器实例化 ( 默认无参数

More information

<4D F736F F D E4345C6BDCCA84323B1E0B3CCD2AAB5E3D6AED2BB2E646F63>

<4D F736F F D E4345C6BDCCA84323B1E0B3CCD2AAB5E3D6AED2BB2E646F63> 基于 WINCE 平台 C# 编程要点之一 本文主要介绍在基于 Windows CE 平台的英创嵌入式主板下进行 C#(Microsoft Visual Stdio.Net 2005) 应用程序开发时会常常用到的一些功能函数以及开发方法, 这些方法适用于英创采用 WinCE 平台的所有型号嵌入式主板, 包括 EM9000 EM9260 EM9160 等 本文要点包括 : 文件的删除和复制 如何获取存取设备的空间大小

More information

Mac Java import com.apple.mrj.*;... public class MyFirstApp extends JFrame implements ActionListener, MRJAboutHandler, MRJQuitHandler {... public MyFirstApp() {... MRJApplicationUtils.registerAboutHandler(this);

More information

年第 期

年第 期 年第 期 论虚拟实践的哲学意蕴 孙伟平 信息技术 虚拟技术 实践 实践形态 虚拟实践 所谓虚拟实践 是指人们按照一定的目的 通过数字化中介系统在虚拟时空进行的 主体与虚拟客体双向对象化的感性活动 它是人们有目的 有意识进行的能动的探索和改造 虚拟客体 同时也提升和改造自身的客观活动 是人类在当代技术革命推动下兴起的一种新型的实践活动形态 具有与传统实践迥然不同的特征 虚拟实在性 即时交互性 自由开放性

More information

第 期 曹 源 等 形式化方法在列车运行控制系统中的应用

第 期 曹 源 等 形式化方法在列车运行控制系统中的应用 第 卷 第 期 年 月 交通运输工程学报 曹 源 唐 涛 徐田华 穆建成 为了确保列车运行控制系统设计和开发的正确性 比较了仿真 测试和形式化 种能够验证 系统设计正确性的方式 根据列车运行控制系统对安全的苛求性 提出了 个与系统安全相关的重要特性 即实时性 混成性 分布 并发 性 反应性 并分析了与这些特性相关的具体形式化方法 通 过对每种形式化方法的数学基础和应用范围的分析和归类 给出了各种方法的优势和不足

More information

untitled

untitled 4.1AOP AOP Aspect-oriented programming AOP 來說 AOP 令 理 Cross-cutting concerns Aspect Weave 理 Spring AOP 來 AOP 念 4.1.1 理 AOP AOP 見 例 來 例 錄 Logging 錄 便 來 例 行 留 錄 import java.util.logging.*; public class HelloSpeaker

More information

Microsoft Word - 第3章.doc

Microsoft Word - 第3章.doc Java C++ Pascal C# C# if if if for while do while foreach while do while C# 3.1.1 ; 3-1 ischeck Test() While ischeck while static bool ischeck = true; public static void Test() while (ischeck) ; ischeck

More information

PowerPoint Presentation

PowerPoint Presentation 对象与对象的内存模型 北京理工大学计算机学院 金旭亮 对象的内存模型 对象与类的静态成员 装箱和拆箱 主要内容 提示 : 本讲以 C# 为主介绍, 但所讲内容同样适用于 Java 2 一 对象的内存模型 对象是如何 活 在内存中的? 我们如何访问内存中的这个对象? 代码中定义一个对象变量的含义是什么? 对象变量 与 对象 对象变量用于 引用 一个真实的对象 类 引用 new 对象变量 对象 对象变量保存在线程堆栈中

More information

<4D F736F F D204A617661B3CCD0F2C9E8BCC6D3EBCAB5BCF9BDCCB3CCA3A8B5DA32B0E6A3A920B5DA35D5C22E646F63>

<4D F736F F D204A617661B3CCD0F2C9E8BCC6D3EBCAB5BCF9BDCCB3CCA3A8B5DA32B0E6A3A920B5DA35D5C22E646F63> 第 5 章 类类和对象和对象 教学目标 : 掌握类的构造方法的定义 作用, 以及如何实现类的构造方法 掌握如何创建类对象 如何使用类对象 掌握静态成员和实例成员的使用方法, 以及二者之间的区别 掌握类成员的访问权限的设置方法以及使用原则 教学重点 : 本章首先要求读者掌握对象的定义和引用的方法, 在此基础上深入理解静态成员和实例成员的定义及其应用 方法重载及其作用, 类的封装和访问控制权限 5.1

More information

Microsoft Word - 01.DOC

Microsoft Word - 01.DOC 第 1 章 JavaScript 简 介 JavaScript 是 NetScape 公 司 为 Navigator 浏 览 器 开 发 的, 是 写 在 HTML 文 件 中 的 一 种 脚 本 语 言, 能 实 现 网 页 内 容 的 交 互 显 示 当 用 户 在 客 户 端 显 示 该 网 页 时, 浏 览 器 就 会 执 行 JavaScript 程 序, 用 户 通 过 交 互 式 的

More information

第四章 102 图 4唱16 基于图像渲染的理论基础 三张拍摄图像以及它们投影到球面上生成的球面图像 拼图的圆心是相同的 而拼图是由球面图像上的弧线图像组成的 因此我 们称之为同心球拼图 如图 4唱18 所示 这些拼图中半径最大的是圆 Ck 最小的是圆 C0 设圆 Ck 的半径为 r 虚拟相机水平视域为 θ 有 r R sin θ 2 4畅11 由此可见 构造同心球拼图的过程实际上就是对投影图像中的弧线图像

More information

博学谷 让 IT 教学更简单, 让 IT 学习更有效 第五章补充案例 案例 5-1 声明类 一 案例描述 1 考核知识点类的声明 2 练习目标 掌握声明一个类的语法格式 掌握如何在类中声明成员变量和成员方法 3 需求分析在程序中, 设计一个表示学生的类, 该类具有以下属性和方法 : 该类具有表示姓名

博学谷 让 IT 教学更简单, 让 IT 学习更有效 第五章补充案例 案例 5-1 声明类 一 案例描述 1 考核知识点类的声明 2 练习目标 掌握声明一个类的语法格式 掌握如何在类中声明成员变量和成员方法 3 需求分析在程序中, 设计一个表示学生的类, 该类具有以下属性和方法 : 该类具有表示姓名 第五章补充案例 案例 5-1 声明类 1 考核知识点类的声明 掌握声明一个类的语法格式 掌握如何在类中声明成员变量和成员方法 3 需求分析在程序中, 设计一个表示学生的类, 该类具有以下属性和方法 : 该类具有表示姓名的属性 该类具有表示性别的属性 该类具有表示说话行为的 sayhello() 方法, 并且用于输出学生的姓名 1) 使用 class 关键字定义一个表示学生类型的类, 类名为 Student

More information

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc

本章学习目标 小风 Java 实战系列教程 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc 本章学习目标 SpringMVC 简介 SpringMVC 的入门案例 SpringMVC 流程分析 配置注解映射器和适配器 配置视图解析器 @RequestMapping 注解的使用 使用不同方式的跳转页面 1. SpringMVC 简介 Spring web mvc 和 Struts2 都属于表现层的框架, 它是 Spring 框架的一部分, 我们可 以从 Spring 的整体结构中看得出来 :

More information

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 -> 目录 1 大概思路... 1 2 创建 WebAPI... 1 3 创建 CrossMainController 并编写... 1 4 Nuget 安装 microsoft.aspnet.webapi.cors... 4 5 跨域设置路由... 4 6 编写 Jquery EasyUI 界面... 5 7 运行效果... 7 8 总结... 7 1 1 大概思路 创建 WebAPI 创建 CrossMainController

More information

试卷代号 : 座位号 中央广播电视大学 学年度第一学期 " 开放本科 " 期末考试 面向对象程序设计 ( 本 ) 试题 2011 年 1 月 题号 一 一 一四总分 一 分数 得分 评卷人 - 单选题, 在括号内填写正确的选项编号 { 每小题 2 分, 共

试卷代号 : 座位号 中央广播电视大学 学年度第一学期  开放本科  期末考试 面向对象程序设计 ( 本 ) 试题 2011 年 1 月 题号 一 一 一四总分 一 分数 得分 评卷人 - 单选题, 在括号内填写正确的选项编号 { 每小题 2 分, 共 试卷代号 : 1 2 9 7 座位号 中央广播电视大学 2 0 1 0 2011 学年度第一学期 " 开放本科 " 期末考试 面向对象程序设计 ( 本 ) 试题 2011 年 1 月 题号 一 一 一四总分 一 分数 得分 评卷人 - 单选题, 在括号内填写正确的选项编号 { 每小题 2 分, 共 2 0 分 } 1. Java 是一门 ( ) 语言 A. 机器 B. 汇编 C. 面向过程的高级 D.

More information

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式] Arrays and Strings 存储同类型的多个元素 Store multi elements of the same type 数组 (array) 存储固定数目的同类型元素 如整型数组存储的是一组整数, 字符数组存储的是一组字符 数组的大小称为数组的尺度 (dimension). 定义格式 : type arrayname[dimension]; 如声明 4 个元素的整型数组 :intarr[4];

More information

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10

1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 Java V1.0.1 2007 4 10 1 4 1.1 4 1.2..4 2..4 2.1..4 3.4 3.1 Java.5 3.1.1..5 3.1.2 5 3.1.3 6 4.6 4.1 6 4.2.6 5 7 5.1..8 5.1.1 8 5.1.2..8 5.1.3..8 5.1.4..9 5.2..9 6.10 6.1.10 6.2.10 6.3..10 6.4 11 7.12 7.1

More information

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6: Chapter 15. Suppressed Exception CH14 Finally Block Java SE 7 try-with-resources JVM cleanup try-with-resources JVM cleanup cleanup Java SE 7 Throwable getsuppressed Throwable[] getsuppressed() Suppressed

More information

目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas

目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas 目录 1 IPv6 快速转发 1-1 1.1 IPv6 快速转发配置命令 1-1 1.1.1 display ipv6 fast-forwarding aging-time 1-1 1.1.2 display ipv6 fast-forwarding cache 1-1 1.1.3 ipv6 fast-forwarding aging-time 1-3 1.1.4 ipv6 fast-forwarding

More information

<4D F736F F F696E74202D20B5DA3032BDB25FC0E0BACDB6D4CFF3312E BBCE6C8DDC4A3CABD5D>

<4D F736F F F696E74202D20B5DA3032BDB25FC0E0BACDB6D4CFF3312E BBCE6C8DDC4A3CABD5D> 程序设计实习 (I): C++ 程序设计 第二讲类和对象 (1) 面向对象的程序设计 面向对象的程序设计方法, 能够较好解决结构化程序设计中出现的问题 面向对象的程序 = 类 + 类 + + 类 设计程序的过程, 就是设计类的过程 2 面向对象的程序设计 面向对象的程序设计方法 : 将某类客观事物共同特点 ( 属性 ) 归纳出来, 形成一个数据结 构 ( 可以用多个变量描述事物的属性 ); 将这类事物所能进行的行为也归纳出来,

More information

目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas

目录 1 IPv6 快速转发 IPv6 快速转发配置命令 display ipv6 fast-forwarding aging-time display ipv6 fast-forwarding cache ipv6 fas 目录 1 IPv6 快速转发 1-1 1.1 IPv6 快速转发配置命令 1-1 1.1.1 display ipv6 fast-forwarding aging-time 1-1 1.1.2 display ipv6 fast-forwarding cache 1-1 1.1.3 ipv6 fast-forwarding aging-time 1-3 1.1.4 ipv6 fast-forwarding

More information