计算机二级 - Java
计算机二级 - Java
第一章
Java语言的特点
Java是一种简单的、面向对象的、分布式的、强壮的、安全的、体系结构中立的、可移植的、高性能的、多线程的和动态的语言。
第二章、基本数据类型
考纲要求:
1、变量和常量:掌握Java标识符的命名规则
2、基本数据类型及转换:掌握各基本数据类型的表示范围及表示形式,掌握数据类型转换方法
3、了解Java类库中对基本数据类型的类包装
学习要点:
1、认识Java语言的基本元素
2、熟悉Java的标识符、关键字
3、掌握Java的基本数据类型
4、掌握Java各数据之间的转换
5、了解Java类库中对基本类型数据的类包装
2.1 概述
Java语言包含 标识符、关键字、运算符 和 分隔符 等元素。
2.2 标识符、关键字
2.2.1 标识符
什么是标识符?
在Java中变量以及类和方法都需要一定的名称,这种名称就叫标识符。
标识符命名的基本规则:
所有的标识符都必须以一个字母、下划线或美元符号“$”开头,后面的字符可以包含字母、数字、下划线和美元符号。
标识符的命名约定:
常量用大写字母,下划线常用于常量名单词分隔。
变量用小写字母开始,如果一个变量名由多个单词构成,第一个单词后面的单词以大写字母开始,例如:anInt。
类以大写字母开始。
2.2.2 关键字
关键字是Java语言自身使用的标识符,它有其特定的语法含义,Java关键字不能用做用户标识符,如:for、while、boolean等都是Java语言的关键字。
abstract | default | if | null | switch |
---|---|---|---|---|
boolean | do | implements | package | synchronized |
break | double | import | private | this |
byte | else | instanceof | protected | throw / throws |
case | extends | int | public | transient |
catch | false | interface | return | true |
char | final | long | short | try |
class | finally | native | static | void |
continue | float | new | strictfp | volatile |
for | main | super | while |
2.3 基本数据类型
Java语言提供了两种数据类型:基本类型 和 引用类型(或叫做 复合类型)
为了保证程序的可移植性,Java规定在各个不同步操作系统平台下,基本类型的数据长度保持一致。
基本类型
整型
字节型 byte 、基本型 int 、短整型 short 、长整型 long
浮点型
单精度 float 、双精度 double
字符型
char
布尔型
boolean
引用类型
数组
类(class)
接口(interface)
数据类型 | 名称 | 位长(固定) | 默认值 | 取值范围 |
---|---|---|---|---|
字节型 | byte | 8 | 0 | -128 ~ 127 |
短整型 | short | 16 | 0 | -32768 ~ 32767 |
整型 | int | 32 | 0 | -2147483648 ~ 2147483647 |
长整型 | long | 64 | 0 | -9223372036854775808 ~ 922372036854775807 |
单精度浮点型 | float | 32 | 0.0 | +1.4E-45 ~ +3.40282335E+38 |
双精度浮点型 | double | 64 | 0.0 | +4.9E-324 ~ +1.7976931348623157E+308 |
字符型 | char | 16 | '\u0000' | '\u0000' ~ '\uffff' |
布尔型 | boolean | 1 | false | true,false |
2.3.1 常量
Java中的常量在程序中为一个标识符,用来记忆一个固定的数值。在程序执行过程中常量是不可更改的数据,常量用final声明,常量与变量的区别是前者不占用内存。Java约定常量名称用大写字母。
声明常量的格式:
final 类型 常量名 [,常量名] = 值 ;
1、布尔常量
布尔常量只有两个值 true 和 false,代表了两种状态:真和假,书写时直接使用 true 和 false 这两个英文单词,不能加引号。
2、整型变量
整型变量是不含小数的整数值,书写时可采用十进制、十六进制和八进制形式。十进制常量以非0开头后跟多个09之间的数字;八进制以0开头后跟多个07之间的数字;十六进制则以 0X 或 0x 开头后跟多个0~9之间的数字或 a~f 之间的小写字母或 A~F 之间的大写字母。
3、浮点型常量(或叫做实型常量)
Java的浮点型常量有两种表示形式:
十进制数形式,由数字和小数点组成,且必须有小数点,如:123,0.123,123.0;
科学计数法形式,如123e3或123E-3,其中e或E之前必须有数,且e或E后面的指数必须为整数。
4、字符常量
字符常量是由一对单引号括起来的单个字符。它可以是Unicode字符集中的任意一个字符,如:'a' ,'Z' 。对无法通过键盘输入的字符,可用转义字符表示。
字符常量的另外一种表示就是直接写出字符编码,编码可以有八进制和十六进制形式,如字母A的八进制表示为'\101' ,十六进制表示为'\u0047' 。
\ '表示单引号字符' | \ "表示双引号字符" |
---|---|
\ 表示反斜杠字符\ | \r 表示回车 |
\n 表示换行 | \b 表示退格 |
\f 表示走纸换页 | \t 表示横向跳格 |
5、字符串常量
字符串常量是由一对双引号括起来的一串字符。如:“abc”,“123”,“我是足球迷” 等等。
注意,Java中的字符串常量作为String类的一个对象来处理。
2.3.2 变量
变量在程序中为一个标识符,在内存中是一块空间,它提供了一个临时存放信息和数据的地方,具有记忆数据的功能。变量是可以改变的,它可以存放不同类型的数据,通常用小写字母或单词作为变量名。
变量具有三个元素:名字、类型 和 值 。
变量的声明与初始化
在Java中存储一个数据,必须将它保存到一个变量中。变量在使用前必须有定义,即有确定的类型和名称。声明变量的格式为:
类型 变量名 [ , 变量名] [ = 初值];
该语句告诉编译器以给定的数据类型和变量名建立的一个变量。
变量有一定的生命周期和作用域。变量的作用域是指允许访问变量的代码范围。按作用域来分,变量可分成局部变量、类成员变量、方法参数、异常处理参数等几类。
在类中声明的变量称为类的成员变量,通常在类开始处声明,可在整个类中使用。在方法或语句块(语句块由两个大括号所定义)中声明的变量称为局部变量。
局部变量在声明时一定要初始化,即赋初值。否则,程序运行时将出错。
成员变量在声明时可以不初始化,程序运行时,系统会自动进行初始化工作,即给成员变量赋初值。
2.4 各数据类型之间的转换
2.4.1 数据类型的自动转换
boolean类型不可转换为其他的数据类型。
整型、字符型、浮点型在混合运算中的自动相互转换,应遵循以下原则:占位数小的类型字段转化为占位数大的类型。
数据类型按占位数大小排序(小 --> 大):
byte → short → (char) → int → long → float → double
多种类型的数据混合运算时,系统首先自动的将所有数据转化为占位数最大的那种数据类型,然后再进行计算。
2.4.2 数据类型的强制转换
占位数大的数据类型转换为占位数小的数据类型时,要加上强制转换符,但可能造成精度降低或溢出,使用时要注意。
当需要把一个整数变成一个字符型数据使用时,也需要将整数类型数据强制转换为字符型数据。
变量类型强制转换的格式为:
(数据类型)数据表达式
2.4.3 涉及byte、short 和 char 类型的运算
Java中涉及byte、short 和 char 类型的运算操作首先会把这些值转换为 int 类型,然后对 int 类型值进行运算,最后得到 int 类型的结果。因此,如果把两个 byte 类型值相加,最后会得到一个 int 类型的结果。
2.5 Java类库中对基本数据类型的对象包装器类
Java对每种基本数据类型都有一个包装器类。
boolean类型对应Boolean类
char类型对应Character类
byte类型对应Byte类
short类型对应Short类
long类型对应Long类
int类型对应Integer类
double类型对应Double类
float类型对应Float类
包装器类为基本数据类型与对应的包装器类对象之间的转换提供了许多方法。
常用的有:
valueOf()//将基本类型转成对应的包装器类对象
xxxValue()//将包装类对象转换成xxx类型基本类型
parseXxx()//将字符串转成xxx类型基本类型
第三章、运算符和表达式
考纲要求:
1、运算符:运算符的分类及相互之间的优先级关系,操作数的类型转换
2、表达式运算:表达式结果的处理
3、表达式语句
学习要点:
1、了解运算符和表达式的概念
2、掌握各种不同类型的运算符和表达式
3、掌握各种运算符的优先级
4、掌握表达式的计算
5、熟悉语句的概念和类型
3.1 概述
Java的运算符代表着特定的运算指令。
按照运算符功能来分,运算符有七种:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符、条件运算符 和 其它运算符。
按照连续操作数的数量来分,有一元运算符、二元运算符 和 三元运算符。
表达式是由常量、变量、对象、方法调用 和 运算符组成的式子。
表达式必须符合一定的规范,才可被系统理解、编译和运行。表达式的值就是对表达式自身运算后得到的结果。
根据运算符的不同,表达式相应地分为以下几类 :算术表达式、关系表达式、逻辑表达式、位运算表达式、赋值表达式、条件表达式等。
3.2 算术运算符和算术表达式
3.2.1 加减运算符
加减运算的运算符号为+、-,是二元运算符,它们的结合性是从左到右。加减运算的操作数是整型或浮点型数据,加减运算符的优先级是5级。
3.2.2 乘、除和求余运算符
乘、除和求余运算的运算符号为*、/、%,都是二元运算符。 *、/、%运算符的结合性是从左到右。乘、除和求余运算的操作元是整型或浮点型数据。 *、/、%运算符的优先级是4级。
3.2.3 自增、自减运算符
自增、自减运算的运算符号为:++、--,都是一元运算符,运算符的优先级是2级。运算符可以放在操作数之前,也可以放在操作数之后,但操作数必须是一个整型或浮点型变量(不能是常量或表达式)。
运算符的作用是使变量的值增1或减1,如:
++x,--x表示在使用x之前,先使x的值加(减)1。
x++,x--表示在使用x之后,使x的值加(减)1。
3.2.4 算术表达式
用算术符号和操作元连接起来的符合Java语法规则的式子,称为算术表达式。例如:x + 2 * y - 30 + 3 * (y+5) - 12 + n + (--n)
3.2.5 算术混合运算的精度
精度从“低”到“高”排列的顺序是:
byte、short、int、long、float、double
Java将运算符两边的操作元的最高精度保留结果的精度,例如:5/2的结果是2,要想得到2.5,必须写成5.0/2或5.0f/2。
注意:byte、short、char型数据之间的运算结果精度是int。例如:byte k=18;那么‘H’ + k;的结果是int型,应当写成:char ch = (char) ('H' + k);
3.3 关系运算符和关系表达式
关系运算符用来比较两个值的关系,关系运算符的运算结果是boolean型数据,当运算符对应的关系成立时,运算结果是true,否则是false。
3.3.1 大小关系运算符
大小关系运算的符号分别是:>、>=、<、<=,都是双目运算符,操作数是数值型的常量、变量或表达式。大小关系运算符的级别是7级。
3.3.2 等与不等关系
等与不等关系运算的符号分别是:“==”、“!=”,都是双目运算符。运算符的级别是8级。
3.3.3 关系表达式
结果为数值型的变量或表达式可以通过关系运算符形成关系表达式。
例如:24>18,(x+y+z)>(30+x)等。
3.4 逻辑运算符和逻辑表达式
逻辑运算用来实现boolean型数据的逻辑”与“、”或“ 和 ”非“ 运算,运算结果是boolean型数据。
3.4.1 逻辑 ”与“ 和 逻辑 ”或“
逻辑 ”与“ 和逻辑 ”或“ 运算的符号是:&&、||,是双目运算符,操作数是boolean型的变量或求值结果是boolean型数据的表达式。
”&&“ 的运算法则是:当2个操作数的值都是true时,运算结果是true,否则是false。”||“ 的运算法则是:当2个操作数的值都是false时,运算结果是false,否则是true。”&&“ 和 ”||“ 的级别分别是12 和13级,结合性是从左到右。
逻辑运算符 ”&&“ 和 ”||“ 也称做短路逻辑运算符
进行op1&&op2运算时,如果op1的值是false,”&&“运算符在运算时不再去计算op2的值,直接就得出op1&&op2的结果是false。
同样在进行op1||op2运算时,当op1的值是true时,”||“运算符在运算时不再去计算op2的值,直接就得出op1||op2的结果是true。
3.4.2 逻辑 ”非“
逻辑 ”非“ 运算的符号是:!,是单目运算符,操作数在左面。当操作数的值是true时,运算结果是false;反之为true。” !“的运算级别是2级,结合性从右到左。
例如:! !x 相当于 !(!x) 。
3.4.3 逻辑表达式
结果为boolean型的变量或表达式可以通过逻辑运算符形成逻辑表达式。
例如:24>18 && 4<0,x != 0 || y != 0。
3.5 位运算符和位运算表达式
位运算都是对整型数据的二进制进行的
3.5.1 ”按位与“ 运算符 ”&“
”&“ 是双目运算符,对两个整型数据 a 、b按位进行运算,运算结果是一个整型数据c。
运算法则是:如果 a、b两个数据对应位都是1,则c的该位是1,否则是0。如果b的精度高于a,那么结果c的精度和b相同。
3.5.2 ”按位或“ 运算符 ”|“
”|“ 是双目运算符。对两个整型数据a、b按位进行运算,运算结果是一个整型数据c。
运算法则是:如果 a、b两个数据对应位都是0,则c的该位是0,否则是1。如果b的精度高于a,那么结果c的精度和b相同。
3.5.3 ”按位非“ 运算符 ”~“
”~“ 是单目运算符。对一个整型数据a按位进行运算,运算结果是一个整型数据c。
运算法则是:如果a对应位是0,则c的该位是1,否则是0。
3.5.4 ”按位异或“ 运算符 ”^“
”^“ 是双目运算符。对两个整型数据a、b按位进行运算,运算结果是一个整型数据c。
运算法则是:如果a、b两个数据对应位相同,则c的该位是0,否则是1。如果b的精度高于a,那么结果c的精度和b相同。
位运算符在操作逻辑型数据时,与逻辑运算符&&、||、!不同的是:位运算要计算完a和b之后再给出运算的结果。
3.5.5 移位运算符
移位运算符用来对二进制位进行移位操作,分为左移位操作和右移位操作。注意,二进制码均为补码。在补码表示中,最高位是符号位,正数的符号位为0,负数的符号位为1。
对正数来说,最高位为0,其余各位代表数值本身(以二进制表示);对负数而言,把该数绝对值的补码按位取反,然后对整个数加1,即得该数的补码。
(1)左移位运算符
左移位运算的符号为:<<,是双目运算符。左移位运算符左面的操作数称作被移位数,右面的操作数称作移位量,操作数必须是整型类型的数据。
假设a是一个被移位的整型数据,n是位移量。
a<<n运算的结果是通过将a的所有位都左移n位,每左移一个位,左边的高阶位上的0或1被移出丢弃,并用0填充右边的低位。
(2)右移位运算符
右移位运算的符号为:>>,是双目运算符。假设a是一个被移位的整型数据,n是位移量。
a>>n运算的结果是通过将a的所有位都右移n位,每右移一个位,右边的低阶位被移出丢弃,并用0或1填充左边的高位,a是正数用0填充,负数时用1填充。正数不断右移位的最后结果一定是0,而负数不断右移位的最后结果是-1。
还有一个逻辑右移运算符:>>>,操作数被右移后,高位都用0填充,无论操作数是正还是负。
3.6 赋值运算符和赋值表达式
赋值运算符:=
赋值运算符是双目运算符,左面的操作数必须是变量,不能是常量或表达式。设x是一个整型变量,y是一个boolean型变量,x=120和y=false都是正确的赋值表达式,赋值运算符的优先级较低,是15级,结合方向从右到左。赋值表达式的值就是”=“左面变量的值。
扩展赋值运算符
运算符 | 用法 | 等价形式 |
---|---|---|
+= | op1 += op2 | op1 = op1 + op2 |
-= | op1 -= op2 | op1 = op1 - op2 |
*= | op1 *= op2 | op1 = op1 * op2 |
/= | op1 /= op2 | op1 = op1 / op2 |
%= | op1 %= op2 | op1 = op1 % op2 |
&= | op1 &= op2 | op1 = op1 & op2 |
|= | op1 |= op2 | op1 = op1 | op2 |
^= | op1 ^= op2 | op1 = op1 ^ op2 |
<<= | op1 <<= op2 | op1 = op1 << op2 |
>>= | op1 >>= op2 | op1 = op1 >> op2 |
>>>= | op1 >>>= op2 | op1 = op1 >>> op2 |
3.7 条件运算符和条件表达式
条件运算符是一个三目运算符,它的符号是:“ ?:”,需要连续3个操作元。
用法如下:op1 ? op2 : op3 (op1为boolean型,op2和op3 是同一数据类型)
3.8 运算符的优先级和复杂表达式
级别 | 运算符 | 结合性 |
---|---|---|
1 | . [] () ; , | --- |
2 | ++ -- ~ ! instanceof | R → L |
3 | new (type) | R → L |
4 | * / % | L → R |
5 | + - | L → R |
6 | << >> >>> | L → R |
7 | < > <= >= | L → R |
8 | == != | L → R |
9 | & | L → R |
10 | ^ | L → R |
11 | | | L → R |
12 | && | L → R |
13 | || | L → R |
14 | ?: | L → R |
15 | = *= /= %= += -= ^= | R → L |
16 | <<= >>= >>>= &= |= | R → L |
3.9 语句
Java里的语句可分为以下5类:
1、方法调用语句
将在第五章介绍类、对象等概念时介绍。
2、表达式语句
一个表达式的最后加上一个分号就构成了一个语句,称作表达式语句。分号是语句不可缺少的部分。
3、复合语句
可以用 “ { ” 和 “ } ” 把一些语句括起来构成复合语句,一个复合语句也称作一个代码块。
4、控制语句
控制语句包括:条件分支语句、循环语句 和 跳转语句。下一章将会介绍到。
5、package语句 和 import语句
package语句 和import语句与类、对象、包有关,将在后续课程中介绍。
第四章、流程控制
考纲要求:
1、条件语句:包括了判断各种条件语句的执行结果,switch语句中表达式类型处理等内容
2、循环语句:包括了对程序中循环体执行次数的判断等内容
3、跳转语句:包括了跳转语句的执行流程判断等内容
学习要点:
1、掌握各种分支语句的使用方法
2、掌握各种循环语句的使用方法
3、掌握各种跳转语句的使用方法
4、掌握各种嵌套结构的使用方法
5、理解递归的概念
4.1 概述
流程控制结构分为三种基本结构:
顺序结构、分支(选择)结构 和 循环结构。
顺序结构 是指命令行顺序执行,即语句的执行顺序和语句的书写顺序一致,这是最常见的一个格式。
分支语句 是一种选择结构,根据条件的值选择不同的执行流程,可以得到不同的结果。分支结构包括条件分支语句(if--else语句)和多分支语句(switch语句)。
循环结构 是指对于一些重复执行的语句,用户指定条件或次数,由机器自动识别执行。循环结构包括条件循环语句(while、do--while语句)和次数循环语句(for语句)等。
4.2 分支(选择)语句
分支语句提供了这样一种控制机制,它根据条件值或表达式值的结果选择执行不同的语句序列,其他与条件值或表达式值不匹配的语句序列则被跳过不执行。
4.2.1 条件分支语句
if语句
if(条件表达式)
s1语句;
这是最简单的单分支结构。条件表达式的值为true,就执行s1语句,否则就忽略s1语句。s1语句可以是复合语句。
if--else语句
if语句通常都与else语句配套使用,形成二分支结构。
if(条件表达式)
s1语句;
else
s2语句;
if后面()内的条件表达式的值必须是boolean型,当条件表达式的值为true,就执行s1语句,忽略else和s2语句;否则,条件表达式的值为false,程序忽略s1语句,执行else后面的s2语句。s1和s2都可以是复合语句。
if--else if语句
程序有时需要根据多条件来选择某一操作,这时就可以使用if--else if语句。if--else if语句是由一个“if”、若干个“else if”、一个“else” 与若干个语句按一定规则构成,其中else部分是可选的。
if (条件表达式1)
s1语句;
else if (条件表达式2)
s2语句;
[else
s3语句;]
注意:else总是与离它最近的if配对使用。
if--else 语句的嵌套
if--else 语句的嵌套表示在一个完整的if--else结构里又包含了其他的控制语句,它的语法格式为:
if (条件表达式)
其他控制语句;
[else
其他控制语句;]
要求:其他控制语句的结构必须完整。
4.2.2 多分支语句switch
switch 语句是多分支的开关语句,它的一般格式定义为:
switch(表达式) {
case 常量值1:语句组1
break;
case 常量值2:语句组2
break;
......
case 常量值n:语句组n
break;
default:语句组n+1
}
switch语句中表达式的值必须是整型或字符型;常量值1到常量值n必须也是整型或字符型。
4.3 循环语句
一个完整的循环结构一般应包括四部分内容:
1、**初始化部分 **:用来设置循环的一些初始条件,计数器清零等。
2、**循环体部分 **:这是反复被执行的一段代码,可以是单语句,也可以是复合语句。
3、迭代部分 :这是在当前循环结束,下一次循环开始时执行的语句,常用来是计数器加1或减1。
4、终止部分 :通常是一个布尔表达式,每一次循环要对该表达式求值,以验证是否满足循环终止条件。
4.3.1 while循环
while语句的一般格式:
while(表达式) {
若干语句
}
while语句由关键字while、括号中一个值为boolean型数据的表达式和若干语句组成,其中的若干条语句称为循环体。
4.3.2 do--while循环
do {
循环体
} while(表达式) ;
4.3.3 for循环
for (表达式1;表达式2;表达式3) {
循环体
}
表达式2 是一个求值为boolean型数据的表达式。
4.4 跳转语句
跳转语句是指用跳转关键字加上分号构成的语句。
Java支持三种跳转关键字:break、continue、return。
4.4.1 break语句
break语句可以用在switch语句中,用于退出switch语句,是程序从switch结构后面的第一条语句开始执行。
还可以在循环语句的循环体中使用break语句。在一个循环中,比如循环50次的循环语句中,如果在某次循环体的执行中执行了break语句,那么整个循环语句就结束。
带标号的break语句
标号是标记程序位置的标识符。它通常用在嵌套循环的内循环中。不带标号的break语句只能跳转到本层循环结构下面的第一条语句上,而带标号的break语句可直接跳出标号所示的层次。
标识符:
...
break 标识符;
lab1:for(int i=0;i<4;i++){
...
for(int j=0;j<4;j++){
...
if(条件){
...
break lab1; //跳出标号标识的层次
...
}
}
}
4.4.2 continue语句
continue语句只能用在循环结构中,它跳过本轮循环中循环体内尚未执行的语句,重新执行循环体的第一条语句,从而开始下一轮循环。
带标号的continue语句
Java也支持带标号的continue语句,它通常用在嵌套循环的内循环中,可以用标号标出你想跳到哪一层语句继续重复执行程序。
标识符:
...
continue 标识符;
4.4.3 return语句
return语句用于方法的返回上,当程序执行到return语句时,终止当前方法的执行,返回到调用这个方法的语句。return语句通常位于一个方法体的最后一行,有带参数和不带参数两种形式,带参数形式的return语句退出该方法并返回一个值。
带参数的return语句格式为:
return 表达式;
不带参数的return语句格式为:
return;
class CircleArea {
final static double PI=3.14159;
public static void main(String args[]) {
double r1=8.0,r2=5.0;
System.out.println("半径为“+r1+”的圆面积="+area(r1));
System.out.println("半径为“+r2+”的圆面积="+area(r2));
static double area(double r) {
return (PI*r*r);
}
}
}
4.5 控制语句的嵌套
在一个循环体内又可包含另一个完整的循环结构,构成多重循环语句。
循环语句与分支语句可相互嵌套,以实现复杂算法。分支语句的任意一个分支都可以嵌套一个完整的循环语句,同样循环体中也可以包含完整的分支语句。
public class Sum1 {
public static void main(String args[]) {
int n=10,sum=0;
while(n>0) {
sum=0;
for(int i=1;i<=n;i++) {
sum+=i;
}
System.out.println("前"+n+"个数的总和为:"+sum);
n--;
}
}
}
class Factors {
public static void main(String[ ] args) {
int n=12;
System.out.print(n+"的因子有:");
for(int k=1;k<=n;k++) {
if(n%k==0)
System.out.print(k+" ");
}
System.out.println("");
}
}
public class Test {
public static void main(String args[]) {
int a,b;
for(a=1,b=1;a<=100;a++) {
if(b>=10) break;
if(b%2==1){
b += 2;
continue;
}
}
System.out.println(a);
}
}
4.6 递归
递归的基本思想是“自己调用自己”。一个使用递归技术的方法将直接或间接地调用自身的方法。利用递归,可以用简单的程序来解决某些复杂的计算问题。
一个递归的问题可分解为:“递归”和“递推”两个阶段。
1、程序控制权反复进入同一个方法,形成递归调用;
2、当满足某一条件后结束递归;
3、程序控制权逐级从方法中返回,形成递推回代。
class FactorialTest {
static long Factorial(int n) {//定义Factorial()方法
if(n==1)
{return 1;}
else
{return n*Factorial(n-1);}
}
public static void main(String a[]) {//main()方法
int n=5;
System.out.println(n+"!="+Factorial(n));
}
}
public class java1 {
public static void main(String[] args) {
int sum=add(10);
System.out.println("1+2+...+9+10="+sum);
}
}
public static int add(int n) {
if(n==1) {
return 1;
}
else {
return n+add(n-1);
}
}
//求1-100的自然数的累加,并打印输出计算结果
public class java1 {
public static void main (String[] args) {
int sum=0;
int i=1;
for(;;) {
if(i<=100)
{sum=sum+i}
else
break;
i++;
}
System.out.println("sum="+sum);
}
}
//计算1-10之间除了5以外的各个自然数的和
public class java1 {
public static void main (String[] args) {
int i=1;
int sum=0;
while(i<=10) {
if(i==5) {
i++;
continue;
}
sum+=i;
i++;
}
System.out.println("sum="+sum);
}
}
第五章、Java的继承、多态、高级类特性和数组
考纲要求:
1、面向对象编程的基本概念和特征:包括面向对象的含义等内容
2、类的基本组成和使用
3、对象的生成、使用和删除:包括构造方法的特点等内容
4、包
5、Java类库的常用类
6、继承、多态和高级特性:包括了继承、接口的概念,抽象类的特点,内部类的使用方法等内容
7、字符串和数组:包括了字符串的使用方法,一维数组、二维数组的定义与数组元素的访问等内容
学习要点:
1、深入理解面向对象编程的概念
2、掌握类的创建和使用
3、掌握对象的创建和使用
4、掌握包的使用
5、掌握字符串的使用
6、掌握继承的概念和实现
7、理解多态的概念和实现
8、熟悉高级类特性
9、了解内部类的概念
10、掌握数组的使用
5.1 Java语言面向对象编程
5.1.1 相关概念
对象
对象是现实世界事物的抽象模型。在软件开发的信息世界中,对象定义为相关数据和方法的集合。
从现实世界事物中抽象出来的对象,一般通过变量描述其状态,通过方法实现其行为。
变量是一种有名称的数据实体,而方法则是和对象相关的函数或过程。
类
Java程序设计的基本单位是类(class),Java的源文件由若干个书写形式相互独立的类构成。
类有两个基本成员:成员变量和(成员)方法。成员变量描述对象的属性,成员方法体现对象的功能。
类就是对象的软件图纸、模板或原型,它定义了同类对象共有的变量和方法。
类和对象二者不太容易区分。一方面,由于软件对象都是现实对象或抽象概念的电子模型,另一方面,经常不加区分地将对象和类统称为“对象”。
Java编程就是设计类,可以采用自定义方式或继承方式设计一个类,然后使用它的实例对象完成具体的功能。
封装
封装是面向对象方法的核心思想之一。它有两个含义:
一是指把对象的属性和行为看成是一个密不可分的整体,将这两者“封装”在一个不可分割的独立单位(即对象)中。
另一层含义指“信息隐蔽”,把不需要让外界知道的信息隐藏起来,只允许使用对象的功能,而尽可能隐蔽对象的功能实现细节。
继承
子类可以继承父类的属性(数据)和功能(操作)。继承是面向对象方法中的重要概念,并且是实现代码重用和提高软件开发效率的重要手段。
多态
多态----程序中允许出现方法重名的现象。
Java中具有方法名称的多态以及和继承有关的多态。
5.1.2 类的声明
类声明定义了类的名字以及其他的属性,说明该类是什么样的一个类。一边来说,类声明可以包含如下3个选项:
1、类的修饰符
2、说明该类的父类
3、说明该类所实现的接口
[类修饰符] class 类名称 [extends 父类名称]
[implements 接口名称列表]
{
变量定义及初始化;
方法定义及方法体;
//类体:其中定义了该类中所有的变量和所有的方法,分别称为成员变量和成员方法。
}
class 是关键字,用来定义类。
1、 类修饰符
类修饰符是下列之一:[public | abstract | final]
public ---- 该关键字声明的类可以在其他的任何类中使用。默认时,该类只能被同一个程序包中其他的类使用。
abstract ---- 抽象类,没有具体对象的概念类,没有具体实现功能,只用于扩展子类。例如:“鸟”,它可以派生出“鸽子”、“燕子”等具体类。
final ---- 最终类,表示该类已经非常具体,没有子类可以扩展。
2、说明一个类的父类
在Java中,除Object类之外,每个类都有一个父类。Object类是Java中唯一没有父类的类,如果某个类没有声明父类,Java就认为它是Object的直接子类。因此,所有其它类都是Object的直接子类或间接子类。
class 类名 extends 父类名{
... //类体
} //其中extends子句认为是直接继承其后的父类
3、说明一个类所实现的接口
接口定义了行为的协议,这些行为可以在处于各个层次的任何类中被实现。一个类要实现接口,可以使用关键字implements,并且在其后面给出由该类实现的接口名表,接口名表是以逗号分隔的多个接口名称。
implements
Interfaces1,Interfaces2, ... ,Interfacesk;
接口可以声明多个方法和常量,但这些方法没有具体实现,这种方法称为抽象方法。
类的名字不能是Java中的关键字,要符合标识符规定,即名字可以由字母、下划线、数字或美元符号组成,并且第一个字符不能是数字。但给类命名时,最好遵守下列习惯:
- 如果类名使用英文字母,那么名字的首字母使用大写字母,如Hello、Time、People等。
- 类名最好容易识别、见名知意。
- 当类名由几个“单词”复合而成时,每个单词的首字母都要大写,如BeijingTime、HelloChina等。
5.1.3 类体的构成
类体内容可以有2种类型的成员:
成员变量:通过变量声明定义的变量,称作成员变量或域,用来表示该类创建的对象的属性。
成员方法:方法是类体的重要成员之一,包括构造方法和成员方法。构造方法是具有特殊地位的方法,使用关键字new调用,供类创建对象时使用,用来给出类所创建的对象的初始状态;而成员方法,可以由类或者类所创建的对象调用,通过调用这些方法体现类或者对象具有的某种功能。
1、成员变量
声明格式为:
[变量修饰符] 变量数据类型 变量名1,变量名2 [=变量初值]...;
变量修饰符:
[public | protected |private] [static] [final]
public、protected、private为访问范围修饰符
static----说明该成员变量是类变量
final----说明该成员变量是常量
成员变量的类型可以是Java中任意的数据类型,包括基本类型、类、接口、数组等。在一个类中的成员变量的名称应该是唯一的。
访问范围修饰符
public:任何其它类、对象只要可以看到这个类的话,那么它就可以存取变量的数据或使用方法。
protected:同一类,同一包可以使用,不同包的类要使用,必须是该类的子类。
private:不允许任何其他类存取和调用。
default:(前边没有修饰字的情况)在同一包中出现的类才可以直接使用它的数据和方法。
类变量
属于类的变量和方法修饰符----static
static 在变量或方法之前,表明它们是属于类的,称为类变量(静态变量)或类方法(静态方法)。若无static修饰,则是实例变量和实例方法。
类变量的生存期不依赖于对象的实例,其它类可以不通过对象实例访问它们,而是可以在它的类的任何对象创建之前使用类名进行访问。
2、成员方法
方法是类的动态属性。对象的行为是由它的方法来实现的。一个对象可通过调用另一个对象的方法来访问该对象。
与类一样,方法也有两个主要部分:方法声明部分 和 方法体。
[方法修饰符] 返回类型 方法名称 (参数1,参数2,...)
[throws exceptionList]
{
...statements;
//方法体:方法的内容
}
方法修饰符:
[public | protected | private]
[static] [final | abstract] [native] [synchronized]
其中,public、protected、private 为访问范围修饰符,使用方法和成员变量的范围范围修饰符一样。
static静态方法
用static声明的方法称为静态方法,静态方法也称为类方法,而非静态方法称为实例方法。
类方法独立于该类的任何对象,其它类不用实例化即可调用它们,即可以使用类名为前缀调用静态方法。
注意:类方法可以调用其它的类方法;
类方法只能访问static变量
类方法不能以任何形式引用this和super。
final最终方法
用final声明的方法称为最终方法,方法被声明为最终方法后,将不能被子类覆盖,即最终方法能被子类继承和使用但不能在子类中修改或重新定义它。这种修饰可以保护一些重要的方法不被修改。
在面向对象编程中,子类可以把父类的方法重新定义,使之具有新功能但又和父类的方法同名、同参数、同返回值,这种情况称为方法覆盖(override)。
abstract抽象方法
用abstract声明的方法称为抽象方法。抽象方法是指没有实现的方法,因为它没有方法体,所以抽象方法不能出现在非抽象类中,只能出现在抽象类和接口当中。
注意:不能同时使用final和abstract修饰同一个方法。
native本地方法
用其他语言编写的方法在Java中称为本地方法。由于native方法的方法体是使用其他语言在程序外部编写的,所以native方法没有方法体。
synchronized同步方法
同步方法用于多线程编程。为避免数据的不一致性,应将方法声明为同步方法,对数据进行加锁,以保证线程的安全。
方法的返回类型
一个方法必须声明其返回类型,如果无返回值,则必须其返回类型为void。
当return语句带有返回值时,它与方法定义的返回类型的关系必须符合如下几种情况之一:
- 当方法声明的返回类型是基本数据类型时,返回值的数据类型必须与返回类型一致;
- 当方法声明的返回类型是一个类时,返回对象的数据类型必须是与方法声明的返回类相同的类或其子类;
- 当方法声明的返回类型是一个接口类型时,返回的对象所属的类必须实现这个接口。
方法名
方法名可以是任何合法的Java标识符
1、方法可以重载
Java支持方法名重载,即多个方法可以共享一个名字。
2、重载的方法不一定返回相同的数据类型,但参数必须有所区别:
- 参数的类型不同。例如,int dt (int x) 和 double dt (String x) 这两个方法的参数的类型不一样。
- 参数的顺序不同。这里是指一个方法有多个不同类型参数的情况,改变参数的顺序也算是一种区分方法。例如,int cp(int a,String b) 和 int cp(String a,int b) 这两个方法的参数顺序不同。
- 参数的个数不同
方法的参数
一个参数是一个方法的变元,它与类的成员变量毫无关系,因此参数名可以和成员变量名相同。如果一个方法的参数名与成员变量名同名,则在这个方法中,参数隐藏了这个成员变量名,也就是说,在方法中出现的这个名字指的是参数名,而不是成员变量名。
方法体内的变量
-
null变量
null是一个“空”变量,用于指代某一个对象,但这个对象没有相应的实例。例如:Stack stack = null ;
-
this变量
this表示的是当前类的当前对象本身,更准确地说,this代表了当前对象的一个引用。
-
super变量
super表示的是当前对象的直接父类对象的引用。所谓直接父类是相对于当前对象的其他“祖先”类而言的。
-
局部变量
在方法体中,可以声明多个变量,它们在该方法内部使用。
5.1.4 包
由于Java编译器为每个类生成一个字节码文件,且文件名与类名相同,因此同名的类有可能发生冲突。为了解决这一问题,Java提供包来管理类名空间。
如同目录是文件的松散的集合一样,包是类和接口的一种松散集合。一般并不要求处于同一个包中的类或者接口之间有明确的联系,如包含、继承等关系,但是由于同一包中的类在默认情况下可以互相访问,所以为了方便编程和管理,通常需要把相关的或在一起协同工作的类和接口放在一个包里。
1、包的创建
通过关键字package声明包语句。package语句作为Java源文件的第一条语句,指明该源文件定义的类所在的包。
package 包名;
如果源程序中省略了package语句,源文件中所定义命名的类被隐含地认为是无名包的一部分,即源文件中定义命名的类在同一个包中,但该包没有名字。
包名可以是一个合法的标识符,也可以是若干个标识符加 “.” 分割而成,如:
package sunrise ;
package sun.com.cn ;
程序如果使用了包语句,例如:
package tom.jiafei ;
那么你的目录结构必须包含有如下的结构:
...\tom\jiafei
源文件编译后得到的全部字节码文件必须拷贝到目录...\tom\jiafei中,而运行程序时必须回到tom\jiafei的上一层目录中。
2、包的使用
在编写源文件时,除了自己编写类外,我们经常需要使用Java提供的许多类,这些类可能在不同的包中。在学习Java语言时,使用已经存在的类,避免一切从头做起,这是面向对象编程的一个重要方面。
使用import语句可以引入包中的类。
在一个Java源文件中可以有多个import语句,它们必须写在package语句(假如有package语句的话)和源文件中类的定义之间。
使用类库中的类
Java为我们提供了大约130多个包,如:
java.lang包 | 基本语言类,程序运行时自动引入 |
---|---|
java.io包 | 所有的输入输出类 |
java.util包 | 实用的数据类型类 |
java.awt包 | 构建图形用户界面(GUI)的类 |
java.applet包 | 实现Java Applet的工具类 |
java.net包 | 实现网络功能的类 |
javax.swing包 | 构建应用程序图形界面的轻量级构件 |
使用import语句引入类库中的类。如:import java.awt.*;
使用自定义包中的类
我们也可以使用import语句引入自定义包中的类。
如:import tom.jiafei.*;
使用无名包中的类
我们也可以使用无名包中的类。假如一个源文件中没有使用包语句,如果一个程序要使用这个源文件生成的类,可以将该类的字节码文件存放在当前程序所在的目录中。
5.1.5 构造方法与对象的创建、使用和清除
1、构造方法
类中有一种特殊方法称作构造方法,类创建对象时需使用构造方法,以便给类所创建的对象一个合理的初始状态。构造方法是一种特殊方法,它的名字必须与它所在的类的名字完全相同,并且不返回任何数据类型,即它是void型,但void必须省略不写。
Java允许一个类中有若干个构造方法,即构造方法的重载,因此这些构造方法的参数必须不同,即是参数的个数不同,或者是参数的类型不同。
2、对象的创建
当使用一个类创建了一个对象时,我们也说给出了这个类的一个实例。创建一个对象包括对象的声明和为对象分配内存空间两个步骤。
对象的声明
类的名字 对象名字;
如:
Rect rectangleOne;
为对象分配内存空间
使用new运算符和类的构造方法为声明的对象分配内存空间,如果类中没有定义构造方法,系统会调用默认的构造方法(默认的构造方法是无参数的),例如上述的Rect类提供了2个构造方法,下面都是合法的创建对象的语句:
rectangleOne = new Rect();
或
rectangleOne = new Rect(10,20);
如果类里定义了一个或多个构造方法,那么Java不提供默认的构造方法。
//如果上述Rect类只提供一个带参数的构造方法,代码:
rectangleOne = new Rect ();
//创建对象是非法的
//正确的创建对象的代码:
rectangleOne = new Rect (10,20);
创建多个不同的对象
一个类通过使用new运算符可以创建多个不同的对象,这些对象将被分配不同的内存空间,因此,改变其中一个对象的状态不会影响其它对象的状态。
例如,我们使用前面的Rect类创建两个对象:rectangleOne、rectangleTwo。
rectangleOne = new Rect (10,20);
rectangleTwo = new Rect (33,66);
//当创建对象rectangleOne时,Rect类中的成员变量sideA、sideB被分配内存空间,并返回一个引用给rectangleOne;
//当再创建一个对象rectangleTwo时,Rect类中的成员变量sideA、sideB再一次被分配内存空间,并返回一个引用给rectangleTwo。
3、对象的使用
对象不仅可以操作自己的变量改变状态,而且还拥有了使用创建它的那个类中的方法的能力,对象通过使用这些方法可以拥有相应的功能。
通过使用运算符“ . ” ,对象可以实现对自己的变量访问和方法的调用。
- 对象操作自己的变量(对象的属性)
- 对象调用类中的方法(对象的功能)
例如:
rectangleOne.sideA=10;
rectangleTwo.sideB=20;
4、对象的清除
对象的清除指释放对象所占的内存。
Java具有“自动垃圾收集”机制,Java的运行环境周期地检测某个实体是否已不再被任何对象所引用,如果发现这样的对象,就释放对象占有的内存。
5.1.6 常用基本类
1、Object类
Object类是Java程序中所有类的直接或间接父类,也是类库中所有类的父类,任何一个类都是由Object类派生出来的,它是继承树上的根节点,所以它含有的属性和方法将被所有的类继承。
如果在类的声明中未声明extends关键字指明其父类,这个类被系统默认为Object的子类。
public class Person
{
...
}
等价于
public class Preson extends Object
{
...
}
Object类以下几个方法可以被系统中的每个类继承
public String toString ()
返回值为代表这个对象信息的字符串,形如:类名@对象的内存地址
在其他类中可以重写toString ()方法,返回对象的详细信息。
public boolean equals (Object obj)
比较当前对象和形参对象是否相同。注意,此处的相同指的是两个对象的引用是否相同,而不是指内容是否相同。例如,x.equals(y),当x和y是同一个对象的引用时返回true,否则返回false。
在其他类中也可以重写equals()方法,例如,String类改写为比较两个字符串对象之间内容值是否相同。
public int hashCode ()
返回一个哈希码值,不同的对象有不同的哈希码值。
public final Class getClass ()
返回一个当前对象在运行期的Class类对象。
protected Object clone ()
生成当前对象的一个复制,并返回这个复制的对象。
protected void finalize ()
这个方法用来把对象从内存中清除,由垃圾收集器自动调用。也可以重写这个方法,在对象被清除时,实现某些相关操作。
2、 Class类
Class类是非常特殊的,它的对象将伴随每个类。当一个类X被编译后,就有一个特殊的对象(Class对象)产生,它隐藏在X. class文件中, Class对象是由编译系统自动生成的。
Class类的最大用途是实现动态性,即在程序执行期间帮助加载新的类。
Class类常用的成员方法:
public static forName (String className)
这个方法是静态方法,所以用Class直接调用。这个方法的形参是一个类名,方法的返回值是形参指示的类的Class对象
例如:
Class t = Class.forName ("java.lang.Thread")
3、String类
Java使用java.lang包中的String类来创建一个字符串变量,因此字符串变量是类类型变量,是一个对象。
1、字符串常量:由双引号括起来的若干个字符
如:“你好”、“1234.987”、“weqweo”。
2、创建字符串对象:使用String类的构造方法创建字符串对象
如:String s;
s = new String(“we are students”);
声明和创建可用一步完成:
String s = new String(“we are students”);
也可以用一个已创建的字符串创建另一个字符串,如:
String tom = String(s);
String类还有两个较常用构造方法:
String(char a[ ]):用一个字符数组 a 创建一个字符串对象,如:
char a[] = {'b','o','y'};
String s = new String(a);
String(char a[],int startIndex,int count):提取字符数组a中的一部分字符创建一个字符串对象,参数startIndex和count分别指定在a中提取字符的起始位置和从该位置开始截取的字符个数,例如:
char a[] = {'s','t','b','u','s','n'};
String s = new String(a,2,3);
3、引用字符串常量的引用赋值给一个字符串变量
如:String s = “Hello”;
4、String类的常用方法:
public int length()
使用String类中的length()方法可以获取一个字符串的长度
public int indexOf(String s)
字符串调用indexOf(String s)方法,从当前字符串的头开始检索字符串s,并返回首次出现s的位置。如果没有检索到字符串s,该方法返回的值是-1。
public int indexOf(String s,int startpoint)
字符串调用indexOf(String s,int startpoint)方法,从当前字符串的startpoint位置处开始检索字符串s,并返回首次出现s的位置。如果没有检索到字符串s,该方法返回的值是-1。
public int lastIndexOf(String s)
字符串调用lastIndexOf(String s)方法,从当前字符串的头开始检索字符串s,并返回最后出现s的位置。如果没有检索到字符串s,该方法返回的值是-1。
public char charAt(int index)
返回字符串中第index个字符
public String replace(char oldChar,char newChar)
在字符串中用newChar字符替换oldChar字符
public void getChars(int start,int end,char c[],int offset)
字符串调用getChars方法,将当前字符串中的一部分字符复制到参数c指定的数组中,将字符串中从位置start到end-1位置上的字符复制的数组c中,并从数组c的offset处开始存放这些字符。需要注意的是,必须保证数组c能容纳下要被复制的字符。
public char[] toCharArray()
字符串对象调用该方法可以创建一个字符数组,该数组的长度与字符串的长度相等,并将字符串对象的全部字符依次复制到该数组中。
public byte[] getBytes()
使用平台默认的字符编码,将字符串对象转化为一个字节数组。
public boolean equals(String s)
比较当前字符串对象的内容是否与参数指定的字符串s的内容相同。
public boolean equalsIgnoreCase(String s)
比较当前字符串对象的内容是否与参数指定的字符串s的内容相同(忽略大小写)
public boolean startsWith(String s)
public boolean endsWith(String s)
字符串对象调用startsWith(String s)方法,判断当前字符串对象的前缀是否是参数指定的字符串s;字符串对象调用endsWith(String s)方法,判断当前字符串对象的后缀是否是参数指定的字符串s;
public String substring(int startpoint)
字符串对象调用该方法获得一个当前字符串的子串,该子串是从当前字符串的startpoint处截取到最后所得到的字符串。
public String substring(int start,int end)
字符串对象调用substring(int start,int end)方法获得一个当前字符串的子串,该子串是从当前字符串的start处截取到end-1处所得到的字符串。
public String toUpperCase()
返回一个字符串为该字符串的大写形式。
public String toLowerCase()
返回一个字符串为该字符串的小写形式。
public String trim()
返回将该字符串去掉开头和结尾空格后的字符串。
4、StringBuffer类
StringBuffer类可以生成一个字符串的可变对象,类似于String类,但它对存储的字符串内容可以任意修改,使用起来比String类更加灵活。它常用的构造方法为:
StringBuffer()
构造一个空StringBuffer对象,初始容量为16个字符
StringBuffer(String str)
构造一个StringBuffer对象,初始内容为字符串str的内容。
//StringBuffer常用方法:
public StringBuffer append (...)
可为该StringBuffer对象添加字符序列,返回添加后的该StringBuffer对象引用,例如:
public StringBuffer append (String str)
public StringBuffer append (StringBuffer sbuf)
public StringBuffer append (char[] str)
public StringBuffer append (char[] str,int offset,int len)
public StringBuffer append (double d)
public StringBuffer append (Object obj)
......
public StringBuffer insert (...)
可以为该StringBuffer对象在指定位置插入字符序列,返回修改后的该StringBuffer对象引用,例如:
public StringBuffer insert (int offset,String str)
public StringBuffer insert (int offset,double d)
......
public StringBuffer delete (int start,int end)
可以删除从start开始到end-1为止的一段字符序列,返回修改后的该StringBuffer对象引用。
public StringBuffer reverse ()
用于将字符序列逆序,返回修改后的该StringBuffer对象引用。
5.1.7 正则表达式
一个正则表达式是含有一些具有特殊意义字符的字符串,这些特殊字符称为正则表达式中的元字符。比如,“\dok”中的\d就是有特殊意义的元字符,代表0到9中的任何一个。一个正则表达式也称为一个模式,字符串“9ok”和“1ok”都是和模式:“\dok”匹配的字符串之一。和一个模式匹配的字符串称为匹配模式字符串,也称为模式匹配字符串。
模式匹配就是检索和指定模式匹配的字符串。Java提供了专门用来进行模式匹配的类,这些类在java.util.regex包中。
正则表达式的作用就是用于字符串的模式匹配。
5.2 继承与多态
5.2.1 继承
继承是一种由已有的类创建新类的机制。利用继承,我们可以先创建一个共有属性的一般类,根据该一般类再创建具有特殊属性的新类,新类继承一般类的状态和行为,并根据需要增加它自己的新的状态和行为。由继承而得到的类称为子类,被继承的类称为父类(超类)。
子类继承父类的成员变量和成员方法作为自己的成员变量和成员方法,就好像它们是在子类中直接声明一样。
父类可以是自己编写的类也可以是java类库中的类。利用继承有利于实现代码的重复使用,子类只需要添加新的功能代码即可。
Java不支持多重继承,即子类只能有一个父类。使用关键字extends来声明一个类是另外一个类的子类,格式如下:
class 子类名 extends 父类名
{
...
}
5.2.2 变量的隐藏
子类重新定义一个与从父类继承来的变量完全相同的变量,称为变量的隐藏。
这里所谓隐藏是指子类拥有了两个相同名字的变量,一个来自继承父类,另一个由自己定义。
在这种情况下,当子类执行继承自父类方法时,处理的是父类的变量,而当子类执行它自己定义的方法或直接使用变量时,所操作的就是它自定义的变量,而把来自继承父类的变量“隐藏”起来了。
5.2.3 方法的覆盖
子类中定义一个方法,并且这个方法的名字、返回类型、参数个数和类型与从父类继承的方法完全相同。子类通过方法的覆盖可以把父类的状态和行为改变为自身的状态和行为。
这时,如果子类想使用父类被覆盖的方法,必须使用关键字super。
需要注意的是:方法覆盖时一定要保证方法的名字、类型、参数个数和类型同父类的某个方法完全相同,只有这样,子类继承的这个方法才被覆盖。如果子类在准备覆盖继承的方法时,参数个数或参数类型与父类的方法不完全相同,那实际上也没有覆盖继承的方法,这时子类就出现两个方法具有相同的名字。
5.2.4 重载方法
方法重载是指一个类中可以有多个方法具有相同的名字,但这些方法的参数必须不同,即或者是参数的个数不同,或者是参数的类型不同。方法的返回类型和参数的名字不参与比较,也就是说,如果两个方法的名字相同,即使返回类型不同,也必须保证参数不同。
构造方法也可以重载,构造方法的重载是指同一个类中定义不同参数的多个构造方法,以完成不同情况下对象的初始化。例如,point类可定义不同的构造方法创建不同的点对象:
point(); | //未初始化坐标 |
---|---|
point(x); | //初始化一个坐标 |
point(x,y); | //初始化两个坐标 |
一个类的若干个构造方法之间可以相互调用。当类中一个构造方法需要调用本类另一个构造方法时,可以使用关键字this,并且这个调用语句应该是该构造方法的第一个可执行语句。
5.2.5 this关键字
this是Java的一个关键字,可以出现在实例方法和构造方法中,但不可以出现在静态方法(static修饰)中。
(1)在构造方法中使用this
this关键字可以出现在类的构造方法中,代表使用该构造方法所创建的对象。
(2)在实例方法中使用this
this关键字可以出现在类的实例方法中,代表使用该方法的当前对象。实例方法可以操作成员变量,当成员变量在实例方法中出现时,默认的格式是:this.成员变量;意思是当前对象的成员变量。
class A{
int x;
void f () {
this.x = 100;
}
}
//通常情况下,可以省略成员变量名字前面的“this.”
类的实例方法也可以调用类的其他方法,调用的默认格式是:this.方法;
一个方法调用另一个方法时同样可以省略方法名字前面的“this.”。
5.2.6 super关键字
super关键字有两种用法:
(1)使用super调用父类的构造方法
子类不继承父类的构造方法,因此,子类如果想直接使用父类的构造方法,必须在子类的构造方法中使用关键字super来表示,而且super必须是子类构造方法中的第一条语句。
(2)使用super操作被隐藏的成员变量和方法
当子类中定义了一个变量或者一个方法,并且这个变量的类型、名字以及这个方法的名字、返回类型、参数个数和类型和父类的某个变量或某个方法完全相同时,子类从父类继承的变量将被隐藏、方法将被覆盖。如果我们在子类中想使用被子类隐藏的成员变量或被子类覆盖的成员方法就需要使用关键字super。
5.2.7 多态性
多态性是指在程序中同一个符号在不同的情况下具有不同解释的现象。多态使程序简洁,为程序员带来很大便利。
多态性的实现有三种方式:覆盖、重载、引用
(1)覆盖实现多态性
通过子类对继承父类方法的重定义来实现。使用时注意:在子类重定义父类方法时,要求与父类中方法的原型(参数个数、类型、顺序)完全相同。
由于此时这些方法是存在不同的类层次结构中,在调用方法时只需要指明是调用哪个类(或对象)的方法,就很容易把它们区分开来。
(2)重载实现多态性
由于重载发生在同一个类中,不能再用类名或对象名来区分不同的方法了,所以在重载中采用的区分方法是使用不同的形式参数表,包括形式参数的个数不同、类型不同或顺序的不同。
(3)引用实现多态性
继承层次结构中的子类对象可以视为父类的对象,这样就可以将子类对象赋给父类变量。
然而,父类对象并不是其任何子类的对象,即不能将父类对象赋给子类引用。
5.3 高级类特性
5.3.1 static关键字
关键字static可用来修饰:
数据。表示所修饰的数据属于类共享的变量或常量。
方法。表示所修饰的方法属于整个类的。
代码块。表示所修饰的代码块属于该类,且只执行一次。
类。表示特指静态内部类。
5.3.2 final关键字
final有三种使用方法:
- final在类之前,表示该类不能被继承。
- final在方法之前,防止该方法被覆盖。
- final在变量之前,定义一个变量。
5.3.3 枚举类型
枚举类型是种特殊的类,通常是一组常量的集合。枚举数据是一些特定的标识符,标识符代表什么含义,完全由程序员决定。数据枚举的顺序规定了枚举数据的序号从0开始,依次递增。
JDK5.0引入了一个新的关键字enum表示枚举类型。定义一个枚举类型很简单,下面是定义一个枚举类型的格式。
//枚举的基本定义格式为:
枚举类型修饰词列表 enum 枚举类型名
{
枚举常量列表;
}
如:
public enum Season
{
春季,夏季,秋季,冬季;
}
枚举Season定义后,有四个值,依次为Season.春季;Season.夏季;Season.秋季;Season.冬季;
5.3.4 抽象类
在客观世界里,许多概念是抽象对象,这种概念的类没有实例。不能实例化的类称为抽象类,在定义时用关键字abstract修饰,例如:
abstract class A
{
......
}
抽象类不能用new运算符直接创建对象,因此它必须作为其它类的父类产生子类,由子类创建对象,这与final类正好相反。
抽象类可以定义一个统一的编程接口,使其子类表现出共同的行为,但各自的细节是不同的。
用abstract来修饰一个方法时,该方法叫做抽象方法。
抽象方法是一种只有方法的声明,而没有方法体,且用分号“ ; ” 结尾的特殊方法。
抽象类定义被所有子类共用的抽象方法,而实现细节由子类完成。
抽象类必须被继承,抽象方法必须被重写以实现具体意义。
抽象方法只需声明,而不需实现。定义了抽象方法的类必须是抽象类。
抽象类里可以有非抽象方法,但是抽象方法只能存在于抽象类里。
5.3.5 接口
Java不支持多继承性,即一个类只能有一个父类。单继承性使得Java简单,易于管理程序。为了克服单继承的缺点,Java使用了接口,一个类可以实行多个接口。
使用关键字interface来定义一个接口。接口的定义和类的定义很相似,分为接口的声明和接口体。
(1)接口的声明
我们曾使用关键字class来声明类,接口通过使用关键字interface来声明,格式:
[修饰符] interface 接口名 [extends 父接口名]
{
接口体;
}
接口体中只能包含常量定义和抽象方法定义两部分。
(2)接口的实现
一个类通过使用关键字implements声明自己实现的一个或多个接口。如果实现多个接口,用逗号隔开接口名,如:
class A implements Printable,Addable
如果一个类实现某个接口,那么这个类必须实现该接口的所有方法,即为这些方法提供方法体。类实现的接口方法以及接口中的常量可以被类的对象调用。
要注意的是,接口中的方法被默认是public和abstract的,接口在声明方法时可以省略方法前面的public和abstract关键字,但是,类在实现接口方法时,一定要用public来修饰。
如果父类实现了某个接口,则其子类也就自然实现这个接口。接口也可以被继承,即可以通过关键字extends声明一个接口是另一个接口的子接口。
(3)接口作为类型的使用
接口除了被继承和实现之外,还可以作为一种类型来使用。定义了一个接口,就是定义了一个新的引用数据类型。在可以使用类型的名字(如变量声明、方法参数声明等)的地方,都可使用这个接口名。只要实现了某个接口的类的对象,都可以声明为该接口类型,这样就可以通过声明的引用类型变量去访问所实现接口中的方法。
(4)接口与abstract类的比较
接口和abstract类都可以有abstract方法。
接口中只可以有常量,不能有变量;而abstract类中既可以有常量也可以有变量。
abstract类中可以有非abstract方法,但是接口不可以。
5.4 内部类
类可以有两种重要的成员:成员变量和方法,类还可以有一种成员:内部类。Java支持在一个类中声明另一个类,这样的类称为内部类(也叫嵌套类),而包含内部类的类称为内部类的外部类。内部类和类中声明的成员方法或成员变量一样,一个外部类把内部类看做是自己的成员,可以使用abstract、private等修饰。外部类的成员变量在内部类中仍然有效,内部类中的方法也可以调用外部类中的方法。内部类的类体中不可以声明静态变量和静态方法。外部类可以用内部类声明对象,作为外部类的成员。内部类不能与外部类同名。内部类也可作为其它类的成员。
内部类的声明格式如下:
[修饰符] class outerClass {
...
[修饰符] class innerClass{
...
}
...
}
有两种方法来声明内部类:
(1)可在外部类中(或外部类的方法中)声明内部类,并在该外部类的内部多次使用。
(2)用new操作符后声明匿名内部类,并立即创建一个对象。
通常,内部类用在图形界面程序的事件处理中。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」