CoreJava核心编程 第一章:Java语言简介.

Slides:



Advertisements
Similar presentations
软件编程基础 一、程序的编辑 Java 源程序是以 Java 为后缀的简单的文本文件,可以用各种 Java 集成开发环境中的源代码编辑器来编写,也可以用其他文 本编辑工具,如 Windows 中的记事本或 DOS 中的 EDIT 软件等。 利用文字编辑器编写下列程序 public class Hello.
Advertisements

第 2 章 Java 运行环境搭建 2.1 Java 的运行系统 2.1 Java 的运行系统 2.2 JDK 的安装与配置2.2 JDK 的安装与配置 2.3 Java 开发工具包 2.4 Java 源文件编辑环境的选择 2.5 Application 和 Applet 程序的编写与运行.
Java 程序分类 Java Application :是完整程序,需要独立的解 释器解释运行;以 “.java” 为后缀的文件,以 main() 方法作为程序入口,由 java 编译器编译生 成字节码,由 Java 解释器加载执行字节码。 Java Applet 没有 main() 方法作为程序入口,是嵌在.
第一章 Java 程序设计技术 概述  什么是 Java 语言  一个简单的 Java 程序  程序的编译和运行  常见错误  使用 Java 核心 API 文档.
程序设计语言基础 软件工程系 秦晓燕. 课程目标 了解面向对象程序设计的思想,以及软件 开发流程。 学习 Java 语言的基本概念和编程方法,基 本掌握 Java 类库的使用。 能够利用所学的方法开发简单的小型应用 程序.
Java 程序设计 案例教程 北京大学出版社 第 01 章. Java 程序设计案例教程 第 01 章 Java 语言与面向对象程序设计 Java 语言的历史 Java 语言的特点 Java 程序的分类 Java 环境配置 Eclipse 的安装 Java 程序的调试 教学目标.
Java 程序设计(第二版) 普通高等教育 “ 十一五 ” 国家级规划教材 辛运帷等 编著 徐小平 主讲.
单元二:面向对象程序设计 任务二:借书卡程序设计.
3.2 Java的类 Java 类库的概念 语言规则——程序的书写规范 Java语言 类库——已有的有特定功能的Java程序模块
JAVA 编 程 技 术 主编 贾振华 2010年1月.
第1章 Java语言概述.
《 Java开发环境配置》 主讲人:耿力.
Java 2实用教程(第3版)教学课件 主讲教师:张国平
Java程序设计教程 第一讲 Java概述.
Java的程式架構與基本觀念 Java語言的歷史 Java程式的開發環境 Java程式的架構 輸出與輸入物件之使用 工具使用方法介紹
四資二甲 第三週作業 物件導向程式設計.
JAVA程序设计.
面向对象的程序设计(一).
《Java程序设计之网络编程》 教学课件 重庆大学计算机学院
面向对象程序设计(Java) 徐志红
北京科技大学天津学院 信息工程系 面 向 对 象 程 序 设 计 第1讲 Java初探 主讲:于静.
计算机学院计算机科学与技术系 中德联合软件技术研究所 李波
程設一.
第二章 JAVA语言基础.
第1章 java简介及环境搭建 第1章 Java简介及开发环境搭建.
Ch07 介面與多重繼承 物件導向程式設計(II).
JAVA程序设计 (03) JAVA Programming
第5章 进一步讨论对象和类.
1 Department of Computing.
第5章 Java中类、对象、接口 及包的概念 5.1 类的基本概念 5.2 类的继承概念 5.3 抽象类和接口 5.4 包.
2.1 基本資料型別 2.2 變數 2.3 運算式與運算子 2.4 輸出與輸入資料 2.5 資料型別轉換 2.6 實例
第5章 面向对象程序设计 本章要点 5.1 面向对象程序设计概述 5.2 Java语言的面向对象程序设计 5.3 方法的使用和对象数组
第二章 C# 基础知识.
Java基础 JavaSE异常.
第六章 类的扩展与继承.
第3章 語法入門 第一個Java程式 文字模式下與程式互動 資料、運算 流程控制.
本單元介紹何謂變數,及說明變數的宣告方式。
西南科技大学网络教育系列课程 高级语程序设计(Java) 第五章 继承、接口与范型.
程式設計實作.
CH09 套件 物件導向程式設計(II).
第2章回顾 标识符:不用记,动手 关键字:if, else, switch, for, while, do, break, continue, void, …… 局部变量和成员变量 ①变量作用域 ②内存布局 基本数据类型 ①4类8种 ②互相转换 流程控制语句 ①分支 if……else, switch.
Java软件设计基础 5. 继承与多态.
Java程序设计 第9章 继承和多态.
2018/12/7 Java语言程序设计 教师:段鹏飞.
Java基础入门 第1章 Java开发入门 · Java语言的特点 · Java开发环境的搭建 · 环境变量的配置 · Java的运行机制.
類別的繼承 Vehicle Car.
3.1 数据类型 3.2 标识符与关键字 3.3 常量 3.4 变量 3.5 运算符与表达式 3.6 一个编程实例
2019/1/16 Java语言程序设计-类与对象 教师:段鹏飞.
2019/1/17 Java语言程序设计-程序流程 教师:段鹏飞.
Java程序设计 第2章 基本数据类型及操作.
C/C++/Java 哪些值不是头等程序对象
* 單元:電腦與問題解決 主題:Java物件導向程式設計-類別與物件 台南縣國立善化高中 蕭嘉民 老師
第三章 C# 基础知识.
第1章 Java语言概述 学习目标 本章要点 上机练习 习 题.
JAVA 编 程 技 术 主编 贾振华 2010年1月.
《JAVA程序设计》 语音答疑 辅导老师:高旻.
第二章Java基本程序设计.
第三课 标识符、关键字、数据类型.
第二章 Java基本语法 讲师:复凡.
Java程式初體驗大綱 大綱 在學程式之前及本書常用名詞解釋 Hello Java!程式 在Dos下編譯、執行程式
第二章 Java语法基础.
第二章 Java基本语法 讲师:复凡.
方法進階及物件導向基礎 Lecturer: 楊昌樺.
第6單元 6-1 類別的繼承 (Class Inheritance) 6-2 抽象類別 (Abstract Class)
PPT注意事项: 当前PPT课件文件必须和提供的源代码文件夹“代码”在同一目录中即不要移动文件夹“代码”的默认位置。
JAVA 程式設計與資料結構 第三章 物件的設計.
第2章 Java语言基础.
第二章 Java基础语法 北京传智播客教育
第6章 继承和多态 伍孝金
Summary
Presentation transcript:

CoreJava核心编程 第一章:Java语言简介

课程整体目标 掌握Java语言基础知识 理解面向对象的编程思想 运用Java编写命令行程序 运用JDBC编写数据库访问程序 运用Swing组件编写图形用户界面程序 运用Swing组件和JDBC实现C/S结构的应用程序

本章目标 了解Java语言 了解Java程序的类型 理解Java虚拟机(JVM) 掌握Java程序运行环境的配置

Java简介 掌握Java程序运行环境的配置 编写第一个基于Java的程序

Java释义 “Java” 一词的本意是地名——“爪哇”; 爪哇岛位于南太平洋,是印度尼西亚的一部分。 爪哇岛

关于爪哇 全世界三大咖啡产地: 巴西 印尼爪哇岛 中国海南岛 由此可见,Java的原意是指一个咖啡的产地,也可以说是一种咖啡的品牌。

Java语言简介 Java是一种程序设计语言,由Sun Microsystem公司于1995年推出; 早在1991年,Sun公司的James Gosling等人开始开发名为Oak的程序设计语言,希望用来控制嵌入在有线电视机顶盒和PDA等设备中的微处理器; 1994年,Oak语言正式更名为Java; Java语言凭借其独有的安全性、可移植性和平台无关性,迅速走红。

Java与Internet Internet使Java成为网络上最流行的编程语言; 同时,Java对Internet的影响也意义深远; 使用Java语言编写的Applet程序可以对用户的输入和操作作出响应。

Java程序的类型-Applet Applet是用Java编写,在Internet上运行的程序,可以在任何客户端系统上下载,在浏览器中运行

Java程序的类型-Application

Java的平台无关性 Java是一种既面向对象又可以跨平台的语言,即:编写一次,随处运行; 源程序代码 Windows Linux Solaris JVM Java虚拟机 Java字节码 (可跨平台) 编译 运行

Java虚拟机 Java虚拟机(Java Virtual Machine)是可运行Java字节码的虚拟计算机系统; 使用Java语言编写的程序,实际上是运行在JVM之上,而不是运行在操作系统上; 它有一个解释器组件,可以实现Java字节码和计算机操作系统之间的通信。 用户USER 字节码程序 JVM (Java 虚拟机) 操作系统 硬 件

编译时 运行时 Java虚拟机的运行过程 .java .class 类加载器 网 络 字节码校验器 硬件 源代码文件 JIT代码 生成器 网 络 JIT代码 生成器 .java 源代码文件 .class 字节码文件 编译时 运行时 硬件 类加载器 字节码校验器 解释器

Java开发工具包 开发和运行Java程序,必须依赖和使用由Sun公司提供的Java开发工具包(Java Development Kit) 操作系统 Java虚拟机 Java 基础类库 客户端 编译器 浏览器 插件 开发工具 集成开发环境

J2SE(Standard Edition):标准版,适用于普通应用程序的开发; Java Platform 2 JDK(Java开发工具包)从1.3版本以后,Sun公司将其正式更名为Java Platform 2; 为适应不同的用途,又将其细分为三个版本: J2SE(Standard Edition):标准版,适用于普通应用程序的开发; J2EE(Enterprise Edition):企业版,适用于大型企业级应用程序的开发; J2ME(Micro Edition):微型版,适用于移动设备或嵌入式设备的程序开发。

下载安装JDK 打开浏览器,在地址栏键入:http://java.sun.com/javase/downloads/index.jsp,登录到SUN官方网站,免费下载JDK软件和文档 下载完毕,即可安装JDK; bin目录:存放可执行文件; lib目录:存放Java的类库文件; demo目录:存放演示程序; jre目录:存放Java运行环境文件。

配置环境变量 安装JDK后,还要配置环境变量才能开发和调试Java程序,右击[我的电脑][属性][高级][环境变量] 编辑Path变量 新建classpath变量

开发Java程序的步骤 创建Java源程序 Java源程序可以使用任何文本编辑器创建与编辑,一般用.java作为扩展名,其实就是一个使用Java语言编写的文本文件; 编译源程序 Java编译器读取Java源程序并翻译成Java虚拟机能够明白的指令集合,并以字节码的形式保存在文件中,通常,字节码文件以.class作为扩展名; 运行class(字节码)文件 Java解释器读取字节码文件,取出指令并翻译成计算机能够执行的机器代码,完成运行过程。

编写第一个Java程序 打开记事本,新建一个文本文件,将文件名改为Hello.java,在文件中键入如下内容并保存: class Hello { public static void main(String[] args) System.out.println("Hello world!"); }

Java源程序 扩展名为.java 的源文件 使用记事本 进行编辑

使用javac编译器编译源文件 接下来需要将源程序进行编译; 进入命令提示行,切换到源文件所在的目录,执行javac命令,使用javac编译器编译源文件; javac命令的格式是:javac 完整的源文件名 切换到源文件所在的目录 切换到源文件所在的目录 切换到源文件所在的目录

class(字节码)文件 顺利通过编译后将生成一个扩展名为.class的字节码文件(类描述文件)。 通过编译后 生成的扩展名 扩展名为.java 的源文件

使用java解释器运行字节码文件 进入命令提示行,在字节码文件所在的目录下,执行java命令,使用java解释器运行字节码文件 这里只需要类名称,而不是带扩展名的文件名 执行java命令运行字节码文件 程序运行效果

分析程序3-1 关键字class用来定义一个类,Hello是类的名称; 在Java程序中,所有的语句都必须放在某个类中; 整个类及其所有成员都包含在一对花括号中(即{和}之间),它们标志着类定义块的开始和结束。 定义类的一般语法: class 类名 { …… }

分析程序3-2 程序必须从main函数开始执行; 关键字public是访问修饰符,用来控制类成员的可见范围及作用域; 关键字static允许在不创建类的实例的情况下,调用main函数; 关键字void用来说明main函数是没有返回值的; args是字符串数组,用来从命令行接收参数; main函数的一般形式如下: public static void main(String[] args){ …… }

分析程序3-3 String[]是字符串类型的数组; 在Java中,类名称一般首字母大写; 使用System.out.println()将信息输出到控制台上,即打印出来。

Java API文档 Java API文档描述了Java的许多内置功能,以及提供各种类的帮助说明,它是程序员经常查阅的资料 可登录Sun公司的官方网站免费下载

多行注释:以/*开始,以*/结束,可以有多行 文档注释:以/**开始,以*/结束,可以有多行 Java文件中的注释 与其它编程语言一样,也可以在Java文件添加注释,Java文件中的注释有三种: 单行注释:以//开始,在行尾结束 多行注释:以/*开始,以*/结束,可以有多行 文档注释:以/**开始,以*/结束,可以有多行 可以使用javadoc命令,将文档注释从源代码中提取出来,生成HTML文件,形成类似于Java API文档的帮助说明文件。

使用javadoc命令生成API文档 javadoc命令的格式是:javadoc 完整的源文件名 执行javadoc命令提取 文档注释的内容

生成的文档

Java语言的特点2-1 去掉了C和C++中许多复杂功能,如指针、运算符重载等,没有goto语句,没有struct和union等 简单 去掉了C和C++中许多复杂功能,如指针、运算符重载等,没有goto语句,没有struct和union等 面向对象 Java是完全面向对象的编程语言,比C++更彻底,纯度更高 健壮性 没有指针,避免对指针的误操作造成程序崩溃 程序员分配的内存空间,无需释放,由Java虚拟机的垃圾回收机制来统一完成此项工作,避免了内存泄漏

Java语言的特点2-2 由于Java取消了指针运算,有效地提高了程序的安全性 分布性 Java程序可以跨平台,跨操作系统,完全支持网络应用程序的设计 多线程 Java程序使用一个称为“多线程”的进程同时处理多项任务

使用Eclipse来开发

总结 javac:编译 java:运行 javadoc:提取文档 Java是面向对象的、跨平台的程序设计语言; 要下载安装JDK,才可以开发和运行Java程序; JDK提供一系列的工具,这些工具位于JDK安装路径的bin目录下,常用的有: javac:编译 java:运行 javadoc:提取文档 可以使用任何文本编辑器编写Java源程序;

作业 熟悉JDK目录,以及JDK环境变量 使用记事本编写Hello World程序 使用记事本编写九九乘法表 使用记事本编写空心菱形

CoreJava核心编程 第二章:Java语言基础

Java语言基础 Java是面向对象并且可以跨平台的编程语言 Java程序是运行在JVM(Java虚拟机)之上的 要运行和开发Java程序,必须下载和安装由Sun公司提供的JDK(Java开发工具包) 配置环境变量:Path和classpath 三个常用的JDK工具:javac、java和javadoc

本章相关词汇(蓝色为关键字) 单 词 说 明 byte 数据类型,字节型 boolean 数据类型,布尔型 true 真,布尔型的字面值 单 词 说 明 byte 数据类型,字节型 boolean 数据类型,布尔型 true 真,布尔型的字面值 false 假,布尔型的字面值 null 空

本章目标 Java中的变量和数据类型 Java中变量的作用域规则 数据类型转换 Java中的输出语句 Java中的运算符和表达式

Java语言基础 Java中的变量和数据类型

变量 变量是内存中的一块存储区域,是存储数据的基本单元; 声明变量的语法: 数据类型 标识符 [= 值]; 如: int num; float money = 123.45f; char ch1, ch2 = ‘A’;

数据类型 数据类型用来确定要存储在内存单元中的数据的类型; 在Java中,数据类型被区分成两个种类: 原始数据类型 引用数据类型

原始数据类型 原始数据类型是最简单的数据形式,与C的基本数据类型很相似: 数据类型 取值范围 说 明 大小 位 boolean 布尔型 1 说 明 boolean 布尔型 1 true/false 用于存储真值/假值 byte 字节型 8 -128~127 数据存储在内存中的最原始形态 char 字符型 16 ‘\u0000’~‘\uFFFF’ 用于存储字符,以Unicode编码方式 short 短整型 -32768~32767 略(参见P20表2.1) int 整 型 32 -231~231-1 long 长整型 64 -263~263-1 float 浮点型 略 double 双精度

引用数据类型 数组 对象 在Java中,除了上述8种原始数据类型的变量以外,其余的全都属于引用数据类型,其中包括: 存储在引用类型变量中的值是该变量表示的值的地址; 可以借用C语言中指针的概念来理解引用数据类型。

回顾C语言中的内存分配 C语言中内存分配的两种形式: 栈内存: 堆内存(即动态内存分配): 特点:和作用域同生命周期,自动申请,自动释放。 申请方式:局部变量,形式参数。 栈内存中的空间一般都有名称,通过变量名访问其存储的数据。 堆内存(即动态内存分配): 特点:手工申请,手工释放,生命周期由程序员决定。 申请方式:由malloc函数或calloc函数申请,realloc函数进行调整,free函数负责释放。 堆内存中的空间一般没有名称,只能通过指针访问。

Java中的内存分配 Java中的原始数据类型与C语言中的基本数据类型一样,其变量都是在栈中分配空间; 而除了8种原始数据类型以外,其它的任何数据都不可以在栈中分配,只能到堆中开辟空间,而在堆中分配的空间又只能通过指针访问; 通过指针访问堆内存的方式,在Java中被称作引用数据类型; 可以认为,Java中的引用就类似于C语言中的指针,只是对指针进行了一定程度上的包装,避免了因直接操作指针而造成的数据意外损坏,从而导致程序错误的情况。

标识符命名规则 变量、函数、数组、对象、类和接口等等都需要命名,这些名称统称为标识符; Java中对于标识符的命名规则作了如下限制: 只能由英文字母、数字、下划线“_”和“$”符号组成; 必须以英文字母、“_”或“$”开头,即不能以数字开头; 除“_”和“$”以外,不能包含其它任何特殊字符; 不能与关键字冲突; 严格区分大小写。

变量的作用域和生命周期 变量 的作用域指变量起作用的范围,说明变量在什么部分可以被访问; 变量的生命周期是指变量在内存中存在的周期,即什么时候分配空间,什么时候销毁。 C Java 变量 声明 程序中所有使用到的变量应该在程序开始部分预先进行声明。 可以在程序的任何部分声明,即:何处使用,何处声明。 作用域 规则 变量的作用域属于声明它的函数范围之内,变量的最小作用域是函数。 变量的作用域属于声明它的代码块,变量的最小作用域是包含它的一对{}之间。

作用域示例 /*有1,2,3,4四个数字,能组成多少个不相同且无重复的三位数?*/ public class ScopeVariable { public static void main(String[] args) int count = 0; for (int i = 1; i <= 4; i++) //在需要使用变量时声明 for (int j = 1; j <= 4; j++) for (int k = 1; k <= 4; k++) if (i != j && i != k && j!= k) int temp = i * 100 + j * 10 + k; System.out.print(temp + "\t"); count++; } } /*思考:在此处可以访问到变量k吗?*/ System.out.println("\n有:" + count + "个符合要求的数");

数据类型转换 程序中经常会遇到要将数据类型进行转换的情况(如:在一个表达式中存在不同类型的操作数时),Java的数据类型转换比C控制得更为严格; 数据类型转换有两种情况: 自动类型转换 强制类型转换

自动类型转换 自动类型转换也称作隐式类型转换; 将一种类型的变量赋值给另一种类型的变量时,只要满足以下条件,就会发生自动类型转换: 如: 两种类型之间相互兼容; 目标类型大于源类型(即类型提升); 如: char ch = 'A'; int num = ch; float f = num; double d = f; //类型转换自动发生,无需显式说明

强制类型转换 强制类型转换也称作显式类型转换; 如果被转换的值的数据类型大于其目标类型,将会丢失部分信息; 如: int x = 65; char ch = x; 这样的语句将报错,因为char类型小于int类型,编译器无法将其自动转换,只能进行强制转换: char ch = (char)x;

类型提升规则 不难看出,在有类型提升的情况下,编译器将自动进行类型转换,否则就要进行强制类型转换; 类型提升应遵循如下规则: 两种类型必须兼容,且目标类型大于源类型,例如: byte、char和short类型都可以提升为int型。 对于表达式而言,其最终结果将会与表达式中最高的数据类型相同。

输出语句 如果要将某些信息打印到屏幕上,就必须使用输出语句; 使用System.out.println()实现换行输出效果; 无论输出什么类型的数据,只需将数据作为参数传递给它们即可,而无需像C语言中那样,使用%s、%d之类的控制字符,如: int a = 10; float f = 3.14f; System.out.println(a); System.out.print(f); System.out.println('X');

使用转义字符控制输出格式 有些时候,我们可能会需要对输出格式进行控制,这就使用到了转义字符; 以下是一些常用的转义字符: 转义字符 说 明 说 明 \n 换行符,将光标移到下一行 \r 回车符,将光标移到当前行的开头 \t 制表符,将光标移到下一制表位 \\ 输出反斜线 \' 输出单引号 \" 输出双引号

运算符和表达式 运算符是通过一定的运算规则操作一个或多个操作数,并生成结果的特定符号; 运算符和操作数的有效组合称为表达式; Java提供了一系列丰富的运算符,包括: 算术运算符 关系运算符 逻辑运算符 条件运算符 赋值运算符

算术运算符 算术运算符主要用于数学计算,一般使用数值作为操作数: 运算符 说 明 一元 - 一元减,即取负 ++ 说 明 一元 - 一元减,即取负 ++ 自增,如:++a等价于a = a + 1 -- 自减,如:--a等价于a = a – 1 二元 + 加法,返回两个操作数的和 减法,返回两个操作数的差 * 乘法,返回两个操作数的积 / 除法,返回两个操作数的商 % 取模,返回两个操作数整除后的余数

关系运算符 关系运算符可以测试两个操作数之间的关系(但不会改变操作数的值),关系表达式的结果为boolean型true/false: 运算符 说 明 == 等于,检查两个操作数是否相等 != 不等于,检查两个操作数是否不相等 > 大于,检查左操作数是否大于右操作数 >= 大于等于,检查左操作数是否大于或等于右操作数 < 小于,检查左操作数是否小于右操作数 <= 小于等于,检查左操作数是否小于或等于右操作数

逻辑运算符 逻辑运算符与boolean型操作数一起使用: 运算符 说 明 Java C 一元 ! 逻辑非(NOT) 逻辑取非(NOT) 二元 说 明 Java C 一元 ! 逻辑非(NOT) 逻辑取非(NOT) 二元 & 逻辑与(AND) 与C语言中的&&相同 按位与 | 逻辑或(OR) 与C语言中的||相同 按位或 && 短路与 如左操作数为false,则不运算右操作数 || 短路或 如左操作数为ture,则不运算右操作数

参见示例: BitwiseOperatorTest <<、>>、>>> 位运算符 常见的位运算符有: &、|、^、~ 参见示例: BitwiseOperatorTest 还有移位运算符 <<、>>、>>> 参见示例: ShiftTest

短路与和短路或 Java提供了两个在其它计算机语言中没有的逻辑运算符,这就是逻辑与和逻辑或的短路版本; 对于短路与(&&),如果其左侧为false,则不再计算其右侧,整个表达式的结果为false,只有左侧为true时才计算右侧; 对于短路或(||),如果其左侧为true,则不再计算其右侧,整个表达式的结果为true,只有左侧为false时,才计算右侧。

短路与示例 11 11 21 20 int a = 10; int b = 20; if (++a == 12 & ++b == 22) { …… } System.out.println(a); System.out.println(b); /*这里使用的是逻辑与, 试分析最后的输出结果*/ int a = 10; int b = 20; if (++a == 12 && ++b == 22) { …… } System.out.println(a); System.out.println(b); /*这里使用的是短路与, 试分析最后的输出结果*/ 11 11 21 20

赋值运算符 赋值运算符的运算顺序是从右至左的: 运算符 说 明 = 赋值,将右侧的值赋给左侧的变量 += 说 明 = 赋值,将右侧的值赋给左侧的变量 += 相加并赋值,如:a += b等价于a = a + b -= 相减并赋值,如:a -= b等价于a = a – b *= 相乘并赋值,如:a *= b等价于a = a * b /= 相除并赋值,如:a /= b等价于a = a / b %= 取模并赋值,如:a %= b等价于a = a % b

条件运算符? : 条件运算符是三元运算符; 它的一般形式是: 表达式1 ? 表达式2 : 表达式3 根据表达式1的结果来判断执行表达式2还是表达式3,如果表达式1的结果为true,则执行表达式2,否则执行表达式3; 条件运算符在某些情况下能够替代小型的if…else语句。

运算符的优先级 很多情况下,一个表达式由多个运算符组成,优先级决定运算符的计算顺序: 优先级 运 算 符 1 括号: ()和[] 2 运 算 符 1 括号: ()和[] 2 一元运算符:-、++(前置)、--(前置)、! 3 算术运算符:*、/、%、+和- 4 关系运算符:>、>=、<、<=、==和!= 5 逻辑运算符:&、|、&&和|| 6 条件运算符:? : 7 赋值运算符:=、*=、/=、%=、+=和-=

总结 Java中的变量和数据类型 Java中变量的作用域规则 数据类型转换 Java中的输出语句 Java中的运算符和表达式

CoreJava核心编程 第三章:流程控制与数组

流程控制与数组 Java中的数组 new关键字

控制流语句 判断语句 循环语句 跳转语句 一般情况下,程序是从上往下依次顺序执行的; 但很多时候,我们需要改变程序执行的流程,这就使用到了控制流语句; 控制流语句包括: 判断语句 循环语句 跳转语句

判断语句 判断语句也称作条件语句或分支语句; 判断语句主要用来控制程序在何种情况下执行某一部分; 判断语句包括: if语句 if…else语句 if…else if语句 switch…case语句

循环语句 循环语句也称作迭代语句; 循环语句可用于重复执行相同的操作; 循环语句包括: while语句 do…while语句 for语句

跳转语句 跳转语句允许以非线性的方式执行程序,可以将控制权转到程序的其它部分; 跳转语句包括: break语句 continue语句 Java抛弃了C语言中的goto语句。

数组 数组用于将相同类型的数据存储在连续的存储单元中; 可以通过指定数组的名称和长度来声明数组; 一旦声明数组的大小,就不能再修改; 数组元素通过数组名和索引来访问,索引从0开始; 数组可以是一维,也可以是多维。

回顾C语言中的数组 在C语言中,从存储方式上讲,声明数组有两种情况; 在栈内存中分配空间,如: int ary[10]; //声明有10个整型元素的数组 在堆内存中分配空间,如: int *p = NULL; //声明整型指针 //指针指向堆空间 p = (int*)malloc(10 * sizeof(int)); C语言允许有栈数组,也允许有堆数组。

new关键字 在Java中,不允许将数组分配在栈内存中,只能分配在堆内存中; Java中没有类似于malloc、calloc、realloc和free等函数,取而代之的是new关键字; new是Java中内置的操作符; new操作符用来从堆中分配指定类型的内存空间,并返回相应类型的引用,其作用类似于malloc函数。

声明数组示例 public class ArrayDemo { public static void main(String[] args) { //声明整型数组的引用,类似于C中的 int *p; int[] ary; //为数组引用在堆内存中分配实际的内存空间 //类似于C中的 p = (int*)malloc(10 * sizeof(int)); ary = new int[10]; //使用循环为数组元素赋值 for (int i = 0; i < ary.length; i++) { ary[i] = i; } //使用循环将数组元素逐个输出到控制台 System.out.println(ary[i]);

Java中声明数组的几种方式 在Java中声明数组有如下方式: //仅声明数组的引用,但没有分配内存空间 float[] fAry; //声明数组的同时,根据指定的长度分配内存,但数组中没有值 char[] chAry = new char[10]; //声明数组并分配内存,同时将其初始化 int[] ary1 = new int[]{1, 2, 3, 4, 5}; //与前一种方式相同,仅仅只是语法相对简略 int[] ary2 = {1, 2, 3, 4, 5};

数组之间赋值 在C语言中,不可以将数组直接赋值给另一个数组; 在Java中,语法上允许这样做,但实际得到的效果是两个数组引用指向同一块内存。 int[] ary1 = {2, 4, 6, 8, 10}; int[] ary2; ary2 = ary1; //允许这样赋值 10 8 6 4 2 堆 栈 ary1 ary2

数组赋值示例 public class ArrayDemo { public static void main(String[] args) { int[] ary1 = {2, 4, 6, 8, 10}; //声明并初始化数组1 int[] ary2; //声明数组2 ary2 = ary1; //将数组1赋值给数组2 ary2[3] = 1024; //通过数组2修改其中一个元素的值 //打印出数组1中的元素 System.out.println("数组1中的元素:"); for (int i = 0; i < ary1.length; i++) { System.out.println(ary1[i]); } //打印出数组2中的元素 System.out.println("数组2中的元素:"); for (int i = 0; i < ary2.length; i++) { System.out.println(ary2[i]);

关于数组长度 在Java中,程序员可以不再关注数组的长度,数组自带的length属性将负责保管数组的长度; C语言不检查数组的边界,数组索引完全由程序员掌握; Java对数组下标越界情况强加约束; 如果试图访问不在有效索引以内的元素,将会引发运行错误。

Java中的垃圾回收机制 在C语言中,被malloc或calloc函数分配的堆内存在使用完毕以后,必须使用free函数进行释放,否则将会造成内存泄漏; 同样的,在Java中由new分配的内存也将存在内存泄漏的可能; 但释放内存的任务是由Java虚拟机来完成的,程序员可以不再关心此项工作; 如果某块内存空间没有任何引用指向它,那么虚拟机就将其认定为垃圾; 虚拟机并不是随时随地地立即回收垃圾,而是在系统比较空闲的时候,才会执行回收任务。

命令行参数 在命令行使用java命令执行程序时,可以将一些参数传递给main函数; main函数携带的String[](字符串数组)类型的形参args正是为了接收这些来自命令行的参数; 可以从命令行传递任意多个字符串给main函数,其间使用空格隔开,也可以不传递任何参数; 这些传递进来的多个字符串最后以字符串数组的形式,供main函数中加以使用。

命令行参数示例 public class ArgumentDemo { public static void main(String[] args) int len = args.length; //获得命令行参数的个数 if (len > 0) //判断是否有命令行参数 //如果有,将其逐一打印到控制台 System.out.println(len + "个命令行参数,具体如下:"); for (int i = 0; i < args.length; i++) System.out.println(args[i]); } else //否则给出提示信息 System.out.println("您没有传递任何命令行参数。");

总结 Java中数组是引用数据类型,只能存放在堆内存中; 数组必须由new关键字为其分配内存; 可以利用命令行参数接收来自用户的输入。

作业 利用命令行参数输入一个整数,并判断该数字是否为奇数,如果是奇数,则用其作行数打印空心菱形 PS:将字符串转换为数字的方法 int num=Integer.parseInt(String number); 利用命令行参数输入三个整数,并对三个数字进行降序排列。 利用命令行参数输入多个参数,并赋值给一数组,同时判断该数组是否为回文数组 PS:例如数组{“123”,”222”,”333”,”222”,”123”}就是回文数组,即元素倒置过后与原元素一样

逻辑趣味思考题 有两个桶,一个容量为5升,一个容量为3升,现在用桶子来乘水,请您用这两个桶准确的乘出4升水来。 有10堆鱼,每堆鱼10条,正常情况下每条鱼10斤,但是现在这10堆鱼中有1堆鱼全是每条9斤,现在给你一把秤(假设这把秤可以称很重很重的东西),请问您能通过一次称量就找出这堆缺斤少量的鱼吗?

CoreJava核心编程 第四章:面向对象思想

回顾 Java中的数据类型分为:原始数据类型和引用数据类型; 在数据类型转换中,由低类型转至高类型,将会自动(隐式)类型转换,而从高类型转至低类型,则必须强制(显式)类型转换; Java中的数组是引用数据类型,必须由new关键字在堆中分配内存; Java虚拟机的垃圾回收机制将自动释放不再使用的内存; 使用命令行参数接收来自用户的输入。

相关词汇 单 词 说 明 Class 类,种类 public 公共的,公有的 private 私有的,私人的 object 对象,物体 单 词 说 明 Class 类,种类 public 公共的,公有的 private 私有的,私人的 object 对象,物体 encapsulation 封装,包装 attribute 属性,特征 method 方法 member 成员 constructor 构造方法,构造器

类和对象I 了解什么是 面向对象 面向对象的 基本概念 如何定义 类,如何创建 对象 成员运算符 访问控制权限:public和private 封装 继承 多态 如何定义 类,如何创建 对象 成员运算符 访问控制权限:public和private 构造方法

类和对象I 了解什么是 面向对象 面向对象的 基本概念 如何定义 类,如何创建 对象 成员运算符 访问控制权限:public和private 封装 继承 多态 如何定义 类,如何创建 对象 成员运算符 访问控制权限:public和private 构造方法

Object Oriendted Programming 什么是面向对象? Object Oriendted Programming 对象 以…为导向的 程序设计 面向对象编程 就是使用对象进行程序设计,简写成OOP。

面向对象的编程语言 如今,面向对象的编程思想已经成为主流; 面向对象的编程语言正大行其道,最具代表性的有: C++ Java C# 连数据库也开始面向对象了,如Oracle。

OOP 面向对象的编程思想 旨在计算机程序中 模拟现实世界中的概念 在OOP中,现实世界的 所有事物全都被视为对象 在计算机程序中用相似的 实体模拟现实世界中的实体 设计和实现 软件系统的方法

C语言的编程方式 C语言是结构化的编程语言(Structured Programming,简作SP); 强调精巧的数据结构和优越的算法,关注程序的运行效率; 不适合于大规模的程序开发; 程序模块之间协调性差,程序的重用性、安全性、健壮性和可维护性都存在较大的缺陷。

SP和OOP对比 SP OOP 设计思路 自顶向下、层次化、分解 自底向上、对象化、综合 程序单元 函数模块 对象 设计方法 程序 = 算法 + 数据结构 程序 = 对象 = 数据 + 方法 优点 相互独立,代码共享 接近人的思维方式 模拟客观世界 缺点 数据与程序不一致 维护困难 客观世界的无序性 概念不成熟

面向对象的三大原则 封 装 继 承 多 态

对象 对象是面向对象编程的核心部分,是实际存在的具体实体,具有明确定义的状态和行为; 对象其实就是“数据”和“函数”的封装体,其中: 姓名:布兰尼 职衔:收银员 年龄:35 体重:60千克 操作: 收款 打印帐单 收银员对象 对象是面向对象编程的核心部分,是实际存在的具体实体,具有明确定义的状态和行为; 对象其实就是“数据”和“函数”的封装体,其中: 数据表示自身的状态,也称作“属性”或“成员数据”; 函数表示自身的功能,也称作“方法”或“成员函数”。 状态 行为 顾客 姓名:朱丽叶 年龄:28 体重:52千克 操作: 购买商品 顾客对象

类 人们为了更好地认识世界,将现实生活中的事物(对象)划分成类; 同一类中的事物总是具有一些共性; 类以共同的特性和行为定义实体; 类是具有相同属性和和行为的一组对象的集合。

属性 事物的特性在类中用变量表示; 每个对象的每个属性都拥有其特定的值; 属性名称由类的所有对象共享; 对象或实体拥有的特征在类中表示时称为属性。 学生对象 姓 名 年 龄 住 址 …… 属 性

方法 事物的行为和动作在类中用函数表示; 每个对象都有相同的动作和行为; 对象执行的操作在类中表示为方法。 吃 饭 睡 觉 上 课 …… 学生对象 吃 饭 方 法 睡 觉 上 课 ……

类和对象的区别 类是用来描述实体的“模板”或“原型”; 对象是实际的实体,每一个对象都是类的一个具体实例; 类用来定义对象所有的属性和方法,同一类的所有对象都拥有相同的特征和操作; 可以将类理解成生产产品的模具,而对象则是根据此模具生产的一个个产品。

类与结构 最简单的理解方式: 类 结构体 结构体变量 对象 C Java 区别在于:结构体一般只有数据(属性)而没有函数(方法)。

封装 将某些东西包装在一起,然后以新的完整形式呈现出来; 隐藏属性、方法或实现细节的处理方式称为封装; 封装其实就是有选择性地公开或隐藏某些信息,它解决了数据的安全性问题。 可以公开 一 个 人 类 的 对 象 姓名:张三 体重:50kg …… 密码:****** 属性 走路 吃饭 方法 无所谓 不可以公开

继承 继承就是重用现有的类来生成新类的一种特征; 通俗地讲就是从现有的类(即父类或基类)创建新类(子类或派生类)的过程; 现实生活中,继承可以达到财产重用的目的,而在Java中,继承可以使代码重用。

多态 多态是指同一函数在不同的类中有不同的实现; 多态的好处就是使类更灵活,更便于扩充。

抽象 把相同的或相似的对象归为一类的这个过程就是抽象,所以,抽象就是分析问题的方法; 抽象的基本原则: 只关心主要问题,而不关心次要问题; 只关心主要矛盾,而不关心次要矛盾; 只关心相同的东西,而不关心不同的东西; 只关心问题是什么,能够完成什么,而不关心怎样去完成。 抽象的过程其实就是面向对象编程的核心思想。

在Java中定义类 成员变量 成员函数 /*定义学生类*/ class Student { String name; //姓名 int age; //年龄 float weight; //体重 /*吃饭的方法*/ void dining() System.out.println("吃饱了..."); weight++; } /*走路的方法*/ void walk() System.out.println("走累了..."); weight--; 成员变量 成员函数

习惯上,类名的首字母大写,如:Student 定义类的语法 class 类名 { 成员列表 //包括成员变量和成员函数 } 在Java中定义类 struct 结构体名 { 成员列表 //只有成员变量,没有成员函数 }; 在C中定义结构体 习惯上,类名的首字母大写,如:Student

在Java中创建对象 /*Test类,用来容纳main方法*/ public class Test { /*main方法,程序入口*/ public static void main(String[] args) Student std; //声明Student类型的引用 std = new Student(); //创建Student类型的对象 std.name = "张三"; //为姓名赋值 std.age = 18; //为年龄赋值 std.weight = 50; //为体重赋值 std.dining(); //调用成员方法 System.out.println(std.weight); std.walk(); }

创建对象的语法 和数组相似,对象也是引用数据类型,只能使用new运算符从堆中分配内存; 创建对象的一般语法: 使用已经定义好的类,创建该类对象的过程称为“实例化”。 注意:这里要有括号

成员运算符. 在C语言中,必须要先声明结构体变量,才可以访问结构体中的成员; 同样的,只有先实例化类的对象,才可以访问到类中的成员(属性和方法); 使用成员运算符(.)来访问成员属性或成员方法; 一般语法是: 对象名.成员名 如:std.age = 18; //为成员属性赋值 std.dining(); //调用成员方法

访问权限:public和private C语言中结构体的成员可以从任何地方进行访问,这将给数据的安全留下极大的隐患; 为了避免从类外部直接访问类成员而造成的数据损坏,Java对类成员的访问制定了约束; 关键字public和private是访问修饰符,用来说明某个成员是否可以从类外部进行访问; public修饰的成员可以在任何地方进行访问,不受任何约束; private修饰的成员只能够被本类中的其它成员访问,而不能从类的外部进行访问。

访问权限 类 无法从类的外部访问私有成员; 其它类的私有成员对于当前类也是隐藏的。 私有 公有 不可从类外部访问 属性或方法 可以从类外部访问 类 属性或方法 私有 公有 不可从类外部访问

访问权限示例 class Student { private String name; //姓名,私有的,不可以从类外部直接访问 private int age; //年龄,私有的,不可以从类外部直接访问 private float weight; //体重,私有的,不可以从类外部直接访问 //吃饭的方法,公有的,可以从任何地方访问 public void dining() { System.out.println("吃饱了..."); weight++; //dining方法是类内部成员,可以直接访问本类私有成员 } //走路的方法,公有的,可以从任何地方访问 public void walk() { System.out.println("走累了..."); weight--; //walk方法是类内部成员,可以直接访问本类私有成员 public class Test { public static void main(String[] args) { Student std = new Student(); //实例化一个Student对象 std.age = 18; //试图从类外部访问私有成员,将会报出一个错误 std.dining(); //允许访问公有成员

访问权限(续) 加上访问修饰符有时候可能会给操作数据带来不便,但可以在很大程度上保证数据的安全; 一般地,我们会将成员属性声明为private,而将成员方法声明为public,但这样做并不是绝对的; 有时候,类外部可能要操作到某些私有数据成员,那么就可以增加一个公有的方法,再由这个方法来操作私有数据,避免因类外部的误操作而造成的数据损坏; 因为main方法要由类外部的虚拟机来调用,所以main方法必须声明成public。

修改Student类 class Student { //定义学生类 private String name; //姓名,私有 private int age; //年龄,私有 private float weight; //体重,私有 public void setName(String name) { //为姓名赋值的方法,公有 this.name = name; } public void setAge(int a) { //为年龄赋值的方法,公有 age = a; public void setWeight(float w) { //为体重赋值的方法,公有 weight = w; public void display() { //将所有信息打印出来的方法,公有 System.out.println("姓名:" + name + ",年龄:" + age + ",体重:" + weight); public void dining() {……} //吃饭的方法,公有,代码略 public void walk() {……} //走路的方法,公有,代码略 public class Test { public static void main(String[] args) { Student std = new Student(); //实例化学生类对象 std.setName("张三"); //为姓名赋值 std.setAge(18); //为年龄赋值 std.setWeight(55); //为体重赋值 std.dining(); //调用吃饭的方法 std.display(); //将信息打印出来

对象初始化 在上例中,只能逐个地为数据成员赋值,如果想在对象实例化的同时就初始化成员属性,就使用到了构造方法; 构造方法是特殊的成员方法,它与类同名,在对象实例化时由虚拟机自动调用; 请注意:构造方法没有返回值类型,也不能有返回值。

构造方法示例 /*定义ConstructorDemo类,对构造方法进行测试*/ class ConstructorDemo { /*构造方法,方法名与类名完全一致 无需指定返回值类型,也不能有返回值*/ public ConstructorDemo() System.out.println("这是构造方法"); } /*Test类,用来容纳main方法 一般将包含有main方法的类声明为public*/ public class Test /*main方法,程序入口*/ public static void main(String[] args) /*实例化ConstructorDemo类的对象*/ ConstructorDemo cd = new ConstructorDemo();

构造方法 正是由于在实例化对象的同时会自动调用构造方法,所以构造方法一般用来给数据成员分配资源或初始化数据成员; 构造方法的一般形式: 访问权限 类名(形参列表) { 方法体 } 因为是由虚拟机来调用构造方法,所以构造方法一般应定义成public。

为Student类添加构造方法 class Student { //定义学生类 private String name; //姓名,私有 private int age; //年龄,私有 private float weight; //体重,私有 //构造方法,根据传递进来的参数,为数据成员赋值 public Student(String n, int a, float w) { //分别为每个数据成员赋初始值 name = n; age = a; weight = w; } public void setName(String n) {……} //为姓名赋值的方法,公有,代码略 public void setAge(int a) {……} //为年龄赋值的方法,公有,代码略 public void setWeight(float w) {……} //为体重赋值的方法,公有,代码略 public void display() {……} //将所有信息打印出来的方法,公有,代码略 public void dining() {……} //吃饭的方法,公有,代码略 public void walk() {……} //走路的方法,公有,代码略 public class Test { public static void main(String[] args) { //利用构造方法,为数据成员指定初始值 Student std = new Student("张三", 18, 55); std.display(); //将信息打印出来

构造方法(续) 每个对象在生成时都必须执行构造方法,而且只能执行一次; 如果构造方法调用失败,那么对象也无法创建; 不可以显式地直接调用构造方法; 在没有定义构造方法的情况下,类会自动产生一个无参数的默认构造方法,这个默认的构造方法什么都不做; 一旦显式地定义了构造方法,默认构造方法自动消失。

总结 对象由状态(属性)和行为(方法)组成; 类是具有相同属性和方法的对象的集合; 封装可以隐藏对象实现的具体细节; 必须先实例化类的对象,才可以访问到其中的成员; 成员运算符用于访问对象的成员; 成员可以定义为公有,也可以定义为私有; 构造方法一般用来初始化对象中的数据成员; 如果不定义构造方法,将有默认的构造方法,一旦定义,默认的构造方法自动消失。

练习 编写一个包含名为Calculator类的程序。定义两个整型属性以及对该两个变量的setter和getter,编写用于对两个属性执行加、减、乘、除运算方法。在main方法里创建该类的对象并访问这些方法。 编写一个名为Box的类,含整型的length,width, height,volume四个属性,要求在构造方法中将其初始化,并定义一个计算体积的calcVolume方法和一个输出体积的print方法,在main方法中进行调用

思考 有三筐水果,一筐装的全是苹果,第二筐装的全是橘子,第三筐是橘子与苹果混在一起。筐上的标签都是骗人的,(比如,如果标签写的是橘子,那么可以肯定筐里不会只有橘子,可能还有苹果)你的任务是拿出其中一筐,从里面只拿一只水果,然后正确写出三筐水果的标签。 一列时速15英里的火车从洛杉矶出发,驶向纽约。另外一列时速20英里的火车从纽约出发,驶向洛杉矶。如果一只鸟以每小时25英里的速度飞行,在同一时间从洛杉矶出发,在两列火车之间往返飞行,到火车相遇时为止,鸟飞了多远?

CoreJava核心编程 第五章:面向对象思想II

回顾 对象由属性(数据)和方法(函数)组成; 类是具有相同属性和方法的对象的集合; 封装可以隐藏对象实现的细节部分; 对象是引用数据类型,使用new运算符创建对象实例,使用成员运算符访问对象中的成员; 访问修饰符用来控制访问权限,可以有效地保证数据安全; 构造方法一般用来初始化对象中的数据成员

相关词汇 单 词 说 明 this 这,这个 static 静态的 package 包裹,包 import 引入,导入 overloaded 单 词 说 明 this 这,这个 static 静态的 package 包裹,包 import 引入,导入 overloaded 重载,超载 overloaded method 方法重载

类和对象II 方法重载 重载 构造方法 对象 在内存中的 存放形式 this关键字 静态成员,static关键字 包 打包,package关键字 导入包,import关键字

类和对象II 方法重载 重载 构造方法 对象 在内存中的 存放形式 this关键字 静态成员,static关键字 包 打包,package关键字 导入包,import关键字

提示 在Java中,函数无需C语言中的前向声明,只要直接定义即可; Java中,函数被称为方法; 定义一个方法的一般形式: [访问权限] 返回值类型 方法名称(形参列表) { 方法主体; } 我们更关注的是方法原型,对于方法原型的三个主要组成部分应当明确区分: 返回值类型 方法名称 形式参数

在Java中定义方法 /*Java中的方法示例 代码片段 */ /*定义求平方值的方法*/ public int square(int x) { return (x * x); } 返回值类型 方法名称 形式参数

案例 方法的定义 方法的调用 /*编写求绝对值的方法来求整数的绝对值*/ /*AbsoluteValue类,其中包含求绝对值的方法 Java中的任何方法都必须在类中定义*/ public class AbsoluteValue { /*求绝对值的方法*/ public int abs(int x) return ((x >= 0) ? x : -x); } /*main方法,程序入口*/ public static void main(String[] args) //必须先实例化类的对象,才可以调用到其中的成员方法 AbsoluteValue obj = new AbsoluteValue(); int a = -8, b; b = obj.abs(a); //调用abs方法求a的绝对值 System.out.println(a + "的绝对值是" + b); 方法的定义 方法的调用

案例分析 在上面的案例中,我们已经定义了求整数绝对值的方法; 但有时候,我们可能还需要求浮点数的绝对值,请问:可以继续使用这个方法吗? 事实上是行不通的,这个方法只能求出整数的绝对值,对于浮点数,还需另外再定义求浮点数绝对值的方法。

修改案例 public class AbsoluteValue { /*求整数绝对值的方法*/ public int absOfInt(int x) { return ((x >= 0) ? x : -x); } /*求浮点数绝对值的方法*/ public float absOfFloat(float x) { public static void main(String[] args) { AbsoluteValue obj = new AbsoluteValue(); int a = -8, b; b = obj.absOfInt(a); System.out.println(a + "的绝对值是" + b); float c = -3.14f, d; d = obj.absOfFloat(c); System.out.println(c + "的绝对值是" + d); 如果还要求其它类型的 绝对值,就需要定义更 多的方法,这对于调用 者来说,将会是非常麻 烦的事情。

方法重载 用于定义一组方法,这些方法具有相同的名称,并执行类似的操作,但是却使用不同的参数列表; 编译器会根据调用时传递的实际参数自动判断具体调用的是哪个重载方法,如: /*abs方法的重载*/ int abs(int x) {……} float abs(float x) {……} double abs(double x) {……} long abs(long x) {……}

方法重载的三大原则 方法名相同 参数不同(可以有三方面的不同) 同一作用域 数量不同 类型不同 顺序不同 同一作用域 温馨提示:方法重载跟方法的返回值类型没有任何关系。也就是说,只有返回值不同的方法不能构成重载。 /*错误的方法重载*/ void fun(int x) {……}; int fun(int x) {……};

方法重载示例 public class AbsoluteValue { public int abs(int x) { //重载方式1,求整数的绝对值 return ((x >= 0) ? x : -x); } public float abs(float x) { //重载方式2,求浮点数的绝对值 public double abs(double x) { //重载方式3,求双精度数的绝对值 public long abs(long x) { //重载方式4,求长整型数的绝对值 public static void main(String[] args) { AbsoluteValue obj = new AbsoluteValue(); int a = -8, b; b = obj.abs(a); System.out.println(a + "的绝对值是" + b); float c = -3.14f, d; d = obj.abs(c); System.out.println(c + "的绝对值是" + d);

方法重载的两种方式之一 利用不同数据类型的参数重载; 对于带有相同数量参数但参数类型不同的重载方法,编译器可以区分它们,如: 只要所有参数式样都是唯一的,就可以使用多个重载; 很多编程语言已经重载了输出方法,以便您可以用相同的函数名称输出任何类型的数据。 int square(int x) {……} float square(float x) {……} double square(double x) {……}

方法重载的两种方式之二 利用不同数量的参数重载,如: 将调用与参数最匹配的方法,如果没有方法得出最佳匹配,那么编译器将报错; 编译器解决重载的方式与方法定义的顺序无关; 重载不考虑方法的返回值类型。 /*函数定义*/ int fun(int n1) {……} int fun(int n1, int n2, int n3) {……} /*函数调用*/ fun(a); fun(x, y, z);

方法重载的作用域规则 只有属于同一作用域范围内的方法才能构成重载。 不构成重载 class First { …… public void show() } class Second { …… public void show(int x) } 不构成重载

课堂练习1 在Java中,对于成员方法 float add(float f1, float f2) {……} 下面选项()是对该成员方法的重载。 int add(int n1, int n2) {……} float add(float f) {……} void add(float f1, float f2) {……} void add(float f1, float f2, float x) {……} float add(float f2, float f1) {……}

int fun(int x, int y) {……} float fun(int x) {……} int fun(float x) {……} 课堂练习2 在Java中,下列方法()不能与 int fun(int x) {……} 构成方法重载。 int fun(int x, int y) {……} float fun(int x) {……} int fun(float x) {……} int fun(int x, int y, int z) {……}

关于方法重载的重要提示 请勿将功能完全不一样的方法进行重载!

重载构造方法 方法重载的一个重要应用就是重载构造方法; 可以定义一组构造方法,使其构成重载关系,从而方便使用者能够灵活机动地以各种不同的方式来实例化对象。

重载构造方法示例 class MyTime { //定义时间类 private int mHour, mMinute, mSecond; //三个成员变量,时、分、秒 public MyTime() { //构造方法重载1 mHour = 0; mMinute = 0; mSecond = 0; } public MyTime(int mHour) { //构造方法重载2 mHour = mHour; public MyTime(int hour, int minute) { //构造方法重载3 mHour = hour; mMinute = minute; public MyTime(int hour, int minute, int second) { //构造方法重载4 mSecond = second; public void display() { //显示时间信息的方法 System.out.println(mHour + ":" + mMinute + ":" + mSecond);

重载构造方法示例(续) /*使用重载构造方法可以使初始化对象的方式灵活机动,大 大方便类的使用者。*/ /*测试时间类*/ public class Test { /*main方法,程序入口*/ public static void main(String[] args) //分别调用不同的构造方法来初始化时间对象 MyTime t1 = new MyTime(); //调用重载方式1 t1.display(); MyTime t2 = new MyTime(8); //调用重载方式2 t2.display(); MyTime t3 = new MyTime(8, 30); //调用重载方式3 t3.display(); MyTime t4 = new MyTime(8, 30, 30); //调用重载方式4 t4.display(); } /*使用重载构造方法可以使初始化对象的方式灵活机动,大 大方便类的使用者。*/

对象在内存中的存放形式 对象1 对象3 对象2 每个对象都有自己独立的数据成员,但是所有的对象共享成员方法。 成员变量1 成员变量2 成员方法1 成员方法2 …… 成员方法n 成员变量1 成员变量2 成员变量n 对象1 对象3 对象2 每个对象都有自己独立的数据成员,但是所有的对象共享成员方法。

this关键字 既然所有的对象都共用相同的成员方法,那么在不同的对象都调用同一方法时,它是怎么确定要使用哪个对象的数据成员呢?

this引用示例 /*this示例,代码片段*/ public class Student //定义学生类 { private String mName; //姓名 private int mAge; //年龄 public Student(String name, int age) //隐式调用,等同于this.mName = name; mName = name; //显式调用,等同于mAge = age; this.mAge = age; } ……

回顾C语言中的静态变量 C语言中的静态变量的特点: 具有全局变量的生命周期(完成了某些全局变量才能完成的功能); 具有有局部变量的作用域(比全局变量更安全)。 在C语言中声明静态变量的语法: static int x; 声明静态变量使用关键字static。

静态成员变量 在成员变量前加static关键字,可以将其声明为静态成员变量; 如果类中成员变量被定义为静态,那么不论有多少个对象,静态成员变量只有一份内存拷贝,即所有对象共享该成员变量; 静态成员变量的作用域只在类内部,但其生命周期却贯穿整个程序。

静态成员变量示例 class Dog { public static int count = 0; //静态成员变量 public Dog() //构造方法 count++; } public class Test public static void main(String[] args) System.out.println("当前狗的数量是:" + Dog.count); Dog d1 = new Dog(); Dog d2 = new Dog();

静态成员变量的注意事项 和程序同生命周期; 在没有实例化对象时,可以通过类名访问静态成员变量; 也可以通过对象访问静态成员变量,但不论使用的是哪个对象,访问到的都是同一个变量; 静态成员变量在声明时最好初始化,如果不进行初始化,系统会默认初始化为初始值。

静态成员方法 在成员方法前加static关键字,可以将其声明为静态成员方法; 静态成员方法只能对类的静态成员变量进行操作; 静态成员方法没有this引用; 在没有实例化对象时,可以通过类名访问静态成员方法。

静态成员方法示例 class Dog { private static int count = 0; //静态成员变量 public Dog() { count++; } //显示数量的方法,静态成员方法 public static void displayCount() { System.out.println("当前狗的数量是:" + count); public class Test { public static void main(String[] args) { //没有实例化对象之前,直接通过类名调用静态成员方法 Dog.displayCount(); Dog d1 = new Dog(); Dog d2 = new Dog();

静态成员小结 静态成员包括静态数据成员和静态成员方法; 静态成员属于整个类而不是属于某个对象,它被该类的所有对象共享; 访问静态成员时一般通过类名访问,也可以通过对象访问; 静态成员也受访问权限的约束; 静态数据成员在使用之前应尽量初始化; 静态成员方法不能操作非静态成员; 静态成员方法没有this引用。

包 有时候,类和类的名称可能发生冲突; Java提供了把类名空间划分为更容易管理的块的机制,这就是包; 包允许将类组合成较小的单元,类似于文件夹; 有助于避免命名冲突,分属不同包的类即便名称相同也不会引起误会; 能在包与包之间对于类的访问权限提供更有力的约束。

使用package关键字打包 可以使用package关键字将源文件中的类打入某个包中,语法是: package 包名; 该语句必须是整个源文件的第一条语句; 包中还可以包含下一级子包,这与文件目录体系非常相似。 //将本源文件中的所有类打到mypkg包中 package mypkg; class Student //定义学生类 { …… }

缺省包 如果省略了package语句,类将保存在一个缺省的没有名称的包中; 尽管缺省包很方便,但对于大型的程序,它是不恰当的; 请尽量为自己编写的类定义具体的包。

使用import关键字导入包 如要使用到某个包中的类,就需要使用import关键字将包或类显式地包括到程序中,有如下两种情况: /*导入java包下的io子包中的所有类*/ import java.io.*; /*导入mypkg包下的Student类,但并不导入该包中的其它类*/ import mypkg.Student; ……

总结 方法重载可以方便方法的调用者,但方法重载应遵循三大原则: 方法名相同 参数列表不同 属于同一作用域 可以适当地重载构造方法,使初始化对象的方式更加灵活; this引用总是指向调用方法的对象本身; 静态成员属于类而不是属于某个对象; 总是将自己定义的类打入到具体的包中是良好的编程习惯; 可以使用import语句导入需要的包或类

作业 在JAVA中定义一个类,在该类中有一系列的求绝对值的方法,要求使用方法重载? 定义一个学生类,并将学生类的属性私有化同时为其提供公开的setter和getter,同时要求方法的参数名字要求要和属性名字一样!使用this关键字的编程! 使用package对自己编写的类打包!使用import将其他的包中的类导入到程序中来

逻辑趣味思考题 小明和他四个兄弟住在一起,每个人都有一个房间,假设每个房间都配有两个钥匙,除了每人拥有自己房间的一枚钥匙以外,如何放置剩下钥匙,且能让任何一个人任何时间都能顺利地进入每个房间呢?

CoreJava核心编程 第六章:继承

继承 方法重载应遵循三大原则; 适当地重载构造方法,可以使初始化对象的方式更为灵活; this引用总是指向调用成员方法的对象本身; 静态成员(包括静态成员属性和静态成员方法)属于类而不是属于某个对象,可以在实例化对象之前通过类名访问; 使用package关键字打包; 使用import关键字导入包或类。

本章相关词汇(蓝色为关键字) 单 词 说 明 protected 受保护的 extends 扩充,扩展 super 上一级的,超级的 单 词 说 明 protected 受保护的 extends 扩充,扩展 super 上一级的,超级的 access 访问 inheritance 继承,遗传 base class 基类/父类 derived class 子类/派生类 modifier 修饰符

本章目标 对象数组(补充) 理解什么是继承 在Java中实现继承,extends关键字 四种访问控制权限 public protected private 缺省 继承中的构造方法 super关键字

继承 在Java中实现继承,extends关键字 四种访问控制权限 继承中的构造方法 super关键字

对象数组 在Java中不但可以声明由原始数据组成的数组,还可以声明由对象组成的数组; 声明对象数组的方式如: 但上述方式类似于C语言中的: struct Student **p = NULL; p = (struct Student**)malloc(5 * sizeof(struct Student*)); //只是声明了一个指针数组,没有任何实际的结构体变量 //假设已经定义了一个Student类 /*声明由5个Student对象组成的数组*/ Student[] stdAry = new Student[5];

对象数组==引用数组 错误的理解方式 堆 栈 堆 栈 正确的理解方式 学生对象的实例 1 2 3 4 stdAry stdAry 对象的引用 1 2 3 4 堆 栈 stdAry 堆 栈 stdAry 正确的理解方式 对象的引用 1 2 3 4

对象数组示例 /*对象数组示例,假设已经定义了Student类*/ public static void main(String[] args) { /*创建包含有5个Student引用的数组*/ Student[] stdAry = new Student[5]; /*逐一为每个引用创建对象实例*/ stdAry[0] = new Student("张三", 18); stdAry[1] = new Student("李四", 20); stdAry[2] = new Student("王五", 24); stdAry[3] = new Student("郑六", 21); stdAry[4] = new Student("田七", 19); for (int i = 0; i < stdAry.length; i++) stdAry[i].display(); }

对象数组的存放形式 堆 栈 stdAry 1 2 3 stdAry[0] stdAry[1] stdAry[2] stdAry[3] 1 2 3 stdAry[0] stdAry[1] stdAry[2] stdAry[3] stdAry[4] 4 张三 18 李四 20 王五 24 郑六 21 田七 19

面向对象的三大特征 面向对象的程序设计有三大特征: 封装:解决了数据的安全性问题 继承:解决了代码的重用问题 多态:解决了程序的扩展问题 前面的章节我们已经学习了有关于封装的各个概念,这一章我们来讨论第二大特征——继承。

继承的概念 在现实生活中的继承,可以理解为儿子继承了父亲的财产,即财产重用; 面向对象程序设计中的继承,则是代码重用; 继承是利用现有的类创建新类的过程,现有的类称作基类(或父类),创建的新类称作派生类(子类)。 基类 方法和属性 派生类 基类方法 + 附加方法

大学系统人员分类树 人 学生 老师 大学生 研究生

继承的概念(续) 最高层是最普遍的、最一般的情况,往下每一层都比上一层更具体,并包含有高层的特征,通过这样的层次结构使下层的类能自动享用上层类的特点和性质; 继承其实就是自动地共享基类中成员属性和成员方法的机制。

在Java中实现继承 在Java中实现继承需要使用到extends关键字; 实现继承的一般语法是: [访问修饰符] class 派生类名 extends 基类名 { 成员列表 } 如: class Student extends Person { ……

实现继承示例 class Person { //定义人类 public String mName; //姓名 public int mAge; //年龄 public void dining() { System.out.println("吃饱了..."); } //吃饭的方法 } class Student extends Person { //学生类继承于人类 public float mGrade; //成绩 public void examination() { System.out.println("考试及格了..."); } //考试的方法 class Teacher extends Person { //教师类继承于人类 public float mSalary; //薪水 public void prelection() { System.out.println("上课很累..."); } //上课的方法 public class InheritanceDemo { //该类用于容纳main方法 public static void main(String[] args) { Student std = new Student(); //实例化学生对象 std.mName = "张三"; std.mAge = 18; //为姓名和年龄赋值,访问的是父类中的成员 std.dining(); //调用吃饭的方法,访问的是父类中的成员 std.examination(); //调用考试方法,访问的是子类中的成员 Teacher tea = new Teacher(); //实例化教师对象 tea.mName = "谭浩强"; tea.mAge = 65; tea.dining(); tea.prelection();

继承的作用 当今软件设计的特征: 软件规模越来越大; 软件设计者越来越多; 软件设计分工越来越细。 引入继承,实现了代码重用; 引入继承,实现了递增式的程序设计。

继承的作用(续) 继承是能自动传播代码和重用代码的有力工具; 继承能够在某些比较一般的类的基础上建造、建立和扩充新类; 能减少代码和数据的重复冗余度,并通过增强一致性来减少模块间的接口和界面,从而增强了程序的可维护性; 能清晰地体现出类与类之间的层次结构关系。

与继承有关的注意事项 继承是单方向的,即派生类可以继承和访问基类中的成员,但基类则无法访问派生类中的成员; 在Java中只允许单一继承方式,即一个派生类只能继承于一个基类,而不能象C++中派生类继承于多个基类的多重继承方式。

对任何实现细节所作的修改不会影响到使用该类的其它代码; 使类更易于使用。 类成员的访问控制权限 信息隐藏是面向对象程序设计的重要特点之一,它可以: 防止类的使用者意外损坏数据; 对任何实现细节所作的修改不会影响到使用该类的其它代码; 使类更易于使用。 在Java中实现信息隐藏的是访问控制权限机制; 访问控制权限包括4个访问修饰符:public、protected、private和缺省; 可以使用上述访问修饰符修饰类的成员。

访问修饰符 public protected private 缺 省 不受任何限制,本类或非本类均可随意访问。 本类及其子类可以访问(父子友好),同一个包中的其它类也可访问(包内友好)。 protected 只有相同包中的类可以访问(包内友好)。 缺 省 只有本类可以访问,其余都不可以。 private

访问控制权限(列表) public protected 缺省 private 访问修饰符 位 置 本类 可以 同包子类 不可以 同包非子类 不同包子类 不同包且非子类 访问修饰符 位 置

课堂练习1 源文件BaseClass.java 源文件DerivedClass.java package com.chinasofti…… public class BaseClass { public int pubA; protected int proB; int defC; private int priD; } 源文件DerivedClass.java package com.chinasofti…… public class DerivedClass extends BaseClass { public void fun() pubA = 10; proB = 20; defC = 30; priD = 40; } √ √ √ ×

课堂练习2 源文件Frist.java 源文件Second.java public class Frist { public int pubA; protected int proB; int defC; private int priD; } public class Second { public void fun() Frist obj; obj = new Frist(); obj.pubA = 10; obj.proB = 20; obj.defC = 30; obj.priD = 40; } 源文件Second.java √ √ √ ×

课堂练习3 源文件SuperClass.java 源文件SubClass.java package com.chinasofti…… public class SuperClass { public int pubA; protected int proB; int defC; private int priD; } package com.chinasofti…… import aaa.SuperClass; public class SubClass extends SuperClass { public void fun() pubA = 10; proB = 20; defC = 30; priD = 40; } √ √ × ×

类的访问权限 还可以在定义类时为类添加访问修饰符,对类进行访问权限控制; 对类使用的访问修饰符只有public和缺省两种; 不加访问修饰符,缺省修饰的类只能从本包中访问,不同包则无法访问到; 但要注意的是:在一个源文件中只能有一个被public修饰的类,并且文件名必须与public的类同名; 如果要定义多个public的类,则必须分别写在不同的源文件中,一个源文件只写一个类是良好的编程习惯。

继承中的构造方法 父类中的构造方法不能被子类继承,即便它是public的; 父类的构造方法负责初始化属于它的成员变量,而子类的构造方法则只需考虑属于自己的成员变量,不必去关注父类的情况。

继承中的构造方法示例 class ParentClass { //定义父类 public ParentClass() { //构造方法 System.out.println("这是父类的构造方法。"); } class ChildClass extends ParentClass { //子类继承于父类 public ChildClass() { //构造方法 System.out.println("这是子类的构造方法。"); public class ConstructorTest { //该类用于容纳main方法 public static void main(String[] args) { ChildClass cc = new ChildClass(); //实例化子类对象

构造方法的执行顺序 当实例化子类的对象时,必须先执行父类的构造方法,然后再执行子类的构造方法; 如果父类还有更上级的父类,就会先调用最高父类的构造方法,再逐个依次地将所有继承关系的父类构造方法全部执行; 如果父类的构造方法执行失败,那么子类的对象也将无法实例化。

本例将报出错误 案例 class Point { //定义"点"类 //x轴坐标和y轴坐标,由于准备用于继承,故修饰为protected protected float mX, mY; public Point(float x, float y) { //构造方法 mX = x; mY = y; } class Circle extends Point { //定义"圆"类继承于"点"类 protected float mRadius; //半径 public Circle(float r) { //构造方法 mRadius = r; public class Demo { public static void main(String[] args) { Circle c = new Circle(2.5f); //实例化"圆"类对象 本例将报出错误

案例分析 在实例化Circle类对象时,虚拟机一定会先调用其父类(Point类)的构造方法; Point类的构造方法需要两个参数来初始化其成员,但此时并没有获得这两个参数,造成Point类的构造方法无法执行; 父类的构造方法执行失败从而导致子类(Circle类)的对象也无法创建; 问题的关键是:在实例化子类对象时,如何将参数传递给父类的构造方法?这将使用到super关键字。

super关键字的第一种用途 在Java中,super关键字有两个主要用途; 其一般语法是: super(实际参数); 需要注意的是:该语句必须是子类构造方法的第一条语句。

super关键字示例1 class Point //定义"点"类 { protected float mX, mY; //x轴坐标和y轴坐标 public Point(float x, float y) //构造方法 mX = x; mY = y; } …… class Circle extends Point //定义"圆"类继承于"点"类 protected float mRadius; //半径 public Circle(float x, float y, float r) //构造方法 super(x, y); //显式调用父类构造方法,必须是第一条语句 mRadius = r;

super关键字的第二种用途 如果父类和子类中有同名成员,在子类中默认访问是属于自己的那一个成员; 其一般语法是: super.成员名; 前提条件是:父类中的该成员不是private的。

super关键字示例2 //定义父类 class SuperClass { protected int num; …… } //定义子类,继承于父类 class SubClass extends SuperClass protected int num; //子类中有与父类成员同名的成员 public void fun() num = 10; //默认访问自己的成员 super.num = 20; //指定访问父类的成员

表示一个指向“implicit parameter”的引用 调用本类中的另一个构造器 调用父类的方法 调用父类的构造器 super与this this关键字有两种意义: 表示一个指向“implicit parameter”的引用 调用本类中的另一个构造器 super关键字也有两种意义: 调用父类的方法 调用父类的构造器 但是,super并不表示一个指向对象的引用,它只是一个特殊的关键字,用来告诉编译器,现在要调用的是父类的方法。

作业 编写一个程序,用于创建一个名为Employee的父类和两个名为Manager和Director的子类,Employee类中包含三个属性和一个方法,属性为name,basic和address,方法为show用于显示这些属性的值。Manager类有一个称为department的附加属性。Director类有一个称为transportAllowance的附加属性。创建包含main方法的EmployeeTest类,在main方法创建Manager和Director类的对象,并调用show方法显示其详细信息。 要求: 所有类的属性通过构造方法初始化。 name是名字、basic是基本底薪、address是地址、 transportAllowance是津贴

作业题效果

逻辑趣味思考题 从空中放下两列火车,每列火车都带着降落伞,降落到一条没有尽头的笔直的铁道上。两列火车之间的距离不清楚。两列车都面向同一个方向。在落地后,降落伞掉在地上,与火车分离。两列火车都有一个微芯片,可以控制它们的运动。两个芯片是相同的。两列火车都不知道自己的位置。你需要在芯片中写入编码,让这两列火车相遇。每行编码都有一定的执行命令的时间。你能使用以下指令(而且只能用这些指令): MF—让火车朝前开   MB—让火车朝后开   IF(P)—如果火车旁边有降落伞,这个条件就得到了满足。 GOTO

CoreJava核心编程 第七章:多态I

多态(1) 继承是指从一个基类(父类)派生出派生类(子类)的过程; 继承使用关键字extends; 对于类成员,可以使用public、protected、缺省和private这4种访问权限修饰符; 对于类,可以使用public和缺省这2个访问权限; 创建子类实例时,必须先执行父类的构造方法,然后再执行子类的构造方法; super关键字有两种主要用途,都与父类有关。

本章相关词汇(蓝色为关键字) 单 词 说 明 polymorphism 多态,多态性 casting 转型 单 词 说 明 polymorphism 多态,多态性 casting 转型 overridden method 方法覆盖

本章目标 方法覆盖 引用转型 了解多态,在Java中实现多态

多态(1) 方法覆盖 引用转型 了解多态,在Java中实现多态

父/子类中的同名成员 上次课在讲述super关键字时,提到了父类和子类中存在同名成员的情况; 如果是同名属性(即成员变量同名),那么可以通过this和super显式地区分开来; 如果是同名方法(即成员方法同名),情况将会相对复杂。

父/子类中成员方法仅仅同名 /*如果仅仅只是名称相同,但参数列表不同的话,则构成方法重载*/ class BaseClass //定义基类 { public void fun() …… //具体实现代码略 } class DerivedClass extends BaseClass //派生类继承于基类 public void fun(int x) //跟父类中有相同名称的方法 /*如果仅仅只是名称相同,但参数列表不同的话,则构成方法重载*/

父/子类中成员方法同原型 class SuperClass //定义父类 { public void fun() …… //具体实现代码略 …… //具体实现代码略 } class SubClass extends SuperClass //子类继承于父类 public void fun() //与父类中的方法完全同原型 /*如果不但名称相同,而且连方法原型也完全相同的话,则构成方法覆盖*/

方法覆盖 在类的继承体系结构中,如果子类中出现了与父类中有同原型的方法,那么认为子类中的方法覆盖了父类中的方法(也称为方法重写); 通过子类的实例调用被覆盖的方法时,将总是调用子类中的方法,而父类中的方法将被隐藏。

方法覆盖示例 class ParentClass { //定义父类 public void fun() { System.out.println("这是父类中的方法。"); } class ChildClass extends ParentClass {//子类继承于父类 public void fun() { //子类覆盖父类中的方法 System.out.println("这是子类中的方法。"); class OverriddenTest { //用于容纳main方法 public static void main(String[] args) { ParentClass parObj = new ParentClass(); parObj.fun(); //父类的实例调用此方法 ChildClass chiObj = new ChildClass(); chiObj.fun(); //子类的实例调用此方法

方法覆盖的注意事项 子类中重写的方法,其访问权限不能比父类中被重写方法的访问权限更低 参见示例:AccessTest.java 在子类中重写方法时要保持方法的签名与父类中方法的签名一致 参见示例:AnnotationTest.java

区分方法覆盖和方法重载 方法覆盖(重写)和方法重载是两个极易混淆的概念,必须严格区分; 方法覆盖出现的前提条件之一是必须有继承发生的情况下,而且要求父类和子类中的方法必须同原型; 方法重载时,继承并不是必需的,它只要求方法名称相同,而参数列表则必须不同,换言之,各方法的原型其实是不同的。

引用转型 基类的引用可以指向派生类的对象,如: BaseClass obj = new DerivedClass(); 这样的语句是合法的; 但是派生类的引用则不可以指向基类的对象,如: DerivedClass obj = new BaseClass(); 这样的语句将引发错误。

引用转型示例 class Person { //定义人类 …… } class Student extends Person { //学生类继承于人类 public class OverriddenDemo { public static void main(String[] args) { //正确,所有的学生一定是人 Person per = new Student(); //错误,并不是所有的人都是学生 Student std = new Person();

问题 既然基类的引用可以指向派生类的实例,如果基类和派生类中存在方法覆盖的情况,那么通过基类的引用将会调用到哪个类中的方法呢?

示例 class Shapes { //基本形状类 public void draw() { //绘图的方法 System.out.println("绘制了一个基本形状。"); } class Circle extends Shapes { //圆形类继承于基本形状类 public void draw() { //覆盖父类的绘图方法 System.out.println("绘制了一个圆形。"); class Square extends Shapes { //正方形类继承与基本形状类 System.out.println("绘制了一个正方形。"); public class polymorphismDemo { public static void main(String[] args) { Shapes obj = new Shapes(); //父类的引用指向父类的实例 obj.draw(); //调用绘图方法 obj = new Circle(); //父类的引用指向子类的实例 obj = new Square(); //父类的引用指向子类的实例

多态 从上例中可以看出,父类的引用指向哪个类的实例就调用哪个类中的方法; 同样是使用父类的引用,调用同一个名称的方法,却可以得到不同的调用结果,这就是Java中的多态,即:同一函数,多种形态; 实际上多态包括动态多态和静态多态。

静态多态 静态多态也称为编译时多态,即在编译时决定调用哪个方法; 静态多态一般是指方法重载; 只要构成了方法重载,就可以认为形成了静态多态的条件; 静态多态与是否发生继承没有必然联系。

动态多态 动态多态也称为运行时多态,即在运行时才能确定调用哪个方法; 形成动态多态必须具体以下条件: 必须要有继承的情况存在; 在继承中必须要有方法覆盖; 必须由基类的引用指向派生类的实例,并且通过基类的引用调用被覆盖的方法; 由上述条件可以看出,继承是实现动态多态的首要前提。

使用多态的优点 我们在前面的学习过程,已经学习到了OOP的封装和继承。 其中封装我们是为了隐藏细节,使代码模块化,而继承是为了代码重用,那么多态呢?我们来看一段需求!

飞行系统代码 //具体实现代码省略 public class Plane { void fly(){…}; // 起飞 void land(){…}; // 着陆 } public class Copter extends Plane { void fly(){…}; // 直升机起飞 void land(){….}; //直升机着陆 public class Jet extends Plane { void fly(){…}; // 喷气式飞机起飞 void land(){….}; //喷气式飞机着陆 //现在我们设计控制一个飞行的方法 public void planeFly(Plane p) { p.fly();

多态的优点 观察上面代码,我们会发现只要使用planeFly方法,可以让所有传给它的飞机(Plane的子类对象)正常起飞!不管是直升机还是喷气机,甚至是现在还不存在的,以后可能会增加的飞碟。 可以看到planeFly()方法接受的参数是Plane类对象引用,而实际传递给它的都是Plane的子类对象,现在回想一下开头所描述的“多态”,不难理解,我们使用多态便于灵活地扩展我们开发的程序。

总结 如果基类和派生类中有原型完全相同的方法,那么就形成了方法覆盖; 引用转型是指父类的引用可以指向子类的实例,但反之不可以; 在有方法覆盖的前提下,并且有引用转型的情况,就将形成动态多态。

作业 在JAVA中开发一个飞行体系!该体系可以对任何飞行器进行控制起飞和降落!

逻辑思考题 周X的前男友D鹏是D唯的堂弟;D唯是W菲的前老公;周X的前男友宋N是高Y的表弟;高Y是D唯的现任老婆;D唯是W菲的前老公;周X的前男友李亚P是W菲的现任老公;周X的前男友P树的音乐制作人是张亚D;张亚D是W菲的前男友、D唯的妹妹D颖的前老公,也是W菲的音乐制作人;张亚D是李亚P的前女友瞿Y的现男友——则下列说法最有可能正确的是? a) W菲与周X是好友关系 b) 瞿Y与W菲是好友关系 c) D颖与周X是好友关系 d) 瞿Y与周X是好友关系

CoreJava核心编程 第八章:多态II

多态(2) 如果基类和派生类中有原型完全相同的方法,那么就形成了方法覆盖; 引用转型是指父类的引用可以指向子类的实例,但反之不可以; 在有方法覆盖的前提下,并且有引用转型的情况,就将形成动态多态。

本章相关词汇(蓝色为关键字) 单 词 说 明 abstract 抽象,抽象的 interface 接口,界面 implements 实现 单 词 说 明 abstract 抽象,抽象的 interface 接口,界面 implements 实现 final 最终的,决定性的

本章目标 abstract关键字 抽象方法和抽象类 接口和实现接口,interface关键字和implements关键字 final关键字 类与类之间的关系(补充)

多态(2) abstract关键字 抽象方法和抽象类 final关键字

抽象方法 在某些情况下,基类无法(或者没有必要)提供被覆盖方法的具体实现,那么就可以将此方法声明成抽象方法; 使用关键字abstract声明抽象方法,一般语法: [访问权限] abstract 返回值类型 方法名称(参数列表); 如: public abstract void draw();

抽象类 如果某个类中包含有抽象方法,那么该类就必须定义成抽象类; 定义抽象类同样使用关键字abstract,一般语法: [访问权限] abstract class 类名 { 成员列表 } 如: public abstract class Shapes { public abstract void draw();

抽象类的注意事项 抽象类不可以直接实例化,只可以用来继承; 抽象类的派生子类应该提供对其所有抽象方法的具体实现; 可以这么认为,抽象方法实际上就是由抽象基类强制要求其派生子类必须实现的方法原型; 如果抽象类的派生子类没有实现其中的所有抽象方法,那么该派生子类仍然是抽象类,只能用于继承,而不能实例化; 抽象类中也可以包含有非抽象的方法; 构造方法和静态方法不可以修饰为abstract。

修改前面的案例 abstract class Shapes { //基本形状类,抽象类 public abstract void draw(); //绘图方法,抽象方法 } class Circle extends Shapes { //圆形类继承于基本形状类 public void draw() { //实现抽象父类的抽象绘图方法 System.out.println("绘制了一个圆形。"); class Square extends Shapes { //正方形类继承与基本形状类 System.out.println("绘制了一个正方形。"); public class abstractDemo { //该类用于容纳main方法 public static void main(String[] args) { Shapes obj; obj = new Circle(); //父类的引用指向子类的实例 obj.draw(); //调用绘图方法 obj = new Square(); //父类的引用指向子类的实例

接口 如果某个类中的所有方法都是抽象方法,那么可以考虑将该类定义为接口; 定义接口使用关键字interface,一般语法: 成员列表 } 如: public interface IMyInterface { ……

实现接口 与抽象类相似,接口同样不可以实例化,只能用于实现; 如果某类要实现接口,则使用implements关键字,一般语法: [访问权限] class 类名 implements 接口名 { 成员列表 } 如: public class MyClass implements IMyInterface { ……

接口示例 源文件IMyInterface.java 源文件MyClass.java package com.chinasofti…… //定义接口 public interface IMyInterface { /*接口中的所有方法都默认为抽象方法 无需加abstract关键字*/ public int add(int x, int y); public int sub(int x, int y); } package com.chinasofti…… import aaa.IMyInterface; //MyClass类实现于IMyInterface接口 public class MyClass implements IMyInterface { //实现接口中的抽象方法 public int add(int x, int y) { return (x + y); } public int sub(int x, int y) { return (x - y); 源文件MyClass.java

接口的注意事项 接口中不能定义非抽象方法,也就是说接口中不能包含有函数实体; 接口中的所有方法都默认为抽象方法,无需在每个方法前加abstract关键字; 接口的实现类应该提供对接口中所有抽象方法的具体实现,否则将成为抽象类; 与抽象类和它的继承类相似,也可以使用接口的引用指向其实现类的对象,从而达到动态多态的效果。

接口示例(续) /*InterfaceDemo.java源文件*/ //用于容纳main方法 public class InterfaceDemo { public static void main(String[] args) //使用接口的引用指向实现类的实例 IMyInterface obj = new MyClass(); System.out.println("两数的和是:" + obj.add(20, 30)); System.out.println("两数的差是:" + obj.sub(30, 20)); }

关于接口的更多知识 Java只支持单继承,而不能象C++那样可以多重继承,接口正是为了弥补这一点; 某个类只能继承于一个父类,但可以实现多个接口,如: public class 实现类名 implements 接口1, 接口2, ……, 接口n { 成员列表 }

关于接口的更多知识(续) Java中还允许一个接口继承于另一个接口,即由父接口派生出子接口,如: public interface 子接口名 extends 父接口名 { 成员列表 } 这样的话,甚至可以使用父接口的引用指向子接口的实现类的对象。

动手实践 USB接口能实现供电和数据传输这两个典型的功能,下面我们来用程序模拟USB接口和USB设备的工作情况 教学案例:接口课堂练习案例

final关键字 在Java中,final关键字有最终的,不可修改的含义; final关键字有三种用途,可以分别应用于变量、成员方法和类。

final修饰变量 如果将某个变量修饰为final,那么该变量就成为常量,一般语法: [访问权限] final 数据类型 常量名 = 值; 如: final double PI = 3.14159; PI成为常量,其后任何试图对PI进行赋值的语句都将报错; 常量在声明时必须初始化。

final修饰方法 如果将某个成员方法修饰为final,则意味着该方法不能被子类覆盖,一般语法: 如: …… } 如: public final void fun() { 如果在派生类中出现同原型的方法,将会报错。

final修饰类 如果将某个类修饰为final,则说明该类无法被继承,一般语法: [访问权限] final class 类名 { 成员列表 } 如: public final class MyClass { …… 任何类想继承于MyClass类都将报错。

类与类之间的关系 类与类之间的关系一般来说有两种:“有”关系和“是”关系; 所谓“是”关系就是指类的继承关系。如:从动物类派生出哺乳动物类,那么可以说哺乳动物是动物; 而“有”关系是指在一个类中包含了另一个类的对象,即一个类中有另一个类(的对象),可以理解为类的嵌套。

总结 无法实现的方法可以定义成抽象方法,包含有抽象方法的类应该定义成抽象类; 通过接口也能够实现多态,同时也可以弥补Java只支持单一继承的不足; final关键字有三种用途; 类与类之间的关系:“是”关系和“有”关系。

lessPay=(leave<=5)?(0.25*basic):(0.5*basic) 作业 在此前作业的基础上,进行修改。在Employee类中添加一个抽象方法以计算薪资总额。定义一个方法基于休假天数leave计算要从基本薪资中扣除的部分。计算薪资扣除部分的公式为: lessPay=(leave<=5)?(0.25*basic):(0.5*basic) Manager和Director类重写父类的抽象方法。 计算Manager的薪资总额totalAmount的公式为: totalAmount=basic+houseRentAllowance+dearnessAllowance+medicalAllowance;

作业(接上一页) 其中: houseRentAllowance为basic的8% dearnessAllowance为basic的30% medicalAllowance为1500 计算Director的薪资总额的公式为: totalAmount=basic+houseRentAllowance+dearnessAllowance+medicalAllowance+entertainmentAllowance + transportAllowance houseRentAllowance为basic的20% dearnessAllowance为basic的50% medicalAllowance为4500 entertainmentAllowance为5000 改程序还应该计算应付薪资,其公式为: NetPay=totalAmount-lessPay 请在getDescription方法中显示name,address,basic,totalAmount和netPay属性中储存的值。

作业题效果

逻辑趣味思考题 老板让工人为自己工作7天,给工人的总回报是一根金条,且在这7天当中,老板必须在每天结束工作时给工人金条中的1段。如果只允许把金条弄断两次,他该如何切割金条,又该如何给工人支付报酬?