java基础 - 1

目录

第一章:Java开始 1

学习目标 1

Java历史 2

Java技术概述 3

Java技术的优点 3

Java虚拟机 4

类加载器 6

Windows环境变量 8

内容总结 13

独立实践 14

第二章: 面向对象概述 15

学习目标 15

面向对象(Object Oriented) 16

面向对象的主要特性 18

抽象(Abstraction) 18

封装(Encapsulation) 19

多态(Polymorphism) 20

面向对象的优点 22

面向对象的分析、设计和编程 23

面向对象语言的发展简史 26

内容总结 29

独立实践 30

第三章:面向对象的程序设计 31

学习目标 31

类和对象的描述 32

声明类 32

声明属性 33

声明成员方法 34

源文件的布局 36

包的声明 36

包与目录的布局 38

内容总结 45

独立实践 46

第四章: Java语法基础 47

学习目标 47

基本语法元素 48

Java关键字 49

基本Java数据类型 50

变量声明和赋值 52

引用(Reference)类型 52

存储器分配和布局 53

this引用 55

Java编码约定 56

运算符的优先级 58

升级和表达式的类型转换 62

独立实践 70

第五章:数组 71

学习目标 71

数组的描述 72

创建数组 72

多维数组 78

拷贝数组 80

内容总结 83

独立实践 84

第六章:继承 86

学习目标: 86

单继承(single inheritance) 87

访问控制 89

方法重载(method overloading) 91

方法覆盖(method overriding) 93

基于继承的多态实现 94

隐藏(hiding) 95

构造方法在继承中的使用 96

super关键字 97

包装类 97

toString( )方法 100

内容总结 101

独立实践 102

第七章:类的高级特征 103

学习目标 103

static关键字 104

final关键字 106

内部类 106

实例分析 110

抽象类,接口 115

内容总结 120

独立实践 121

第八章:异常 122

学习目标 122

异常的概念 123

异常的分类 123

实例分析 124

自定义异常 126

方法覆盖和异常 127

内容总结 129

第九章:基于文本的应用 131

学习目标 131

程序交互的几种方式 132

常用类方法说明 132

String的方法 132

正则表示式(Regular expression 133

StringBuffer 135

StringBufferString的区别 136

集合类的使用 136

实例分析 136

内容总结 153

独立实践 154

第十章:JAVA GUI概述 155

学习目标 155

GUI概述及组成 156

Swing优点 157

布局管理器 158

BorderLayout 159

GridLayout 161

CardLayout 162

GridBagLayout 164

实例分析 165

内容总结 172

独立实践 173

第十一章 线程 174

学习目标 174

线程的概念 175

线程状态和调度 ….176

线程中断/恢复的几种方式 178

创建线程的两种方式 179

线程的控制 180

实例分析 182

内容总结 189

独立实践 190

第十二章:高级I/O 192

学习目标 192

I/O基础知识 193

字节流 193

字符流 194

节点流 194

过程流 194

基本字符流类 198

对象串行化 201

实例分析 203

内容总结 211

独立实践 212

第十三章:网络 213

学习目标 213

TCP/IP协议模型 214

基于Java的网络技术 216

DatagramSocket 219

InetAddress类的使用 221

扩展知识: 227

SocketChannel 227

内容总结 229

独立实践 230

第十四章:数据结构与算法(上) 231

学习目标 231

算法(algorithm) 232

查找算法: 234

排序算法: 237

递归(recursive) 240

快速排序: 242

内容总结 245

独立实践 246

第十五章:数据结构与算法(下) 247

学习目标 247

数据结构介绍: 248

数组 248

逻辑大小和物理大小 248

链表 248

(stack) 249

队列: 250

树: 250

实例分析 252

内容总结 274

独立实践 275

第十六章:数据库(一) 276

学习目标 276

数据库的基本概念 277

数据的描述 277

数据联系的描述 278

数据模型 278

数据库三级模式结构 279

数据库三个范式 280

范式总结 282

创建数据库 283

创建表 287

内容总结 290

独立实践 291

第十七章: 数据库() 292

学习目标: 292

查询(从基本到高级) 293

模糊查询 293

排序 295

集合操作- 296

集合操作- 297

集合操作- 297

常用函数 297

数据类型转换函数CASTCONVERT 298

分组查询 299

五大约束 301

索引 303

数据库的备份与恢复 304

内容总结 308

独立实践 309

第十八章:数据库(三) 310

学习目标: 310

存储过程 311

触发器 313

函数 314

规则 314

事务 315

while语句 317

case语句 317

内容总结: 318

独立实践 319

第十九章: JDBC基础 320

学习目标 320

JDBC的概念 321

连接数据库的几种方式 321

JAVA编程语言和JDBC 323

JDBC编程的步骤 323

实例分析 325

内容总结 335

独立实践 336

第二十章:高级JDBC 337

学习目标 337

使用DDL,DML语言对数据库进行基本操作 338

查询数据库里的数据 339

预编译语句(PreparedStatement 340

使用事务 341

事务的级别控制 343

使用存储过程 345

操作元数据 347

ResultSetMetaData(结果集元数据) 349

可滚动的和可更新的结果集 350

批处理更新 354

二进制大对象BLOB 357

RowSet 新特性 359

JdbcRowSet 360

FilteredRowSet 361

内容总结 363

独立实践 364

第二十一章:XML基础 366

学习目标 366

XML的概念 367

定义XML文档 368

命名冲突 371

使用前缀解决命名冲突问题 371

使用命名空间 371

命名空间属性 372

统一资源标识符 372

默认的命名空间 372

使用命名空间 373

XML 文档规则 374

XML Schema 379

SchemaDTD的区别: 380

Schema的数据类型 380

样式表(XSL 384

CSS样式表 384

XSL样式表 385

XSL的基本结构 386

XSL的基本语法 390

节点选择语句<xsl:value-of > 392

循环判断语句<xsl:for-each> 392

条件判断语句<xsl:if> 392

内容总结 395

独立实践 395

第二十二章:使用Java解析XML 397

学习目标 397

解析器的介绍 398

DOM以及广义的基于树的处理具有几个优点 399

文档对象模型(DOM)解析实例 402

DOM对象 404

DOM解析的例子: 406

SAX解析实例 409

DOM4J解析实例 412

JDOM解析实例 413

JAVA操纵XML 实例讲解 414

通过JAVA写数据到XML里面 415

内容总结 418

独立实践 418

第二十三章:HTML基础 419

学习目标 419

知识要点 420

HTML元素 420

标签属性 420

HTML基本标签 422

标题元素 422

HTML格式 427

HTML实体 431

不可拆分的空格 431

HTML表格 439

表格 441

HTML列表 461

HTML图像 469

Img标签和src属性 469

HTML背景 475

内容总结 478

独立实践 479

第二十四章:HTML进阶 480

学习目标 480

知识要点 481

表单 481

HTML框架 488

框架 488

在子窗体中访问并控制父窗体中对象 493

内容总结 495

独立实践 496

第二十五章:JavaScript介绍 497

学习目标 497

JavaScript语言概况 498

JavaScriptJava的区别 499

基于对象和面向对象 499

解释和编译 499

强变量和弱变量 500

静态联编和动态联编 500

实例 500

内容总结 503

独立实践 504

第二十六章:JavaScript基础 505

学习目标 505

基本结构 506

JavaScript代码的加入 506

基本数据类型 506

常量 507

表达式和运算符 509

实例 511

JavaScript程序构成 513

事件驱动及事件处理 516

内容总结 519

独立实践 520

第二十七章:JavaScript进阶 521

学习目标 521

基于对象的JavaScript语言 522

对象的基础知识 522

this关键词 523

new运算符 523

常用对象的属性和方法 525

算术函数的math对象 527

创建新对象 529

JavaScript中的数组 532

实例 535

文档对象功能及其作用 538

document中三个主要的对象 539

文档对象的基本元素 541

窗口及输入输出 544

输出流及文档对象 546

简单的输入、输出例子 547

内容总结 551

独立实践 552

第二十八章: Servlet 553

学习目标 553

Java Servlet概述 554

Servlet能够做什么 554

Servlet的生命周期 557

Java Servlet API 560

Web上使用的HTTP Servlet 560

处理HTTP Servlet的关键方法 560

其它相关接口的说明 561

HTTP协议基本概念及其特点 563

获取Cookie 565

HTTP响应报头--Response 566

会话管理 566

Servlet过滤器 569

Servlet监听器 576

内容总结 579

独立实践 580

第二十九章: Jsp 技术 583

学习目标 583

JSP介绍 584

JSP语法 584

模板元素 588

指令元素 588

页面指令 588

标签库指令 593

脚本元素 593

动作元素 597

<jsp:include> 598

JSP内置对象 605

SessionApplication对象 610

JSP的汉字问题的原理 611

自定义标签 613

标准标签的使用 618

内容总结 621

独立实战 622

第三十章:struts入门 623

学习目标 623

Struts简介 624

什么是应用框架 624

WEB框架所要解决的问题 625

建立简单的Struts应用 627

内容总结 636

独立实践 636

第三十一章:Struts基础 637

学习目标 637

MVC 638

struts框架的优势 639

Struts如何实现Model 2, MVC 639

Struts 控制流 639

Struts framework的工作原理和组件 642

Struts ActionServlet控制器对象 642

Struts Action Classes 642

搞定Action对象 643

处理异常 643

Action的分类 643

Struts Action Mapping 646

使用ActionForward导航 647

Struts ActionForm Bean捕获表单数据 648

ActionForm的处理流程 649

Struts的其他组件 652

内容总结 653

独立实践 653

第三十二章:配置Struts组件 654

学习目标 654

三个 XML文件和一个属性文件 655

Web应用部署描述符 web.xml 655

ActionServlet的参数的配置 656

应用资源文件 658

Ant构建文件 659

配置Tiles框架 660

内容总结 661

独立实践 661

第三十三章:Struts标记库 662

学习目标 662

Struts标记库taglib介绍 663

Bean标记 663

逻辑标记 665

转发和重定向标记 668

HTML标记 669

显示错误信息的标记 673

其他HTML标记 673

模板标记 673

内容总结 676

独立实践 676

第三十四章:Hibernate基础 677

学习目标 677

Hibernate简介 678

建立简单的Hibernate应用 678

通过 Hibernate API 操纵数据库 684

Hibernate的初始化 687

访问HibernateSession接口 688

Hibernate工作原理图 691

内容总结 693

独立实践 693

第三十五章: 映射继承关系 694

学习目标 694

域模型关系 695

继承关系树的每个具体类对应一个表 696

创建映射文件 696

操纵持久化对象 698

选择继承关系的映射方式 699

映射多对一多态关联 702

内容总结 705

独立实践 705

第三十六章:HQL介绍 706

学习目标 706

HQL的出现 707

进入HQL世界 707

聚合 708

分组 709

Java中使用HQL 709

内容总结 712

独立实践 712

第三十七章 Spring介绍 713

学习目标 713

Spring简介 714

IOC控制反转 714

Spring的容器 715

AOP面向切面编程 715

AOP的专业术语 715

Spring事务管理 718

SpringStruts整合 719

SpringHibernate整合 721

独立实践 724

第一章: Java开始

学习目标

? Java技术的组成

? Java虚拟机的主要功能

? JAVA内存垃圾自动回收机制

? 运行代码的步骤

? 编写、编译并运行简单Java应用程序

Java历史

1991年,电视机,机顶盒,录象机的开发设计需要一种可移植、方便、高效的计算机语言。为了满足这种需求,由Sun公司的Patrick HaughtonJames Gosling领导的技术小组开发了JAVA

上世纪九十年代中期,Sun推出了Sun Java Development Toolkits 1.0,简称JDK1.0JDK1.0是一个功能强大的软件包,可以用来开发小应用程序和多种操作系统(Sun SolarisWindows NtWindows 95Macintosh)的应用程序。

1998Sun推出Java 2 Platform,它定义了所有Java技术的概念和标准,即包括已经实现的技术也包括尚未实现的技术;即包括Sun的实现的,也包括其它公司的实现。目前,Java 2 SDK1.6Java 2 Platform的最新定义。这个定义又可以细分为四个版本:

标准版:J2SE(Java SE),用于开发普通的小应用程序和应用程序。它是我们这门课程要讲述的内容。

Java SE的体系结构)

企业版:J2EE(Java EE),用于企业级应用。

微型版:J2ME(Java ME),用于开发移动电话,机顶盒,个人数字设备等。

JavaCard:适用于智能卡的Java平台。

Java各版本应用领域)

Java技术概述

任何复杂的事物都可以分解成一些相对简单的组成部分。Java作为一门丰富而复杂的新技术,它由下列这些技术层面组成:

? Java编程语言:定义变量、表达式、逻辑控制等基本规则。

? Java类库:Java 软件工具包(SDK)为程序员提供了几千个类,包括基本的数学函数、数组和字符串、窗口,GUII/O,网络等。

? Java运行环境:包括Java字节代码的加载器、校验器以及Java虚拟机。

? Java虚拟机:Java技术出于跨平台,可移植的考虑,没有将程序的源代码编译连接成CPU的指令序列,直接交给计算机执行。Java技术在不同的硬件,不同的操作系统之上,定义了完全相同的支持Java程序运行的虚拟计算机。Java源程序被编译成字节(byte)代码,编译后的文件名后缀是.class文件,在Java虚拟机上运行。

? Java工具:编译器,注释器(interpreter),文档生成器等工具。

? Java小应用程序:小应用程序(Applets)是一种贮存于WWW服务器上的用Java编写的程序,它通常由浏览器下载到客户系统中,并通过支持Java运行环境的浏览器运行。它由超文本标识语言(HTML)的Web页来调用。

? Java应用程序:Java Applications是一种独立的程序,它不需要任何Web浏览器来执行。它们是普通的应用程序;可运行于任何具备Java运行环境的设备中。

? 其它Java程序:JavaBean,Servlet,JSP等。

Java技术的优点

Java技术取得今天这样的成就,依赖于这门技术的先进性,Java技术具有下列优点:

? 简单、健壮:java=(c++)--++,继承了c++语言的优点,去掉了c++的难点,又加入了新的特性;许多高级语言都要由程序员进行指针运算和存储器管理。这项工作即复杂又容易出错。Java不需要程序员进行指针运算和存储器管理,简化了设计,减少了出错的可能性。

? 面向对象:Java是面向对象的程序设计语言。与面向过程的语言相比,面向对象的语言更能反映人类对世界的认识和处理模式,具有良好的代码重用性。处理复杂、庞大而且不断变化的信息系统,必须使用面向对象的程序设计语言。

? 分布式:目前,在所有软件产品中,仅供单个计算机使用的单机版软件所占的比例越来越小。大多数软件都可以运行在网络环境中。Java拥有一个网络协议对象库(TCP/IP,HTTP,FTP等),可以象访问当地文件一样访问Internet上的对象。

? 改进的解释性:为弥补解释语言速度较慢的不足,Java采用预编译的办法,将源程序生成字节代码,减轻运行时的解释工作。另一方面,有些Java运行环境采用Just-In-Time(JIT)编译器将字节代码编译成机器码直接运行,这种运行环境对于重复执行的服务器端软件特别有效,可以达到C语言的速度。

? 安全:Java语言在编译时删除了指针和内存分配,在运行时检查字节代码,拒绝执行非法的内存访问,超越权限的访问等。可以防御黑客攻击。

? 平台无关:Java通过采用虚拟机技术真正实现了与平台无关。Java软件是真正跨平台可移植的。编译过的JAVA文件,即可以在windowns上运行,也可以LinuxUnix等系统上运行。

? 多线程:允许一个应用程序同时做多个任务。

? 动态性:Java允许下载代码模块,因此,当程序运行时也能动态升级。

? 高性能:经过实际的综合评测得出结论,Java是高性能的。

Java虚拟机

Java虚拟机在Java运行环境中处于核心地位。Java虚拟机使Java语言可以跨多种平台运行,保障了SUN提出的"write once, run anywhere"的特性,其组成为:

? 指令集(中央处理器[CPU

? 寄存器

? 类文件格式

? 栈

? 垃圾收集堆

? 存储区

Java虚拟机隐藏了计算机硬件和操作系统的复杂性。使我们只面对单一的支持Java的计算机。当我们写好Java源程序后,使用编译器将源代码转换成JVM的指令序列(字节代码),保存为.class文件。执行Java程序时,JVM负责解释字节代码, JVM的指令转换成真实的机器指令,并执行。

自动内存回收(垃圾收集)

垃圾回收就是将程序不再使用的内存块释放出来,以提供给其它程序使用。程序运行时需要占用一定内存空间,当程序退出后应该把占用的内存释放,在c, c++语言中由程序保证内存的释放,但如果程序员忘记释放内存,就会在内存中垃圾增多,影响其它程序运行;Java语言实现自动垃圾回收处理,减轻了程序员的负担,杜绝了因内存管理而导致的程序中的问题。程序员可以建议垃圾回收,通过调用System.gc()实现。

常见垃圾收集机制介绍

JVM中内存划分为:堆栈(Stack)、堆(Heap)、静态存储(Static

大多数垃圾收集使用了根集(root set)这个概念;所谓根集就量正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾收集首选需要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而根集通过任意路径不可达的对象符合垃圾收集的条件,应该被回收。简单的说,就是没有任何引用指向这块内存空间,该空间的内存就可以被回收。

引用计数法(Reference Counting Collector)

一般来说,堆中的每个对象对应一个引用计数器。当每一次创建一个对象并赋给一个变量时,引用计数器置为1。当对象被赋给任意变量时,引用计数器每次加1当对象出了作用域后(该对象丢弃不再使用),引用计数器减1,一旦引用计数器为0,对象就满足了垃圾收集的条件。

基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜地必须 实时运行的程序。但引用计数器增加了程序执行的开销,因为每次对象赋给新的变量,计数器加1,而每次现有对象出了作用域生,计数器减1

Tracing算法(Tracing Collector)

基于tracing算法的垃圾收集器从根集开始扫描,识别出哪些对象可达,哪些对象不可达,并用某种方式标记可达对象,例如对每个可达对象设置一个或多个位。在扫描识别过程中,基于tracing算法的垃圾收集也称为标记和清除(mark-and-sweep)垃圾收集器。

compacting算法(Compacting Collector)

为了解决堆碎片问题,基于tracing的垃圾回收吸收了Compacting算法的思想,在清除的过程中,算法将所有的对象移到堆的一端,堆的另一端就变成了一个相邻的空闲内存区,收集器会对它移动的所有对象的所有引用进行更新,使得这些引用在新的位置能识别原来 的对象。在基于Compacting算法的收集器的实现中,一般增加句柄和句柄表。

垃圾回收的几个特点

垃圾收集发生的不可预知性:由于实现了不同的垃圾收集算法和采用了不同的收集机制,所以它有可能是定时发生,有可能是当出现系统空闲CPU资源时发生,也有可能是和原始的垃圾收集一样,等到内存消耗出现极限时发生,这与垃圾收集器的选择和具体的设置都有关系。

垃圾收集的精确性:(a)垃圾收集器能够精确标记活着的对象;(b)垃圾收集器能够精确地定位对象之间的引用关系。前者是完全地回收所有废弃对象的前提,否则就可能造成内存泄漏。而后者则是实现归并和复制等算法的必要条件。所有不可达对象都能够可靠地得到回收,所有对象都能够重新分配,允许对象的复制和对象内存的缩并,这样就有效地防止内存的支离破碎。

垃圾收集的实现和具体的JVM 以及JVM的内存模型有非常紧密的关系。不同的JVM 可能采用不同的垃圾收集,而JVM 的内存模型决定着该JVM可以采用哪些类型垃圾收集。现在,HotSpot 系列JVM中的内存系统都采用先进的面向对象的框架设计,这使得该系列JVM都可以采用最先进的垃圾收集。

代码运行过程

Java源程序通过"编译",转换成字节码。字节码被存储在.class文件中。

构成Java软件程序的字节代码在运行时被加载、校验并在解释器中运行。当运行Applets时,字节码可被下载,然后由浏览器中的JVM进行解释。解释器具备两种功能,一是执行字节代码,二是对底层硬件做适当调用。

在一些使用Java技术的运行环境中,部分校验过的字节码被编译成机器码并直接运行于硬件平台。这就使Java软件代码能够以接近CC++的速度运行,只是在加载时,因为要编译成机器码而略有延迟。

Java技术运行字节代码包含如下三大步骤:

? 加载代码-由类加载器执行

? 校验代码-由字节码校验器执行

? 执行代码-由运行时的解释器执行

Java程序运行的三大步骤)

类加载器

类加载器为程序的执行,加载所需要的类。类加载器将本地文件系统的类名空间,与来自网络的类名空间相分离,以增加安全性。当全部类被加载后,可执行文件的存储器格式被确定。这时,特定的存储器地址被分配给变量并创建检索表格。由于存储器格式在运行时出现,因而Java技术解释器增加了保护以防止对限制代码区的非法访问。

JVM中有四种类加载器,分别为(本节以下内容可以在以后再理解):

? BootStrapClassLoader:启动类加载器:虚拟机启动时最先加载系统加载关键的运行类的加载器。

? ExtClassLoader:扩展类加载器,专门用来加载所有java.ext.dirs下的.jar文件。开发者可以通过把自己的.jar文件或库文件加入到扩展目录的classpath,使其可以被扩展类加载器读取。

? AppClassLoader:应用(系统)类加载器,用来读取所有的对应在java.class.path系统属性的路径下的类

以上三个类在JDK中不能查到,他们是JVM底层使用的,我们可以认为这三者关系如下:

BootStrapClassLoader<-ExtClassLoader<-AppClassLoader

JDK中定义了一些ClassLoader类,我们可以观察到继承关系如下:

ClassLoader<-SecureClassLoader<-URLClassLoader<-AppClassLoader

我们也可以继承ClassLoader类制作自己的ClassLoader(用户定义的类加载器)。

一些关于ClassLoader的常用方法:

? sun.misc.Launcher.getBootstrapClassPath().getURLs();//根据以上叙述,应该是先获取启动类路径再转成路径的数组。

? MyClass.class.getClassLoader();//MyClass是类名

? ClassLoader.getSystemClassLoader();//获得系统(应用)级类加载器

? ClassLoader.getSystemClassLoader().getClass();//可以知道这个类加载器的名字等了

? java.lang.Thread.getContextClassLoader();//获取当前线程的上下文类加载器。

字节代码校验器

所有的class文件都要经过字节码校验器。字节码校验器主要测试以下内容:

? 代码段语法格式是否正确?

? 有无违反规则的非法代码?

? 是否违反对象访问权限?

? 是否试图改变对象类型?

字节码校验器对程序代码进行四遍校验,这可以保证代码符合JVM规范并且不破坏系统的完整性。如果校验器在完成四遍校验后未返回出错信息,则下列各项要求会得到保证:

? 程序代码所在的类,符合JVM规范的类文件格式。

? 无访问限制违例,如访问本地文件,访问网络等。

? 代码未引起操作数栈的上溢或下溢。

? 所有操作代码的参数类型将总是正确的。

? 无非法数据转换发生,例如:将整数转换为对象引用。

Java安装配置

各平台安装程序可以到SUN的网站(java.sun.com)下载,在安装完成后应该进行配置,通常集成开发环境(IDE)自带JDK或进行了自动配置,如果我们通过控制台编译或运行Java程序则必须手动配置。

JDK: Java开发工具包(J2SE Software Development Kit)的缩写,Java语言编写applet小程序和应用程序的软件开发环境,Java开发者应该安装JDK,并且通常JDK中已包含一个JRE拷贝。

JRE: Java运行环境 (Java Runtime Environment) 的缩写。它基本上就和Java虚拟机是同一个概念,运行Java程序的应该安装JRE

JDK安装目录示例)

? binjava常用开发工具目录,例如javacjavajar等工具。

? demo: sun提供的一些用于java开发的示范,如有关appletsjfcplugin等。

? include: Java提供用于c/c++调用的.h文件;

? jre: 对应版本的java运行环境文件

? sample: java案例。

? lib: java类库目录

Windows环境变量

应设置的环境变量包括:JAVA_HOME, PATH, CLASSPATH

假设J2DK安装在“C:\JDK1.5”,环境变量可设置为:

? JAVA_HOME=C:\JDK1.5

? CLASSPATH=.

? PATH=%JAVA_HOME%\BIN;%PATH%

Windows下环境变量的设置)

Linux下环境变量

假设jdk安装在/home/jdk1.5目录下,修改配置文件 /etc/profiles ,在文件的尾部加入如下信息:

JAVA_HOME=/home/jdk1.5

CLASSPATH=.

PATH=$JAVA_HOME/bin:$PATH

第一个Java程序

编写一个程序,输出一行文本信息:"Welcome to Java Programming"

编辑器的使用

Java代码的开发可以使用常见的编辑器,如:写字板,EditplusUltra Edit,也可以使用专用的开发工具,如:JBuilder, Eclipse, NetBeans,JCreator等。在开始学习时,建议先学习使用带有关键字颜色提示的EditPlus开发Java代码。

Editplus下的Java程序显示

编写程序

1 //这是一行注释

2 public class Welcome {

3

4 public static void main(String[] args) {

5 System.out.println("Welcome to Java Programming");

6 }//main方法结束

7

8 }//类结束

1:注释:用来说明程序的作用

2:开始声明一个类,类名为Welcome, classJAVA的关键字,用来定义类,public为访问说明。在这里我们声明了一个类,类的名字为Welcome.

37:空行,用来增加程序的可读性

4:是JAVA应用程序必须包含的方法,被称为入口方法:程序运行时从这里开始执行,其形式必须是:

public static void main(String[] args) 或者

static public void main(String[] args)

上面的语句里,只能修改 args这个字符串数组的名字。

static 表示直接能够加载该方法运行。

void 是方法的返回类型 ,每个方法必须有返回类型(除了构造方法)。

main是方法的名字,是程序的入口调用的方法。

String[] 是方法的参数,必须是String 数组类型的 。

5 System.out.println("Welcome to Java Programming");

就是输出字符串的,双引号中的字符串会在控制台输出。

也可以使用以下语句输出一个对话框显示信息:

JOptionPane.showMessageDialog(null, "Welcome\nto\nJava\nProgramming!" );

程序的开头要加入以下语句:

import javax.swing.JOptionPane;

6"}"表示方法的结束。

8:表示类的结束。

编写完成后,以Welcome.java文件名保存到指定目录中。

配置环境和编译

在控制台使用如下命令编译刚才保存的文件Welcome.java

将会生成对应类名的.class文件:Welcome.class,如下图:

Editplus下也可以直接编译并运行JAVA代码,配置如下:

打开用户工具栏:视图/工具栏/窗口/用户工具栏

选择配置工具栏

配置相应的内容

运行JAVA程序

在控制台使用如下命令运行刚才生成的文件Welcome.class

注意:运行时,不可以加文件的扩展名.class

内容总结

JAVA是一门丰富而且复杂的技术;

JAVA虚拟机处于核心地位,保障了JAVA的平台独立性;

虚拟机可以进行自动内存管理,并且进行安全检查;

JAVA包含三个版本,分别适用于不同的应用需求;

开发JAVA程序的三大步骤:编写JAVA源程序,编译源程序,运行程序。

独立实践

实践1: 编写程序,实现在控制台输出一行文本"I LOVE JAVA!"

实践2: 编写程序,实现在对话框输出文本"I LOVE JAVA!"

实践3: 假设:Welcome.javad:\study,编译后生成Welcome.class.

如何可以在任意路径运行此程序?

实践4:以下main函数定义正确的是:

1 public static String main(String[] args)

2 public static void main(String args[])

3 public void main(String[] args)

4 static public void main(String args[])

5 public void static main(String[] args)

第二章: 面向对象概述

学习目标

? 掌握什么是面向对象以及面向对象的主要特点

? 了解OOAOODOOP的概念以及之间的关联

? 了解面向对象程序语言的发展简史

面向对象(Object Oriented)

面向对象是一个广泛使用但涵义并不清晰的术语。上世纪80年代面向对象主要指一种程序设计方法,但在随后的发展中,面向对象的方法已经渗透到计算机软件领域的许多分支。在了解面向对象之前我们必须得了解两个重要概念:对象和类。

什么是对象?

首先,我们来了解一下什么是对象。对象的概念最早出现于五十年代人工智能的早期著作中,在现实世界中,我们可以将对象定义为:

对象(Object):一个具有明确行为的有形实体,具有行为和状态,有着清晰的边界。

以面向对象的眼光来看待现实世界,现实世界中的每一个具体事物,我们都会将其看作一个对象,比如狗、电视机、自行车等,都可以是对象。狗有特定的名称、毛色、品种、会饿等特点,还有狗叫、尾巴左右摇摆等动作;同样的,自行车也有品牌、重量等特点,同时具备换速、刹车等动作;依此类推,我们不难发现,现实中的每一个对象都会有自己的特点以及相关动作,我们将对象所有特点(属性)称之为对象的状态,而动作称之为行为。

属性(Attribute):对象的一种内在的或独特的性质、特点、质量或特征,它构成了一个独一无二的对象(摘自<<Objects-Oriented Analysis and Design with Applications>>)

每一个学生具备名称、性别、年龄、身高、长相、爱好等属性,通过这些属性我们可以很快地区分所有的学生对象,因为这些属性构成了每一个独一无二的学生对象。比如说,在大部分情况下,我们会通过学生名称来区分每一个学生对象。我们经常会说:某某人很高,某某人很年轻等,高和年轻实际上就表现出某一个对象的内在的特点。因此,可以这样理解,我们是通过每一个对象特有的属性来区分各个对象。

注意:属性都有其对应的值,而且某些属性值是可以动态改变的,比如学生的体重、爱好是可以改变的,而DNA、指纹却是不能改变的。

随着属性值的改变,状态也随之改变了。比如,学生甲的身高值逐渐增长了,那学生甲的状态也发生了变化----长高了!

状态的具体定义如下:

状态(State):包含对象的所有属性以及属性值,会随着属性值的改变而改变。

没有一个对象是孤立存在的,对象之间是相互作用的。行为就是指这种作用。

行为(Behavior):是一个对象根据它的状态改变和消息传送所采取的行动和做出的反应,代表了对象对外的可见、可测试的动作。(摘自<<Objects-Oriented Analysis and Design with Applications>>)

行为和状态是相互的。Dog处于饿的状态时,就会采取进食等行为,进食完毕后,Dog又会处于饱的状态。现实中,大多对象是通过接受另一个对象传递的一个消息(操作)来改变自身的状态。比如:驾驶员扭动汽车启动钥匙至关闭位置,此时,汽车关闭引擎。其中,驾驶员、汽车都是对象,而关闭引擎则是一个特定消息,是由驾驶员传递给汽车的消息,汽车根据这个消息改变状态---从启动状态变为关闭状态。因此,消息实际上就是一个对象对另一个对象施加的操作。

小练习

列举现实生活中5种对象以及相关的属性和可能的行为?

在软件开发中,对象一词的正式应用是在Simula*语言中,在Simula中对象是用来描述现实的某个方面。对象的范围更广,除了现实中描述的对象之外,还包括在软件设计中产生的一些产物,这些产物一般用来实现更高级的行为功能。

Simula--20世纪60年代产生的一种面向对象语言,是所有基于对象和面向对象语言的原型,用于描述系统和开发仿真的语言。

在软件中,对象代表一个单独的、可确认的实体,可以是具体的也可以是抽象的,必须有明确定义的一个这样的角色。相似对象的属性和行为在它们的共同类中定义。

在软件中,对象可能有很清晰的边界,然而却是抽象的;也可能是具体存在的,但边界不明确。注意,软件中的对象和现实中对象同样有其自身的状态和行为!每一个对象在软件中都会拥有自己的空间(内存)和唯一标识名。一般,我们也将对象称之为实例(instance)。通俗地讲,对象指的是客观世界中的实体, 它能"知道一些事情"(即存储数据),"做一些工作"(即封装服务),并"与其它对象协同"(通过交换消息),从而完成(模块化)系统的所有功能。对象反映了系统保存和处理现实世界中某些事物的信息的能力。

什么是类?

在现实世界中,我们会将所有脊椎动物对象进行分类:鸟类、两栖爬行类、哺乳类,比如我们将leopardtigermonkey等脊椎对象都归纳为哺乳类,而eaglecraneswan属于鸟类。那我们又是怎样去判断哪种动物是属于哪一类的?

我们发现,leopardtigermonkey都具备viviparity(胎生)lactation(哺乳)coat(皮毛)等哺乳动物特征,而eaglecraneswan却具备feather(羽毛)flight(飞翔)beak()等鸟类特有的特征。不难发现,。这些对象都具有一些共同的属性和行为,通过这些属性和行为的划分,我们将leopardtigermonkey划分为哺乳类,而eaglecraneswan划分为鸟类。

类和对象是紧密关联的,没有对象就没有类!

类的定义:类(Class)是一组共享公共属性和公共行为的对象的集合。

类可以是一种抽象,是一个蓝图,即可以不具体存在;它实际上是对一组对象的公共部分的归纳集合,而对象却是一个具体的存在,是实体而非抽象。我们可以这样说:类Mammal代表所有哺乳动物的共有特征,所有的非公有特征都不属于类Mammal,比如皮毛的颜色、喜好的食物等都不会归纳到类Mammal。而当我们想去识别某个特定的哺乳动物时,就必须指定"这个哺乳动物"或者"那个哺乳动物",即对象,也就是说,当我们需要去分析哺乳动物特有的属性和行为时,那就必须针对具体的对象来研究,而不是针对一个抽象的类!

注意:在软件开发中,我们将一个对象称之为类的一个实例。

没有公共结构和公共行为的对象,我们不能将它们组合在一个类中。比如,我们都知道不能将pinastersquirrel组合成一个类,是因为pinastersquirrel并没有共享结构和公共行为,比如 pinaster有枝叶而squirrel没有,squirrel能行走而pinaster不能等等。

在现实世界中,我们认识事物的时候都是首先将所见事物进行分类,然后按照每种类别去逐一研究事物对象。同样,在软件领域中,我们也是将问题进行分解分类(将大问题分解成许多小问题,每个小问题可以归纳为一类),然后再针对每一类进行分析设计以及实现,这就是广义的面向对象。

面向对象定义:尽量模仿现实世界,在软件中将复杂问题中的实体都作为一个对象来处理,然后根据这些对象的结构和行为再划分出类(即实现问题的分解),最后实现软件的模拟仿真。

也可以理解为:现实世界中的实体抽象成模型世界、程序世界中的对象和类,设计它们以完成预期任务并具有更好的可维护性和健壮的结构。

注意:在软件领域中,类包含了对象的属性和行为的定义,是一组属性和行为操作的集合!

只有掌握了对象和类的概念,我们才能清晰、准确地明白什么是面向对象!当然,对面向对象的深入了解还必须掌握面向对象的一些相关特性,在下一小节我们将具体学习。

面向对象的主要特性

程序语言发展到如今,已出现了多种风格不一的编程语言,大体主要分为以下两种风格的语言:

? 面向过程(C语言为代表)

? 面向对象(JavaSmalltalkC++)

并不是说哪种语言是最好的,每种风格语言的好坏是针对不同方面的应用程序而言的。比如说,面向过程语言适用于计算密集型操作(复杂算法等)的设计,而面向对象适用于广阔的应用程序范围(这也是Java能迅速发展并占据广大市场的原因之一)

面向过程(Process Oriented):基于该风格的程序的设计都是在想怎样才能一步一步的解决问题,思维方式是过程,或是说步骤。

那怎么区分面向过程和面向对象的区别,只要是具备以下特点的语言我们都可以将其看作为实现了面向对象的语言:

抽象(Abstraction)

在前面,我们已知道通过抽象创建出了类,类就是抽象的一种表示。抽象是解决问题复杂性的一种基本方法,抽象会重点强调我们应该注意什么,而不应该注意什么!通过抽象我们可以着重实现需关注的细节而忽略一些非实质性或无关紧要的细节,从而能够更好的分析问题解决问题!

抽象:表示一个对象与其它所有对象区别的基本特征,为不同的观察者提供不同的角度来观察对象。

对同一个对象---电视机,维修员只会关注电视机的内部结构:线路是否断裂、显像管是否损坏等,而购买电视的客户却只会关心电视机的画面是否逼真、外观是否好看等等,客户不会也不用关心电视机的内部结构。可以看出,维修员只关心电视机的内部,购买用户只关心电视机的外观及实用性,他们观察电视机的角度不一致,这就是抽象的实现,在现实生活中,到处都存在着抽象!

抽象强调实体的本质、内在的属性,在软件开发中,抽象指的是在决定如何实现对象之前对对象的意义和行为的定义----即类的实现!通过对类的了解,我们也可以将抽象定义为:从许多事物中舍弃个别的、非本质的特征,抽取共同的、本质性的特征。

为什么需要抽象?

首先,问题的复杂性日益增长,其中描述的事物也越来越复杂,如果分析员去了解每一个事物的所有方面,那将是一个穷举耗时、低效率的工作

其次,如果没有识别所有对象的共同特征的行为,那么对这些对象的分类将无法进行!

对象分类是面向对象中非常重要的环节,而抽象则是实现该环节的必须解决方案!抽象的本质就是将问题分解,在面向对象中,所有对象被抽象成各种类,从而让程序员集中关注于功能的实现!

小练习

列举现实生活中的抽象例子,最少3例。

封装(Encapsulation)

我们再来思考上面的例子,对于客户来说,他只会关心电视机的外观及性能是否良好等方面,电视机中的显像管、集成电路板对客户而言是不可见的,即电视机的生产商已将这些配件通过电视机外壳包装了起来,对客户,配件是隐藏的!现实中,这样的例子很多,比如计算机对于购买者而言,其组成部分CPUMainboardHDPC配件都被封装在机箱内,是不可见的!

封装:是一种信息隐蔽技术,是一个划分抽象的结构和行为的过程。

封装和抽象是互补的,抽象着重于对象的行为,而封装着重于对象的行为的实现。抽象实现抽取众多对象的公共特征和行为,而封装则是在不同的抽象之间设置明显的分隔线,从而导致每一个观察者关注内容的明显分离!没有抽象的封装将无意义;没有封装的抽象是不完整的!

在开发中,封装可以更通俗的理解为:把代码和代码所操作的数据捆绑在一起,使这两者不受外界干扰和误用的机制,封装可被理解为一种用作保护的包装器,以防止代码和数据被包装器外部所定义的其他代码任意访问,对包装器内部代码与数据的访问通过一个明确定义的接口来控制。

封装代码的好处是每个人都知道怎样访问代码,进而无需考虑实现细节就能直接使用它,同时不用担心不可预料的副作用。

继承(Inheritance)

类和类之间的关系之一,是面向对象系统的最基本要素。继承表明为一个"是一种"的关系,在现实中有很多这样的例子:人类是一种哺乳动物;树是一种植物类…….。为什么人类是一种哺乳动物?答案:因为人类具备所有哺乳动物的特征(结构和行为),也就是说,人类继承了哺乳动物的特点!我们经常会这样描述:儿子继承了父()亲的优()点!

继承:一个类共享一个或多个类中定义的结构和行为,表示的是一种泛化/特化的层次关系。

注意:类和类之间实现继承的前提是这些类之间有着必然的联系---"A是一种类B"!假如:我们将树继承于哺乳动物,而人类则继承于植物类!大家想想看,结果会如何?

我们在使用继承的时候必须得遵守这样的检验标准:如果类B"不是一种"A,那么类B必然不是从类A继承而来!

? 当类B继承于一个类A,那么这种继承称之为单继承。

? 当类B继承于多个类ACD等,那么这种继承称之为多继承。

也可以这样理解,当实现单继承时,那类B继承了类A的所有属性和方法(比如人类继承了哺乳动物的所有属性和行为);而实现多继承时,类B继承了ACD等多个类的所有属性和方法(比如儿子继承了母亲和父亲的所有优、缺点)。其中,类B称之为子类(派生类)subclass,而类ACD则称之为超类(父类、基类)superclass

泛化(generalization):将一些有关联的不同类中的共同结构和行为抽取出来,构成一个新的超类。

特化(specialization):和泛化正好相反,从一个或者多个超类中派生出多个子类。

简单理解就是:超类的创建代表泛化,子类的派生代表特化!

子类除了能通过继承共享父类的属性和行为之外,还能修改继承于父类的属性和行为,最重要的一点就是:能在继承父类的基础上定义属于子类自身的属性和方法,从而实现扩展!以上这段话就是继承的最神奇之处!面向对象使继承得到了充分的体现!

学习技巧:大部分同学在初学时往往对继承、抽象等概念一知半解,建议大家多结合实际例子来学习,可以多想想周边的现实世界中哪些是继承、哪些是抽象。

多态(Polymorphism)

我们来假设思考一下现实中的一个问题:

假设,某条snake和某条cabrite,它们都取名为Jack,注意,snakecabrite有着共同的超类---爬行类,都具备爬行类的公共行为:爬行。但我们发现,虽然一个名字Jack代表两种不同类对象,但是这两个对象却是用不同的方式来爬行,Jack(snake)通过蠕动身上的鳞片来爬行,而Jack(cabrite)则通过四肢来爬行。

虽然,在现实中我们可以通过给这两个对象取不同名字用以区分,但上面的例子向我们演示了这样一个过程:

一个名字可以表示许多不同类(这些不同类必须拥有一个共同的超类)的对象,从而实现以不同的方式来响应某个共同的操作集。

以上就是多态的定义,多态只有通过继承才能实现!在后面章节我们会详细掌握多态以及其运用。

以上就是面向对象的一些主要特征,具备了这样特征的程序语言我们就可以称之为面向对象语言。

面向对象的优点

先来看一下软件复杂性,软件固有的复杂性:

? 维护过于困难

? 修改每一个地方将会牵涉到许多功能模块的变动,复杂性加大。

? 过于僵硬,扩展困难

? 由于系统的关系错综复杂,很难添加新的功能。

? 重用率过低,导致大量冗余

? 在每个项目中往往会出现大量的代码冗余,不能很好的重用。

? 耦合度过高,导致理解、修改困难

? 每一个程序之间联系过于密切(强耦合),增加了阅读和修改的复杂性。

一个好的系统应该具备如下的性质:

可扩展性、灵活性、可插入性。

--Peter Code[CODE99]

通过面向对象就能很好的处理以上的复杂性。在面向对象过程中,我们根据问题领域中的关键抽象来分解系统,识别关键对象并将其分类,最终达到将复杂问题分解成多方面来分析和实现。

比如,PC机就是一个很复杂的设备,为了更好的了解PC,我们就会将PC的组成部分分解,再逐一了解,从而达到复杂问题简单化。PC包含CPUdisplaykeyboardHD等,通过对这些部件的逐一熟悉,PC就不会显得很复杂了。而且,如果我们只想了解PC的处理速度,那么就只需专注于对CPU的了解(通过抽象来实现)

面向对象是一种尽量模仿现实世界的思想,以上对PC的了解就是我们在现实中对一个复杂事物进行分解熟悉的一个过程,面向对象就是这样的一个过程,只是复杂许多。

面向对象的一些主要优点:

? 和现实世界更接近,更符合我们人类的思维逻辑

? 开发出的系统容易维护和修改

? 适用于开发复杂、庞大的系统

? 开发出的程序更稳定合理

? 由于继承、类的机制,更容易实现重用,减少冗余

? 由于实现数据和逻辑的分离,维护和扩展变得更加容易

面向对象的分析、设计和编程

在面向对象开发中,一般都会遵循三方面来分析解决问题:

? 首先,通过一些好的方法对问题进行分析,寻找问题中的对象实体、类。

? 其次,基于分析结果使用类和对象抽象在逻辑上构建系统,实际上就是使用面向对象的各种分解方法来建立系统的逻辑、物理模型和动态、静态模型。

? 最后,就是运用不同的面向对象语言对设计的结果的实现,即类和对象的实现。

下面我们就这三方面具体来学习。

面向对象分析(Object-Oriented Analysis)

面向对象分析(OOA)方法是建立在对象及其属性、类属及其成员、整体及其部分这些基本概念的基础上。

大英百科全书指出:

人类在认识和理解现实世界的过程中普遍运用着三个构造法则:

a.区分对象及其属性。例如,区分一棵树和树的大小或空间位置关系。

b.区分整体对象及其组成部分。例如,区分一棵树和树枝。

c.不同对象类的形成及区分。例如,所有树的类和所有石头的类的形成和区分。

OOA就是建立在以上三个原则的基础上的,每个软件都建立在特定的现实世界中,OOA阶段产生的模型就是用来形式化该现实世界的"视图"---我们称之为建模。有许多优秀的方法作用于整个OOA阶段,如Shlaer-Mellor, Jacobson, Coad-Yourdon, CharlesAbbott等,还有现今已成为建模主流的UML(Unified Model Language)

OOA就是仔细的划分系统的各个部分,明确它们之间的层次关系,然后将各个部分作为一个对象进行功能上的分析的一个过程。包括业务分析和需求分析。

OOA:是一种分析方法,它以可在问题域的词汇表中找到的类和对象的观点来理解、审视需求。(摘自<<Objects-Oriented Analysis and Design with Applications>>第二版)

虽然面向对象分析和面向对象设计的侧重点很不相同,但二者之间的界限是很模糊的,在开发中,我们往往不能明确的区分二者的范围。从上面的描述可以知道,在分析中,我们通过发现构成问题域中的词汇表来寻找类和对象,从而模拟现实世界对软件建模。

OOA阶段的方法众多,各有其特点,这里我们只介绍一种最简单的方法:非形式化的语言描述。这个方法是由Abbott提出,他建议用语言(英语)写出问题的描述,接着在名词和动词下面划线;名词代表对象,动词代表对象的操作。

例子

描述一个顾客购买机票的场景。

顾客选择某一个柜台,首先顾客向柜台助手查询某一天的航班信息以及是否有机票预订,柜台助手往电脑里输入查询信息并查看结果,如果有机票,顾客则填写预订表预订机票,柜台助手输入预订信息并打印机票,最后将机票返回给顾客。

单下划线代表对象,双下划线代表操作。通过Abbott方法我们可以分析出该场景中的对象和操作,名词:顾客、柜台助手、航班信息、机票、查询信息、机票;动词:查询、预订、打印。

在使用UML建模时,OOA阶段主要是通过另一种方法---用例分析来实现系统的用例图以及简单类图和时序图等,既UML是将系统用一种统一标准的图形来表示(在后期会专门学习)

面向对象设计(Object-Oriented Design)

OOD是对OOA的细化,强调的是复杂系统的正确和有效的构建,通过不同的方法来着重于系统的逻辑设计、物理设计。如果说分析是产生系统的类和对象,那么设计则确定类和类之间的关系、对象和对象之间的关系、类的状态转换、模块之间的依赖性等。

OOD特点

? 没有严格的界线

? OOD的结果直接用于编码

? 与OOA的输出一样,只是更加详细完善

OOD:是一种设计方法,包含面向对象分解的过程以及一种表示方法,用来描述设计中系统的逻辑与物理模型和动态与静态模型

OOD步骤

? 细化重组类

? 细化和实现类间关系,明确其可见性

? 增加属性,指定属性的类型与可见性

? 分配职责,定义执行每个职责的方法

? 对消息驱动的系统,明确消息传递方式

? 利用设计模式进行局部设计

? 画出详细的类图与时序图、状态图、对象图等(UML)

OODOOA的区别

? OOA偏重于理解问题,描述软件要做什么,而OOD偏重于理解解决方案,描述软件要如何做

? OOA只考虑理想的设计,不关心技术与实现底层的细节,而OOD需要得到更具体详细更接近于真实的代码的设计方案

? 在设计结果的描述上,OOA偏重于描述对象的行为,OOD偏重于描述对象的属性与方法

? OOA只关注功能性需求,OOD还需要关注非功能性需求

一个设计的好坏直接决定程序的成败,因此,在往后的项目实战中,大家一定要全面、仔细、合理的进行设计。

面向对象编程(Object-Oriented Programming)

OOP是对设计的一种代码实现方法,在该阶段,我们将采用合适的面向对象语言来编码实现设计阶段产生的系统架构。

OOP:是一种实现方法,程序被组织成对象的协作集合,每一个对象代表某一个类的实例,而类则是通过继承关系联系在一起的。

OOP阶段必须满足三个标准条件

? 使用对象而不是算法(面向过程则是使用算法)作为其基本逻辑构件

? 任何一个对象都必须是某一个类的实例

? 类通过继承关系和其它类相关

OOP的关键就是面向对象语言的选择以及面向对象特点的实现。实际上,有很多程序员对面向对象和基于对象(Object-Based)的语言概念很模糊,容易混淆。当一种语言满足以下条件时才能称之为面向对象语言:

? 对象必须是数据的抽象

? 每一对象对应相关类

? 子类可以从超类中继承属性和方法

如果某种语言只满足了以上的前两个条件,而第三个条件并没满足(JavaScript语言),那么我们就将该语言称之为基于对象的语言。

面向对象语言的发展简史

编程语言从最初的复杂机器语言发展到如今的高级面向对象语言,经历了近50年的历史,其中,产生了四代计算机语言:

? 第一代:(1954-1958)

Fortran IALCOL 58Flowmatic等语言,主要应用于数学和工程应用,几乎全部使用数学词汇。

? 第二代:(1959-1961)

Fortran IIALCOL 60COBOLLisp等语言,重点在于算法抽象,集中于告诉机器应该做什么,比如通过这些语言编写的算法会告诉机器应该在查看员工数据之前进行排序。

? 第三代:(1962-1970)

PL/1(FORTAN+ALCOL+COBOL)PascalSimula(最早出现类和对象的思想的语言),对数据()抽象,描述各种类的类型。

? 第四代:(1970-至今)

SmalltalkC++AdaJavaEiffelPHP等语言,都是面向对象或基于对象的语言。

发展到至今,高级语言已出现了2千多种,现在仍在不断出现(Ajax等新语言),呈一个高速发展阶段,而现今主流的语言就是我们所学的面向对象语言,对于复杂的问题面向对象语言能比任何其他种类语言更好的解决,其中的代表性语言是-Java

Simula是最早出现类和对象的基本思想的语言,后期产生的各种面向对象或者基于对象语言均是从Simula语言的基础上发展而来。比较典型的有:Java(纯面向对象)Smalltalk 80(纯面向对象)C++(面向对象)Object Pascal(面向对象)Ada(基于对象)等。

对象不是类,类却可以是对象,请思考是否正确

对象之间的关系

? 上下级关系

对象之间的一个物理或概念联系,一个对象通过它与另一个对象之间的上下级关系协作,通过上下级关系,对象和对象之间可以相互传递消息,即一个对象可以通知另一个对象并产生响应。注意:对象之间可以双向传递消息。

? 聚合关系

表示一个整体/部分的层次,表示物理包含和非物理包含。如:PC包括CPUkeyboardmemory bank,这就是物理包含;而股东拥有股票,但股票不是股东身体的一部分,这就是非物理包含。

OOA模型的结构

? 第一层:对象-类层

表示待开发系统的基本构造块。图符的外层边界表示实例边界,实际上它表明对象是非空的。而图符的内层边界则表示类边界。在某些情形下,定义这种对象是很有用的。我们将它们称为模板类或抽象类。模板类可以为结成较高级的聚合体提供一条方便的途径。

? 第二层:属性层

对象的属性和实例连接共同组成了OOA模型的属性层。我们把对象所存储的数据称为对象的属性。类的实例之间互相约束,它们必须遵从应用论域的某些限制条件或事务规则。例如,当定金取消后,相应的订户也应该被取消,这可能是一项事务规则。我们称这些约束为实例连接。

? 第三层:服务层

对象的服务和消息通信组成了OOA模型的服务层。我们把对象所做的工作称为服务或方法。系统的不同对象都分别执行一定的工作或功能,它们之间通过消息通信,即所谓的协同。对象的服务及对象实例之间的消息通信共同组成了OOA模型的服务层。

? 第四层,结构层

该层负责捕捉特定应用论域中的结构关系。泛化、特化等结构,整体-部分结构表达了人类的一种基本组织方式,即自然的整体和部分的结构关系,从而把一些部分的聚合构造成整体。例如,一辆汽车由发动机、传动装置和刹车装置组成。

? 第五层:主题层

相当于全局系统的子系统或子模型。由于OOA模型的结构庞大而复杂,因此众多的对象有时很难处理。于是,可以把对象归到各个主题层中,可以把有关的对象用一个边框框起来加以实现。例如,在一个控制系统中,众多的对象可分为"管理""控制"两个主题。

类和类之间的关系

? 关联

? 一对一,保险合同与保险人、订单与客户

? 一对多,订单与商品、职员与部门

? 多对多,学生与课程、项目与程序员

? 继承

? 泛化和特化的实现,分为单继承和多重继承

? 聚合

? 同对象的聚合类似

? 实例化

? 定义类的一个对象

参考书籍:<<Objects-Oriented Analysis and Design with Applications>>(Second Edition)

内容总结

? 对象(Object)是一个具有明确行为的有形实体,具有行为和状态,有着清晰的边界,具备属性、行为、状态。

? 对象的属性及其值表现状态,不同的状态会有不同的属性。

? 对象的状态和行为是相互的,行为可以改变状态,状态可以促使行为的产生。

? 类(lass)是一组共享公共属性和公共行为的对象的集合,类是一种抽象,是蓝图,不具体存在。一个对象称之为类的一个实例。

? 类包含了对象的属性和行为的定义。

? 面向对象的主要特征:抽象、封装、继承、多态。

? 在OOA中,我们通过发现构成问题域中的词汇表来寻找类和对象,从而模拟现实世界对软件建模。

? OOD是对OOA的细化,强调的是复杂系统的正确和有效的构建,通过不同的方法来着重于系统的逻辑设计、物理设计。

? OODOOA的区别。

? 面向对象与基于对象语言的区别。

? 四代程序语言的发展,面向对象语言属于第四代语言。

独立实践

? 观察猫和老鼠,用自然语言描述出猫和老鼠的属性、状态、行为。

? 描述猫抓老鼠的过程。

? 试分析:”螳螂在前,黄雀在后这句话包含几个类及这些类之间的关系.

第三章:面向对象的程序设计学习目标

? 类和对象的描述

? 类,属性,方法,构造方法定义

? privatepublic访问权限的介绍

? 源文件的布局

? 包的声明和导入

? 包与目录的布局

? CLASSPATH环境变量的使用

? API文档的使用

类和对象的描述

现实社会中一切皆对象。比如:人,树,石头,猫,鸟,汽车,地球等等。任何一种对象都具有静态的属性,但不一定具有动态的行为。比如:石头。一般情况下,对象既有静态的属性,也有动态的行为。对象本身的属性和行为之间可以相互影响,比如:一个人饿了(属性),就会去吃饭(行为)。相反,这个人吃饭(行为)后,就饱了(属性),体重(属性)也增加了。不同的对象之间也可以相互作用。比如:人看到汽车开过来了,就会沿着路边走。如果这个人站在路中间不动(他不怕死),那么汽车就会停下来。那么怎么用Java语言来实现上述功能呢?后面实例分析有实现。

如同建筑设计师设计建筑图(建筑的蓝图),可以用该图来盖出许许多多这种风格的房子一样。类是对象的蓝图,是用来描述对象的,你可以用该类,来实例化许许多多个该类型的对象,类就是对象的模板。在类中定义了一套数据元素(属性)和一套行为(方法)。数据是用来描述具体的一个对象(静态),行为是用来描述该类型对象的共性,也就是该对象能够做什么(动态),以及完成相关对象之间的交互,从而改变对象的状态。同样对象的状态也能够对象的行为。属性和方法都叫做类的成员。例如杯子装水的时候:最大盛水量和当前盛水量。盛水的方法要始终跟踪这两个属性。 装水时改变了当前盛水量的属性,同样当当前盛水量等于最大盛水量(水装满时),就会影响装水的行为,将不再倒水。

我们下面通过一个具体事例来说明Java中如何实现以上概念。

1

编写一个类,描述人吃饭,体重增加这个简单操作。

下图描述了一个

这是一个UML中的类图,我们对它进行简单说明。

? 第一行:是类名Person,代表我们正在说明一个的概念。

? 第二行:是属性,“-” 号代表这个属性只有这个类自己可以访问,weight代表属性的名字,double表示属性的类型,这里意思是人有一个体重的特性,体重可以是小数,别人不能直接看出人有多重,必须使用某种称量体重的方法

? 第三行、第四行:是构建器,“+” 号代表public访问权限,含义是任何人可以访问到它。构建器是外界创造出这个概念的实际例子的入口,第三行是按照缺省方式构建,第四行是按照特定方式构建,特定方式是指按照参数指定的属性构建

? 第五行、第六行:是方法,其中eat方法有参数,参数名字是temp,参数类型是double,该方法的返回类型为void,该方法含义是人可以吃一定数量的食物,吃完不需要给外界任何回馈。第六行的方法getWeight()没有参数,返回double类型,含义是看这个人的重量。

声明类

Java中的语法和C一样,语句都是以分号结束,区分大小写。

Java技术中采用下列方法声明类:

<modifier> class <name>{

<attribute_declaration>

<constructor_declaration>

<method_declaration>

}

说明:

<modifier>:暂时只用"public",含义为:可以被所有其它类访问。或者不加public 在修饰类的访问权限的时候,只有两种:1,就是加上public,表示所有类都可以访问。 2,就是什么也不写,表示本包访问权限,在讲到包的含义时再理解。

<name>:任何合法的标识符。它代表所声明类的名称。

Java中的标识符(类名,变量名,方法名)是由字母,数字,下划线(_),美圆符($)组成,数字不能用于标识符的开始。其中长度不受限制,不能使用java中的关键字,并且是区分大小写的。比如:classvoid等关键字。Java中的关键字都是由小写的字母组成的,所以在我们并不知道java中有那些关键字的情况下,在定义标识符的时候,只要不全是小写的字母,就不会和java中的关键字相冲突。

<attribute_declaration>:声明属性。也就是说用变量表示事物的状态。

<constructor_declaration>:声明构造函数。也叫构造方法,也叫构造器。是用来实例化该类的实例(对象)的。

<method_declaration>:声明方法。来说明事物能够做的事情,也就是行为。

注意:属性,方法,构造函数在类中的顺序没有固定的约束。一般习惯性地先声明属性,后声明方法(习惯性地把构造方法写普通方法的前面)。

所以Person这个类的初始版本应该是:

public class Person{

}

声明属性

<modifier> <type> <name> [ = <default_value> ];

说明:

<name>:任何合法的标识符。它代表所声明属性的名称。

<modifier>:暂时只用“public”“private”,其中private含义为:仅能被所属类中的方法访问,这称作封装。

<type>:可以是任何原始类型(基本类型)或其它类(引用类型)。

[=<default_value>]是给属性初始化为给定的值。如果没有的话初始化为默认的值。(基本类型的初始化相应的值:比如:intshortbytelongcharUnicode码值)初始化为0floatdouble初始化为0.0boolean初始化为false,所有的引用类型都初始化为null)。

注意:Java语言与其它语言不同,在JAVA中声明属性和初始化属性值必须一句完成。不能分开写:先声明,再另起一行初始化。

例如:

private int a ;

a=5; //错误

private int b=6;//声明一个属性 b,并初始化为6

在类里面除了声明语句之外,是不能直接写其它执行语句的。 a=5 是赋值语句。如果要执行语句应放在语句块(方法块,初始化块等)里执行。

据此,我们的Person类成为如下样子:

public class Person{

private double weight;

}

声明构造器

<modifier> <class_name> (<parameter>) {

<statement>

}

说明:

<class_name>:是类名,构造器的名字和类名必须一样。

<modifier>:可以是public,指明可以被任何其它代码访问。private,指明仅能被同一个类中的其它代码访问。

<parameter>:向构造器传递参数,可以没有参数。传递多个参数时,参数之间用逗号分开。每个参数由参数类型和标识符组成,这和声明属性的方式很类似,但是不能向参数赋初始值。

注意:构造器必须没有返回类型,并且构造方法的名字和类名必须一样。当一个类里面如果没有声明构造方法,那么虚拟机将自动给该类一个默认的构造器(不带参数的构造器)。如果在该类里面,定义了带参数的构造方法,那么虚拟机将不再为该类提供默认的构造方法,也就是该类不能按缺省方式构建了。

我们的类此时变成:

public class Person {

private double weight;

// 该类的默认的构造器

public Person() {

}

// 带参数的构造器

public Person(double d_weight) {

weight = d_weight; // 实例化对象时,给weight属性赋初始值

}

}

声明成员方法

<modifier> <return_type> <name> ( <parameter> ){

<statement>

}

<name>:任何合法的标识符。

<modifier>:可以是public,指明可以被任何其它代码访问,private:指明仅能被同一个类中的其它代码访问。

< return_type>:指明方法返回值的类型。假如方法不返回值,应被声明为void

<parameter>:向方法传递参数。传递多个参数时,参数之间用逗号分开。每个参数由参数类型和标识符组成。

注意:方法必须有返回类型,返回类型为void和没有返回类型是不一样的。除了返回类型void外,有其它返回类型的方法块里必须有return语句。

我们的类此时变成(Person.java)

public class Person {

private double weight;

// 该类的默认的构造器

public Person() {

}

// 带参数的构造器

public Person(double d_weight) {

weight = d_weight; // 实例化对象时,给weight属性赋初始值

}

public void eat(double temp) { // 吃饭的方法

weight = weight + temp; // 吃多少,体重就增加多少

}

public double getWeight() {// 得到人的体重属性

return weight; //返回weight属性

}

}

private封装

在类里面声明属性的时候,一般把属性的访问权限定义成private,封装的要求。这样只能在类里面访问该属性,在类的外面是没有访问的权限的,也就是说对于该类的实例(对象),是不能够直接访问该对象的属性的。这样就会保护对象状态不会非法改变。

比如,人的体重是不能直接修改的,通过吃饭可以增加人的体重,如果该人很瘦,是不能直接把20斤牛肉放到该人身上,就算增加该人的体重的。同样的道理,如果该人很胖,也不能够从该人身上割下20斤肉,而让体重下降20斤。

所以我们在以上的类中声明weight属性为private

public 公共访问

在类里面声明方法的时候,一般把该方法定义成public访问权限。在程序运行的时候,就是通过对象和对象之间的交互来实现的。为了保证对象都能够执行功能(方法),应该把方法的访问权限定义成public

我们对方法getWeight()的处理就是这样。

下面是测试PersonPersonApp.java

public class PersonApp {

public static void main(String[] args) {

// p1是声明的变量,类型是Person类型的,并且引用了Person类的一个对象,且使用默认的构造器构造对象

Person p1 = new Person();

// p2 p1,使用带参数的构造器

Person p2 = new Person(120);

// p1所引用的对象(简称p1对象),吃了2.5

p1.eat(2.5);

// p2 对象 吃了4.3

p2.eat(4.3);

// 打印出p1的体重

System.out.println("p1的体重为:" + p1.getWeight());

// 打印出p2的体重

System.out.println("p2的体重为:" + p2.getWeight());

}

}

编译和运行的过程如下图:

2

我们知道如果文件名出现重复,那么我们要放在不同的目录中,class文件作为类的字节码载体,如果存在类名重复,那么class文件就应该放到不同的目录下,就类似文件夹的方式来管理文件。在Java里面是通过包的结构来管理类的。下面我们就上面例子修改下,再加个类,定义不同的包,放在不同目录下进行访问。

源文件的布局

Java技术源文件只有三部分,采用下面的布局:

[<package_declaration>]

<import_declaration>

<class_declaration>

说明:

<package_declaration> 声明包的语句,包通常使用小写字母,用.作为分割符,这是一种逻辑结构划分的方法。

<import_declaration> 导入包语句

<class_declaration> 类的声明语句

源文件命名

源文件的名字必须与该文件中声明的公有类的名字相同。一个源文件中可以包含多个类,但是最多只能包含一个公有类,显然,这个文件的名字应该是这个public类的名字后缀是“java”。如果源文件中不含公有类,源文件的名字不受限制。

包的声明

多数软件系统是庞大的。为了方便管理,通常要将功能相似的类组织成包,通过包来管理类文件。在包中可以存放类,也可以存放子包,从而形成具有层次结构的包。包可以根据需要任意组织,通常,要按照类的用途、含义来组织包。如下UML 包图:

Java技术提供了包的机制,以次来组织相关的类。声明包的句法如下:

package <top_pkg_name> [.<sub_pkg_name>];

你可以使用package命令指明源文件中的类属于某个特定的包。例如:

package shenzhen.luohu;

public class Person{

//…

}

package声明必须放在源文件的最前面,或者说可执行代码的第一行,或者除了注释之外的第一行。一个源文件最多只能有一条package声明。一条package声明对源文件中的所有类起作用。如果你的源文件中没有package声明,你的类将在缺省包中,这个缺省包的位置就是当前目录。

包的导入

当你想要使用包中的类的时候,可以用import命令告诉编译器类在哪里。import命令的语法:

import <pkg_name>[.<sub_pkg_name>].<class_name | *>;

例如:

import shenzhen.nanshan.*;

import shenzhen.futian.*;

import java.util.List;

import java.io.*;

当你使用import指令时,你并没有将那个包或那个包中的类拷贝到当前文件或当前包中。你仅仅是将你在import指令中选择的类加入到你的当前名字空间。无论你是否导入当前包,当前包都是你的名字空间的一部分。

import命令指明你要访问的类。例如,你需要访问Writer类,你需要下面的命令:

import java.io.Writer;

如果你需要访问一个包中的所有类,你需要下面的命令:

import java.io.*;

但是不会导入java.io下子包的类。

默认情况下,系统将自动导入java.lang包。

import java.lang.*; //源文件里不管有没有写上该句,该句的功能永远存在。

import java.io.Writer;import java.io.*;的区别如下:

如果写类名,那么虚拟机将直接从所在包里找到该加载执行,如果写*号,编译器会CLASSPATH指定的路径,一个一个路径去找,直到找到该类为止。

javacjava命令都有-classpath 参数,他们就是通知编译器或虚拟机在哪些路径中查找可能用到的类。

包与目录的布局

由于编译后的字节码文件在文件系统中存放,包结构就以目录结构的方式体现,包的名字就是目录的名字。例如,shenzhen.luohu包中的PersonApp.class文件应该在 path\shenzhen\luohu目录中。

*运行的时候进入到path目录下:

path>java shenzhen.luohu.PersonApp 或者

path>java shenzhen/luohu/PersonApp

我们没有使用-CLASSPATH参数,系统是如何工作的呢?

首先,系统级别的CLASSPATH环境变量应该是个“.”,表示当前路径,在运行javacjava的时候如果没有-classpath参数就会使用环境变量中的CLASSPATH环境变量,所以系统将从当前路径开始查找类,也就是在“path”路径下,那么按照shenzhen/luohu/路径查下去,确实能找到PersonApp类,所以运行正常,在这里我们把path路径称为顶层目录。

在这种情况下不能进入到shenzhen目录下运行:path\shenzhen>java luohu.PersonApp或者path\shenzhen>java luohu\PersonApp,也不能进入到上一级目录运行。假如你把shenzhen 放在daima文件夹里,你也不能进入到daima 那个文件所在目录下运行:

path>java daima\shenzhen\luohu\PersonApp 或者

path>java daima.shenzhen.luohu.PersonApp

如果想在任何目录下运行正确,必须有三个限制:

? CLASSPATH环境变量或-CLASSPATH参数已指向顶层目录

? class文件按包路径完整结构存放。

? 类的名字必须是全限定名,就是必须包含包路径的类名。

上面是运行时的目录结构,我们可以通过拷贝的方式将类文件防止为以上形式并运行成功。我们也可以在编译的时候用下面两种方式把包的结构生成出来。

通常我们需要把源文件和类文件完全分离,例如我们我们把源文件按包路径完整的存放到src目录中,我们将来编译的类文件将按照包路径完整的存放到build目录中,如下图:

为了达到以上目的,我们手工开始工作,虽然将来有集成开发环境(IDE)帮助我们,但是这对我们明白包的含义很有帮助。

1、手动建立文件夹。把包的结构创建出来

我们分别使用三个包,在一个我们选定的工作目录下按照上图结构创建好目录,其中build目录下的结构无需创建(但是build自身要创建),src目录中存放源文件,他们分别按照自己的package声明存放到不同目录。

2、自动把包的目录结构生成出来。

进入工作目录(srcbuild的上级目录),执行以下命令:

就自动把类按包的结构生成到build目录中了。

其中-d指定了生成带有包结构的类的顶层目录,-sourcepath 指定了源文件查找路径,显然,由于PersonApp要使用到其他包里的其他类,而这些类还是以源文件形式存在的时候,编译器必须能查找到他们并同时将他们编译成功才可以编译PersonApp自身,编译器对源文件的查找方式和虚拟机对类的查找方式类似。

<PersonApp.java>

//声明包

package shenzhen.luohu;

//导入包

import shenzhen.nanshan.*;

import shenzhen.futian.*;

//公共类PersonApp

public class PersonApp {

public static void main(String[] args) {

// p1是声明的变量,类型是Person类型,并且引用了Person类的一个对象

Person p1 = new Person();

// p2 p1

Person p2 = new Person(120);

// c1是声明的变量,类型是Cat类型的,并且引用了Cat类的一个对象

Cat c1 = new Cat();

c1.jiao();

// p1所引用的对象(简称p1对象),吃了2.5

p1.eat(2.5);

// p2 对象 吃了4.3

p2.eat(4.3);

// 打印出p1的体重

System.out.println("p1的体重为:" + p1.getWeight());

// 打印出p2的体重

System.out.println("p2的体重为:" + p2.getWeight());

}

}

<Person.java>

//声明包

package shenzhen.nanshan;

//声明公共类Person

public class Person {

// 声明该类的一个属性,访问权限为private ,对该属性进行封装,实例化时,给该属性的初始化默认值0

private double weight;

// 该类的默认的构造器

public Person() {

}

// 带参数的构造器

public Person(double init_weight) {

// 实例化对象时,给weight属性赋初始值

weight = init_weight;

}

// 吃饭的方法

public void eat(double temp) {

// 吃多少,体重就增加多少

weight = weight + temp;

}

// 得到人的体重属性

public double getWeight() {

// 返回weight属性

return weight;

}

}

<Cat.java>

//声明包

package shenzhen.futian;

//声明公共类

public class Cat {

public void jiao() {

System.out.println("cat jiao......");

}

}

运行时情况如下:

当然我们也可以在build目录下,利用CLASSPATH环境变量已经带有的.(当前路径)直接找到要运行的类(shenzhen.luohu.PersonApp),我们也可以利用绝对路径形式制定CLASSPATH,例如:

而且绝对路径相对路径的概念在编译、运行的时刻同样有效。

对于CLASSPATH我们可以通过环境变量方式设置,例如希望从系统级别设置类路径,也可以通过-CLASSPATH参数形式设置,例如希望临时更改类路径。

3

人看到汽车开过来了,就会沿着路边走。如果这个人站在路中间不动(他不怕死),那么汽车就会停下来

这里涉及到两个对象的相互作用,我们先声明两个类,来描述上述现象,然后再用一个测试类来实现。

CarPersonApp.java

class Car {

private boolean moving;

public boolean getMoving() {

return moving;

}

public void move(boolean side) {

if (side) {

System.out.println("车继续行驶");

moving = true;

} else {

System.out.println("车停下来");

moving = false;

}

}

};

class Person {

boolean side; // 表示人是否在路边

public boolean walk(boolean car) {

if (car) // 如果有车的话,人往路边走

{

System.out.println("人往路边走");

side = true;

} else {

System.out.println("人直着走");

side = false;

}

return side;

}

};

public class CarPersonApp {

public static void main(String[] args) {

Person p = new Person();

Car c = new Car();

c.move(true); // 车在行驶

p.walk(c.getMoving());// 测试人是否能行走,也就是说车的行为,影响了人的行为

}

}

编译和运行:

API文档的使用

Java API是扩展的Java类库。它为程序员提供了几千个类,包括基本的数学函数、数组和字符串、窗口,图形用户界面,输入/输出,联网等任何你需要的内容。

类库被组织成许多包,每个包都包含多个类。下面列举了一些重要的包:

? java.lang:包含一些形成语言核心的类,如StringMathIntegerThread

? java.awt:包含了构成抽象窗口工具包(AWT)的类,这个包被用来构建和管理应用程序的图形用户界面。

? java.applet:包含了可执行applet特殊行为的类。

? java.net:包含执行与网络相关的操作的类和处理接口及统一资源定位器(URLs)的类。

? java.io:包含处理I/O文件的类。

? java.util:包含为任务设置的实用程序类,如随机数发生、定义系统特性和使用与日期日历相关的函数。

Java API文档详细说明了Java API的使用方法。Java API文档是一组等级制布局的HTML文件,因而主页列出所有的包为超链接。如果选中了一个特殊包的热链接,作为那个包成员的类将被列出。从一个包页选中一个类的热链接将提交一页有关那个类的信息。

下载Java2 SE Version 1.5的文档并解压缩,打开/api/Index.html 文件。

一个类文档的主要部分包括:

? 类层次

? 类和类的一般目的描述

? 成员变量列表

? 构造函数列表

? 方法列表

? 变量详细列表及目的和用途的描述

? 构造函数详细列表及描述

? 方法详细列表及描述

内容总结

? 一个类由属性、方法、构造函数构成。

? private实现信息的封装,只有这个类自身内部可以访问这个属性或方法。

? CLASSPATH环境变量是Java虚拟机查找类的路径,在编译和运行时会使用到它。

? Package:将功能相似的类组织成包,通过包来管理类文件。在包中可以存放类,也可以存放子包,从而形成具有层次结构的包。

? import告诉编译器:导入Java类库中的类或者程序员自己开发的类文件。

? API文档是我们使用已有类完成任务的参考手册。

独立实践

? 练习API文档的使用,查找Date类,根据API文档说明写出一个程序演示输出当前日期。

? 写一个猫吃老鼠的实例。

? 对上面的类增加包,要求猫、老鼠、演示类在不同的包中,练习使用 CLASSPATH环境变量。

? 编写一个类:Person,包含一个属性:name及方法:getName(),画出它的类图。

? 给Person类加上注释,练习javadoc命令,生成文档。

第四章: Java语法基础

学习目标

? 标识符定义

? Java数据类型

? 参数传递:基本型参数,引用类型参数

? 对象实例化和成员的访问

? 变量作用域及程序中逻辑控制

基本语法元素

注 释

注释是程序员用来标记、说明程序的。编译器会忽略注释中的内容,注释中的内容不会对程序的运行产生任何影响。Java语言允许三种风格的注释:

// 单行注释

多用于对属性,变量以及算法重要转折时的提示

/* 多行

注释 */

多用于对类、方法及算法的详细说明,一般在对类的注释中要有以下内容:

1. 类的简要说明

2. 创建者及修改者

3. 创建日期或者最后修改日期

/** JAVA文档

*注释

*/

产生Java文档,使用javadoc命令.

分号

Java编程语言中,语句是一行由分号(;)终止的代码。

例如:

totals = a + b + c + d + e + f;

语句块(block)

语句块(block)也叫做复合语句。一个语句块(block)是以上括号和下括号{}为边界的语句集合;语句块也被用来组合属于某个类的语句。例如:

public class Date {

private int day = 3;

private int month;

private int year;

public void pri() {

}

public static void main(String[] a) {

}

}

语句块可被嵌套。我们以前见到的main方法就是一个语句块,它是一个独立单元。

下面的语句是合法的:

// a block statement

{

x = y + 1;

y = x + 1;

}

// an example of a block statement nested within another block

// statement

while ( i < large ) {

a = a + i;

if ( a == max ) {

b = b + a; // nested block is here

a = 0;

}

i++;

}

还有一种静态语句块,这个我们将在学习static关键字时介绍.

空白

空白:是空格、tabs和新行(换行符)的统称。

在源代码元素之间允许插入任意数量的空白。空白可以改善源代码的视觉效果,增强源代码的可读性。例如:

{

int x;

x = 23 * 54;

}

{

int x;

x = 23 + 54;

}

标识符定义

标识符是语言元素的名称,是我们在程序中表示变量、类或方法等等的符号。

? 标识符由字母、下划线(_)、美元符号($)或数字组成,但不能以数字开头。另外可以使用中文做标识符,但实际开发中不推荐这样做。

? 标识符是大小写敏感。

? 标识符未规定最大长度,但实际工作中不会对标识符命名过长,10个字符以内合适,标识符的命名尽可能的有意义。

下列标识符是有效的:

idendsafdstifier

ugfdsgName

Udsaf_dsfe

_sys_varldaf

$changdsafe

Java技术源程序采用双字节的"统一字符编码" (Unicode,使用16bit编码)标准,而不是单字节的 ASCII(使用8bit编码)文本。因而,一个字母有着更广泛的定义,而不仅仅是azAZ

标识符不能是关键字,但是它可包含一个关键字作为它的名字的一部分。例如,thisone是一个有效标识符,但this却不是,因为this是一个Java关键字。

Java关键字

下面列出了在Java编程语言中使用的关键字。

abstract do implements private throw

boolean double import protected throws

break else instanceof public transient

byte extends int return true

case false interface short try

catch final long static void

char finally native super volatile

class float new switch while

continue for null synchronized default

if package this

关键字对Java技术编译器有特殊的含义,它们可标识数据类型名或程序构造(construct)名。

以下是有关关键字的重要注意事项:

? truefalsenull为小写,而不是象在C++语言中那样为大写。

? 无sizeof运算符;所有类型的长度和表示是固定的,不依赖执行。

? gotoconst不是Java编程语言中使用的关键字。

基本Java数据类型

Java编程语言定义了八种原始数据类型:

类型 位数(bit 默认值

逻辑型 boolean 1bit false

文本型 char 16bit(2byte) '\u0000'

整数型 byte 8bit(1byte) 0

short, 16bit(2byte) 0

int, 32bit(4byte) 0

long 64bit(8byte) 0

浮点型 double, 64bit(8byte) 0.0

float 32bit(4byte) 0.0

注意:整数类型默认的是int,浮点型默认的是double

逻辑型--boolean

逻辑值有两种状态,即人们经常使用的 “true”“false”。这样的值是用boolean类型来表示的。boolean有两个文字值,即truefalse

以下是一个有关boolean类型变量的声明和初始化:

boolean truth = true; //声明变量值为真

注意:在整数类型和boolean类型之间无转换计算。有些语言(特别值得强调的是CC++)允许将数字值转换成逻辑值, 这在Java编程语言中是不允许的;boolean类型只允许使用boolean值。

字符型--char

使用char类型可表示单个字符。一个char代表一个16-bit无符号的(不分正负的)Unicode字符。一个char文字必须包含在单引号内(’’)

‘a’

‘\t’ 一个制表符

‘\u????’ 一个特殊的Unicode字符。????应严格按照四个16进制数字进行替换。例如: ’\u03A6’表示希腊字母“Φ”

char类型变量的声明和初始化如下所示:

char ch = ’A’; // 声明并初始化一个char型变量

char ch1,ch2 ; // 声明两个char型变量

charint兼容的类型,比如可以如下声明:

int a = ‘a’; // a = 97

char c = 65; // c = ‘A’

字符串类--String

String不是原始类型,而是一个类(class),它被用来表示字符序列。字符本身符合Unicode标准。与CC++不同,String不能用 \0作为结束。

String的文字应用双引号封闭,如下所示:

“The quick brown fox jumped over the lazy dog.”

String类型变量的声明和初始化如下所示:

// 声明两个String型变量并初始化他们

String greeting = "Good Morning !! \n" ;

String err_msg = "Record Not Found !" ;

String str1,str2 ; // 声明两个字符串变量

整数型--byte, short, int, long

Java编程语言中有四种整数类型,它们分别使用关键字byte, short, intlong中的任意一个进行声明。整数类型的文字可使用十进制、八进制和16进制表示,如下所示:

? 十进制值是2

? 首位的0表示这是一个八进制的数值

? 0xBAAC 首位的0x表示这是一个16进制的数值

注意──所有Java编程语言中的整数类型都是带符号的数字。

整数类型数字被默认为int类型。

整数类型数字后面紧跟着一个字母“L”,可以强制它为long型。

例如:

? 2L 十进制值是2,是一个long

? 077L 首位的0表示这是一个八进制的数值

? 0xBAACL 前缀0x表示这是一个16进制的数值

四种整数类型的长度和范围前面已经列出,这些长度和范围是按Java编程语言规范定义的,是不依赖于平台。

浮点数--floatdouble

如果一个数字包括小数点或指数部分,则该数字默认为double型浮点数。

例如:

3.14

3.02E23

如果一个数字文字后带有字母Ff,则该数字文字为float型浮点数。

例如:

2.718F

如果一个数字文字后带有字母Dd,则该数字文字为double型浮点数。

例如:

123.4E-306D

浮点变量可用关键字floatdouble来声明。

Java技术规范的浮点数的格式是由电力电子工程师学会(IEEE754定义的,是独立于平台的。

变量声明和赋值

变量用于存储信息。一个变量代表一个特殊类型的存储位置,它指向内存的某个单元,而且指明这块内存有多大。变量的值可以是基本类型,也可以是对象类型。

下列程序显示了多种类型的变量,如何进行声明及赋值的。

public class TestAssign {

public static void main(String args[]) {

int a, b; // declare int variables

float f = 5.89f; // declare and assign float

double d = 2.78d; // declare and assign double

boolean b = true;// declare and assign boolean

char c; // declare character variable

String str; // declare String

String str1 = "good"; // declare and assign String variable

c = 'A'; // assign value to char variable

str = "hello ,hello"; // assign value to String variable

a = 8;

b = 800; // assign values to int variables

}

}

引用(Reference)类型

从大的范围来讲,Java中的数据类型就分为两种:基本数据类型和引用类型,前面已经对基本数据类型(也称为主数据类型)进行了讲解,下面我们再来理解引用类型。

创建一个新类型

为克服Java中数据类型的不完整,Java编程语言使用类来创建新类型。例如可以用下面的类表示人:

class Person {

private double height = 1.75;

private double weight = 65;

private String name;

public Person(String aName) {

name = aName;

}

public Person() {

}

}

关键字class是用来声明类的。

Person是指定这个类的名称。

height变量被声明,是类Person的一个属性。 本类Person中包含有3个属性。

Person zhangsan, lisi; 声明Person类有两个引用,引用名称为:zhangsanlisi

zhangsan = new Person()//Persion构造出实际的内存空间,zhangsan这个引用,指向这个内存空间。

lisi = new Person()//同上。因此这两个变量zhangsanlisi都是引用类型的,并不实际存储这些数据

创建并初始化一个对象

当任何基本数据类型(boolean, byte, short, char, int, long, floatdouble类型) 的变量被声明时,内存空间同时被分配,此分配属栈;

使用非基本数据类型(class)变量的声明,不为对象同时分配内存空间。事实上,使用class类型声明的变量不是数据本身,而是数据的引用(reference)。引用可以理解为C语言的指针(Pointer),但是不能象C语言那样计算指针。

在使用引用变量之前,必须为它分配实际存储空间。这个工作是通过使用关键字new来实现的。如下所示:

Person pangzi;

pangzi= new Person();

第一个语句仅为引用分配了空间,而第二个语句则通过调用对象的构造函数Person()为对象生成了一个实例。这两个操作被完成后,Person对象的内容则可通过pangzi进行访问。

还可以用一条语句创建并初始化一个对象:

Person pangzi = new Person(“danan”);

使用非基本数据类型(String)变量的声明,分两种情况:

使用String str = “班集,指向的是内存中的特殊区域,叫字符串池;

String str = new String(),则和class变量声明的规则一致。

存储器分配和布局

在一个方法体中,做如下声明:

Person liuxiang

liuxiang= new Person();

语句Person liuxiang; 仅为一个引用分配存储器,存储空间里的值没有确定。

liuxiang

在语句liuxiang= new Person() 中关键字new意味着为对象分配内存空间,并初始化。

注意:由于使用了缺省构造函数,而缺省构造函数中并未对name属性进行赋值操作,所以name属性是没有初始化的。

引用类型的赋值

Java编程语言中,一个被声明为类的变量,叫做引用类型变量,这是因为它正在引用一个非基本数据类型,这对赋值具有重要的意义。请看下列代码片段:

int x = 7;

int y = x;

String s = “Hello”;

String t = s;

四个变量被创建:两个基本数据类型 int 和两个引用类型Stringx的值是7,而这个值被复制到yx y是两个独立的变量且其中任何一个的进一步的变化都不对另外一个构成影响。

至于变量 s t,只有一个String 对象存在, 它包含了文本”Hello” s t均引用这个单一的对象。

将变量t 重新定义, t= "World";则新的对象World被创建,而 t 引用这个对象。

Java基本数据传递与引用传递

Java中的参数传递,都称为是传值。但传的这个值,到底是什么,这个就是我们需要研究的。传递的是一个基本数据,还是一个引用,这就要仔