一、标识符和关键字

  1. 用来标识类名、接口名、变量名、方法名、数组名、包名的有效字符序列称为标识符。简单点说,是程序开发者在Java程序中自己起的名字。Java的标识符只能由字母、下划线、美元符号和数字组成,合法标识符的规则如下:
  • 标识符由字母、下划线、美元符号和数字组成,长度不受限制;
  • 标识符的第一个字符不能是数字字符,可以是字母、下划线、美元符号;
  • 标识符不能是Java语言的关键字;
  • 标识符不能是true、false和null等Java预定义的文字值;
  • 标识符不能是Java类库中已使用的名字。

⚠ 注意: Java使用Unicode字符集,字母并不限于英文字母,
而是Unicode字符集支持的任意语言的文字,包括汉字。

1
2
3
4
5
6
// 合法标识符的例子:
Identifier、user_name、$change、_password、猴子、马zida。
// 非法标识符的例子:
2sun //以数字2开头
class //是Java关键字
#myname //含有其它字符#
  1. 关键字是已经被Java语言自身使用的字符序列,在Java程序中具有特定的意义与作用,不能在Java程序中将关键字用作标识符。下面这张表列出了Java语言的53个关键字:

Java中的关键字

二、基本数据类型

Java的变量和其它语言的变量一样,都是用于保存值。变量所保存的值可以被改变,所以称为变量。变量有自己的名称(变量名)和类型(数据类型)。变量在使用前必须先使用数据类型进行声明,在声明的同时可以赋给初值,如

1
2
int i;     
double x = 10.6; // 声明的同时赋初值

Java有8种基本数据类型,分别是boolean、byte、short、char、int、long、float、double。这8种类型可分为布尔类型、整数类型、字符类型、浮点类型这四类,如下所示:
Java基本数据类型

1. 布尔类型:boolean

用关键字boolean声明变量;只能取两个值:true,false

1
2
// 例:
boolean on = true, off = false, flag;

⚠ 注意: Java的布尔类型只能用true表示真值,用false表示假值,不允许在数值类型和布尔类型之间转换。

2. 整数类型:byte、short、int、long

(1) int型

用关键字int声明变量; 取值可以是十进制数(如123)、八进制数(以0为前缀,如077)、十六进制数(以0x为前缀,如 0x3abc);

1
2
3
// 例:
int a, b, c;
int x = 2, y = 046, z = 0x1b4d;

⚠ 注意:Java的整数类型都是有符号的,没有无符号整数,整数在没有后缀的情况下默认是int型。

(2) byte型

用关键字byte声明变量; 取值为byte型范围内的整数,可以是十进制、八进制、十六进制。可用强制类型转换来强调一个整数是byte型,如(byte)-12, (byte)27。尽管12和(byte)-12的值相同,但在内存中的表示不一样,12是四个字节的int型,而(byte)-12是一个字节的byte型。
在byte型取值范围内的整数可以直接赋值给byte型变量,如:

1
byte x = -12, tom = 28; 

而超出byte型取值范围的整数,必须强制转换后才能给byte型变量赋值,如:

1
byte y = (byte)234, z = (byte)-197; 

(3) short型

用关键字short声明变量;取值为short型范围内的整数,可以是十进制、八进制、十六进制。可用强制转换来强调一个整数是short型,如(short)-12, (short)27。强制转换后,(short)-12和 (short)27变成两个字节的整型数。
与byte型类似,在short型取值范围内的整数可以直接赋值给short型变量,而超出short型取值范围的整数,必须强制转换后才能给byte型变量赋值。

(4) long型

用关键字long声明变量;用带后缀L或l的整数来表示long型整数,可以是十进制,如108L;八进制,如0712L;十六进制,如0x3aBcl。

1
2
例:
long width = 12L, height = 2005l;

3. 字符型:char

用关键字char声明的一个变量,分配两个字节内存,没有符号位,不存在负的char(相当于无符号整型);
取值为用英文单引号括起来的一个Unicode字符,如‘A’、‘b’、‘?’、‘9’、‘好’、‘\t’等。

⚠ 注意:一个字符的值就是该字符的Unicode编码。
一个字符的Unicode编码是该字符在Unicode表中的位置值(ASCII编码也一样),Unicode字符表的前128个字符正好是ASCII字符。

转义字符:有些字符不能通过键盘输入或者用于表示特殊的功能,就需要使用转义字符。
例:‘\n’(换行)、‘\b’(退格)、‘\t’(水平制表)、‘\’’(单引号)、‘\’’’(双引号)、‘\’(反斜线)、‘\r’(回车)、‘\f’(走纸换页)等。
十六进制转义字符:用一个字符的Unicode编码的十六进制数表示该字符,格式为:‘\u****’,如‘\u0041’表示字符A,‘\u0061’表示字符a。

可以把字符的值当作整数使用,无需强制转换,如字符‘A’的值就是整数65(它的Unicode编码值),则int m = ‘A’,相当于把整数65赋值给int型变量m。如果一个整型数是一个Unicode编码,那么这个整数可以直接作为Unicode字符使用,如char n = 65,相当于把字符‘A’赋值给cha型变量n。

4. 浮点类型:float、double

如果数值中包含小数点、指数(e),或者有字母后缀f/F或d/D,则为浮点数。

(1) float型(单精度浮点型)

用关键字float声明变量,有8位有效数字;任意数值(包括整型数) 加后缀F或f就成为float型,而且后缀不能省略;
例:453.543f,21345.5F,231.0f,100F,2e40f(科学记数法)。

(2) double型(双精度浮点型)

用关键字double声明变量,有16位有效数字;浮点数在无后缀的情况下默认是double型,任意数值(包括整型数)加后缀D或d就成为double型。

三、数据类型转换

1. 数据类型的级别从低到高依次是

byte short char int long float double

2. 数据类型的转换规则

当把低级别类型的值转换成高级别类型的值时,类型转换可以自动完成,不需要强制转换。如下例:

1
2
3
float x = 100;  //赋值后x的值变为100.0。
int x = 50;
float y = x; //赋值后y的值为50.0。

当把高级别类型的值转换成低级别类型的值时,必须使用强制类型转换。
转换格式:(类型名)要转换的值;

1
2
3
4
如:
int x = (int)34.89;
long y = (long)56.98f;
int z = (int)1999L;

转换后,x、y、z的值分别为34、56、1999。

当把int型整数赋值给byte、short和char型变量时,如果不超出该类型的取值范围,可以直接赋值,如:

1
byte a = 100;

否则必须强制转换,如:

1
2
byte a = (byte)128;    //转换后a的值为-128
byte b = (byte)(-129); //转换后b的值127

四、数据的输入与输出

1. 输出基本类型的数据

可以使用System.out.println()或System.out.print()输出字符串、变量、常量、表达式的值。前者输出后换行,后者不换行。可以使用符号“+”将变量、常量或者表达式与一个字符串连接后一起输出。例如,m和sum的值分别是10和100,则:

1
2
System.out.println(m + "个数的和为" + sum);   // 输出:10个数的和为100
System.out.print(123 + "大于"+ 122); // 输出:123大于122

⚠ 注意:只要在“+”号的前后有字符串,执行的就是连接操作,否则执行普通的加法运算。

JDK1.5新增了类似C语言printf函数的输出方法:System.out.printf("格式控制部分",表达式1,表达式2,…表达式n);
格式控制部分由格式符号%d、%c、%f、%s和普通的字符组成。普通字符原样输出,格式符号用来控制输出格式。

  • %d:输出int类型数据值;
  • %md:输出的int型数据占m列;
  • %c:输出char型数据;
  • %s:输出字符串数据。
  • %f:输出浮点型数据,小数保留6位,不够的话补0;
  • %m.nf:输出的浮点型数据占m列,小数保留n位。
1
2
3
4
// 例如:
System.out.printf("整数n的值是%d", n); //若n的值是10,则输出为:整数n的值是10
System.out.printf("字符x的值是%c", x); //若x的值是字符‘A’,则输出为:字符x的值是‘A’
System.out.printf("浮点数的值是%f", 10.3); //输出为:浮点数的值是10.300000
  1. 输入基本类型的数据
    使用Scanner类的对象执行输入,先创建对象:Scanner reader = new Scanner(System.in);
    然后通过reader对象分别调用next()、nextLine()、nextBoolean()、 nextByte()、 nextShort()、 nextInt()、nextLong()、nextFloat()、nextDouble()等方法从终端读入一个字符串(遇到空格或回车符结束)、一行字符串(遇到回车符才结束)、一个boolean型数据、一个byte型数据、一个short型数据、一个int型数据、一个long型数据、一个float型数据、一个double()型数据。要读入多个数据,就要多次调用nextXXX()方法。
    为了正确的调用nextXXX()方法,可以先调用hasNextXXX()方法判断将要读入的数据是否为期望的数据类型,然后再调用相应的nextXXX()方法读取数据。hasNextXXX()方法与nextXXX()方法相对应,如hasNextBoolean()、hasNextByte()、hasNextFloat()、hasNext()、hasNextLine()…等。

⚠ 注意:字符类型没有对应的nextXXX()方法,可以先调用next()或nextLine()方法将控制台的输入按字符串读入,则返回一个String对象,然后调用String类的char charAt(int index)方法提取指定位置的字符,如charAt(0)提取的是第一个字符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in); // 创建从控制台读取数据的流对象

System.out.print("请输入int型整数:");
if (scan.hasNextInt()) { // 判断当前将要读入的数据是否为int型整数
int i = scan.nextInt(); //读入一个int型整数
System.out.println("读入的整数为:" + i);
}
else {
System.out.println("输入的数据不是int型整数!");
}

System.out.print("请输入字符:");
if (scan.hasNext()) { // 判断当前是否有输入数据
String s = scan.next(); //按字符串读入当前的输入数据
char c = s. charAt(0);
System.out.println("读入的字符为:" + c);
}
else{
System.out.println("还没有输入数据!");
}

scan.close();
}
}

五、运算符

运算符具有优先级结合性这两个属性

运算符的优先级

所谓优先级,就是当多个运算符出现在同一个表达式时,先执行哪个运算符。Java语言会比较各个运算符的优先级,按照优先级从高到低的顺序执行。例如,在表达式2+36-7中,运算符的优先级最高,因此先计算3*6,然后再执行其它运算。运算符的优先级总共有14级,从1级到14级是逐级降低的。

运算符的结合性

所谓结合性,就是当一个表达式中出现若干个连续相邻的优先级相同的运算符时,先执行哪个运算符,先执行左边的叫左结合,先执行右边的叫右结合。例如,若#是一个运算符,有表达式a#b#c,如果#是左结合的,那么该表达式被解析为(a#b)#c,如果#是右结合的,那么该表达式将被解析为a#(b#c)。比如,表达式a*b/c,和/的优先级相同,结合性都是从左到右,所以先算,然后算/。

  • 单目运算符:只有一个操作数的运算符,比如x++。
  • 双目运算符: 有两个操作数的运算符,比如x+y。
  • 三目运算符:有三个操作数的运算符,比如a>b?1:0。

1. 算术运算符

  • (1) +, -

    当作为双目运算符时,+是加法运算符,-是减法运算符,结合性从左到右,优先级是4级。当作为单目运算符时,+是正号运算符,-是负号运算符,结合性从右到左,优先级是2级,正号运算符保持操作数的正负不变,负号操作符逆转操作数的正负。
  • (2) *, /, %

    双目运算符,*是乘法运算符,/是除法运算符,%是求余运算符,结合性从左到右,优先级是3级。两个整数的除法运算得到的结果也是整数,舍去余数。求余运算符的操作数可以是整数或浮点数,整数的运算规则:a%b=a-(a/b)b,浮点数的运算规则:a%b=a-qb, q=int(a/b);
  • (3) ++, –

    单目运算符,++是自增运算符,将变量自身加1,–是自减运算符,将变量自身减1。操作数必须是变量,不能是常量或表达式。结合性从右向左,优先级是2级。当出现在表达式中时,有前置(x和–x )或后置(x和 x–)两种情况,前置是先执行自增或自减运算,再将该操作数用于表达式计算;后置则相反,先将该操作数用于表达式计算,再执行自增或自减运算。
  • (4) 算术运算的精度

    算术运算符能接受的操作数的最低类型是int型,凡是低于int型的操作数都会首先被提升到int型。此外,若两个操作数的类型不同,则会将较低的操作数类型转换为较高的操作数类型。

2. 关系运算符

  • (1) >, >=, <, <=

    双目运算符,将两个操作数的大小进行比较,大小关系成立的话结果为true,否则为false。>表示大于关系,>=表示大于等于关系,<表示小于关系,<=表示小于等于关系。结合性从左到右,优先级是第6级。
  • (2) ==, !=

    双目运算符,==运算符比较两个操作数是否相等,!=运算符比较两个操作数是否不相等,成立的话结果为true,否则为false。结合性从左到右,优先级是7级。

3. 逻辑运算符

  • (1) &&, ||, &, |

    双目运算符,&&和&是逻辑与运算符,前者具有短路运算功能,后者没有。||和|是逻辑或运算符,前者具有短路运算功能,后者没有。短路运算功能就是如果左边的逻辑运算已经能够判断出最终结果,则不再继续往右执行。结合性都是从左到右,&&的优先级11级,||是12级。
  • (2) !

    单目运算符,逻辑非运算符,结合性从右到左,优先级是2级。

4. 移位运算符

双目运算符,优先级是5级,结合性是从左到右,两个操作数都必须是整数类型(包括char型)。操作数低于int型的,会先提升到int型,若有一个操作数是long型则都提升到long型。提升规则为:正数的高位用0填充,负数用1填充。左操作数是被移位的数,右操作数是移位量,不超过左操作数的位长度,超出后则对右操作数执行取余运算:n%32(int型)或n%64(long型)。

  • (1) <<

    左移运算符:高位移出,低位补0。相当于乘2。如:a<<5是把a左移5位。
  • (2) >>

    右移运算符:低位移出,高位用符号位填充。相当于除2。如:a>>5是把a右移5位。
  • (3) >>>(无符号右移)

    无符号右移运算符:低位移出,高位用0填充。如:a>>5是把a无符号右移5位。

5. 位运算符

操作数低于int型的要提升至int型。

  • (1) &

    按位与。双目运算符,结合性从左到右,优先级是第8级。
  • (2) |

    按位或,双目运算符,结合性从左到右,优先级是第8级。
  • (3) ^

    按位异或,双目运算符,结合性从左到右,优先级是第8级。
  • (4) ~

    按位取反,单目运算符,结合性从右到左,优先级是2级。

⚠ 注意: &和|既可以做逻辑运算符,也可以做位运算符。
具体做什么,取决于操作数。如果操作数是布尔型,则是逻辑运算符,如果是整型,则是位运算符。

6. 条件运算符:op1?op2:op3

三目运算符,结合性从右到左,优先级13级。例:(x>0)?5:0表示,如果x>0成立则该表达式的值为5,否则为0。

7. instanceof 运算符

双目运算符,左操作数是一个对象,右操作数是一个类型。当左边的对象属于右边的类型时,结果是true,否则是false。例: A a = new A();
boolean b = a instanceof A;

8. 赋值运算符:=

双目运算符,左操作数必须是变量,结合性从右到左,优先级是14级。赋值运算符的运算结果是左操作数被赋予的值。如果赋值运算符两边的类型不同,需要进行类型转换:若左操作数的类型高于右边运算结果的类型,则转换可以自动完成,不需要强制转换,否则必须将右边运算结果的类型强制转换为左操作数的类型。

9. 复合赋值运算符: +=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>=

双目运算符,左操作数必须是变量。左操作数先和右操作数执行相应的运算,然后再赋值给左操作数。结合性从右到左,优先级是14级。复合赋值运算符的运算结果同样是是左操作数被赋予的值。注意:当复合赋值运算符的左右两边的类型不同时,不需要强制类型转换。

六、表达式和语句

1. 表达式

由运算符和操作数组成的符合Java语法规则的式子称为表达式,执行指定的运算并返回确定的值,如int x = a+b*c+5。表达式必须要包含赋值运算,x++也算表达式,因为隐含了赋值运算。判断是否为表达式很简单,如果在式子后面加上分号构成合法语句,那么就是表达式。

2. 语句

  • 表达式语句:一个表达式末尾加上分号“;”
  • 方法调用语句:如reader.nextInt();
  • 复合语句:用一对花括号“{”和“}”把若干语句括起来构成复合语句
  • 控制语句:条件语句,循环语句,跳转语句
  • package语句和 import语句
  • 单独一个分号也是一条语句,称为空语句

上机作业:
从键盘输入任意一个英文字母,大写的转成小写的然后输出,小写的转成大写的然后输出。自己写程序实现大小写字母转换,不允许使用Java类库转换大小写字母。
提示:
(1) 大写字母和小写字母相差一个固定的值

(2) 用Character的静态方法isUpperCase(char ch)判断是否大写字母,isLowerCase(char ch)判断是否小写字母,

如:

1
2
boolean a = Character. isUpperCase(‘A’);     
boolean b = Character. isLowerCase(‘A’);

则a的值为true,b的值为false。

程序大致结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Scanner;

public class xxxxx{
public static void main(String[] args) {
System.out.print("请输入字符:");

Scanner reader = new Scanner(System.in);
String str = reader.next();
char c = str. charAt(0);

/* 判断大小写,然后转换 */
.......
}

七、选择结构

if条件语句

(1) if语句

形式:

1
2
3
if(关系表达式) {
...
}

如果圆括号内的关系表达式成立,则执行花括号内的代码块,否则不执行。

例:

1
2
3
if(x > 0) {
x++;
}

(2)if-else语句

形式:

1
2
3
4
5
6
if(关系表达式) {
...
}
else{
...
}

如果圆括号内的关系表达式成立,则执行if分支的代码块,否则执行else分支的代码块。

例:

1
2
3
4
5
6
if(x>0) {
x++;
}
else {
x--;
}

(3) if-else if语句

形式:

1
2
3
4
5
6
7
8
9
10
11
if(关系表达式1) {
...
}
else if(关系表达式2) {
...
}
...
[else{
...
}]
// (最后的else分支可以没有)

从if分支开始依次判断,哪个分支的条件成立就执行哪个分支的代码块,否则接着判断下一个分支。前面分支的条件均不成立时,如果有else分支,就执行else分支的代码块。执行了任何一个分支的代码块后就退出,不再判断其它分支的条件。如果没有else分支,有可能没有一个分支会被执行。

(4) if条件语句的嵌套

在if语句的分支里面,可以嵌套if语句

1
2
3
4
5
6
7
8
9
10
11
if(关系表达式1){
if(关系表达式 2){
...
}
else {
...
}
}
else{
...
}

switch语句

1
2
3
4
5
6
7
8
9
10
11
12
switch(表达式) {
case 目标值1
若干语句
break;
case 目标值2
若干语句
break;
......
default:
若干语句
break;
}
  • switch语句将表达式的值依次与每个case的目标值进行比较,与哪个case的目标值匹配上就执行该case的语句块。
  • 每个case语句块的最后一条语句通常是break语句,用于退出switch结构。
  • 如果没有break语句,则执行完当前case的语句块后,会接着执行下一个case的语句块。
  • 注意:switch表达式一旦与某个case的目标值匹配上,就不会再与其它case的目标值进行匹配,而是从当前匹配位置开始依次执行后面的语句,直到遇到-break语句或者执行完了所有的语句。
  • 找不到匹配的case目标值时,会执行default语句块。
  • default不是必须有的,default的位置可以是任意的,不是必须在最后。
  • switch表达式的类型可以是byte、short、char、int、enum、String。

八、循环结构

1. while循环

1
2
3
while(关系表达式){
….
}

先判断关系表达式是否成立,如果成立则执行花括号内的语句块,然后依此循环,直到关系表达式不成立,while循环结束。

例:

1
2
3
4
while(num > 5) {                                     //条件判断
System.out.println("num = " + m); //代码块
num--; //条件改变
}

2. do-while循环

1
2
3
do{
...
}while(关系表达式);

先执行花括号内的语句块,然后判断圆括号内的关系表达式是否成立,成立的话继续执行,否则循环终止。

例:

1
2
3
4
do{
System.out.println("num = " + m); //代码块
num--; //条件改变
}while(num > 5); //条件判断

3. for 循环

1
2
3
for(初始化表达式; 条件表达式; 条件改变表达式){
...
}

⚠ 注意: for语句头部的三个表达式都是可选项,都可以没有。

  • 第一步:执行初始化表达式;
  • 第二步:判断条件表达式是否成立,如果成立执行第三步,否则退出循环;
  • 第三步:执行花括号内的for语句块;
  • 第四步:执行条件改变表达式,然后返回第二步;

例:

1
2
3
for(int i = 0  i < num; i++) {	        //条件初始化;  条件判断;  条件改变
System.out.println("执行循环"); //代码块
}

4. 循环的嵌套

循环的内部可以再嵌套循环。如:

1
2
3
4
5
6
7
8
9
10
11
12
for(int i = 0  i < num; i++) {
for(int j = 0; j < num; j ++) {
System.out.println("i = " + i + " j = " + j);
}
}

while(num > 0){
for(for(int i = 0; i < num; i++) {
System.out.println("i = " + i);
}
num--;
}

5. 跳转语句

break: 跳出switch语句和循环语句;

continue:跳过循环体中的剩余语句,继续往下执行。

上机作业:
用循环语句打印九九乘法表,注意行列对齐。

九、Java的编程风格与注释

十、数组

数组是相同类型的数据按顺序组成的复合数据类型,通过数组名加下标来访问数组中的数据。Java数组的下标从0开始。

1. 声明数组

声明一维数组有下列两种格式:

1
2
数组元素的类型   数组名[];       例如:float  boy[]; 
数组元素的类型 []数组名; 例如:float []boy;

一维数组的逻辑结构如同数学中的向量,数组的每个元素对应向量的一个分量。

声明二维数组有下列两种格式:

1
2
数组元素的类型   数组名[][];     例如:int  mytwo[][]; 
数组元素的类型 [][]数组名; 例如:int [][]mytwo;

二维数组的逻辑结构如同数学中的矩阵或者方阵,第1维是行,第2维是列。数组的每个元素对应矩阵的一个元素。

声明更高维的数组与此类似,比如:

1
2
三维数组:int   mythree[][][];   或int   [][][]mythree; 
四维数组:int myfour[][][][]; 或int [][][][]myfour;

三维数组的逻辑结构如同三阶魔方这种立方体。因为现实世界是三维的,所以更高维数组是抽象的产物。

2. 创建数组

声明数组仅仅是声明了一个数组变量(确定了数组名和数组元素的类型),在使用数组前还必须先创建数组。创建数组的语法格式如下:
数组变量(数组名) = new 数组元素的类型[数组元素的个数];

例如:

1
2
float  boy[]; 
boy = new float[4];

声明数组和创建数组可以一起完成:

1
2
float boy[] = new float[4]; 
int mytwo[][] = new int[3][4];

3. 数组元素的使用

  • 一维数组通过下标访问数组的元素,如boy[0],boy[1]。
    • 数组的下标从0开始,最大值是数组长度减1。若数组有7个元素,则下标到6为止,超过6将会引发异常。
  • 二维数组也通过下标符访问元素,如a[0][1],a[1][2]。
    • 下标也是从0开始,每一维的下标不超过该维的长度减1。
  • 更高维的数组依此类推,比如访问三维数组的元素a[0][2][5]。
    • 每一维的下标不超过该维的长度减1。

4. 数组的初始化

在声明数组的同时可以给数组元素一个初始值,如:
float boy[] = {21.3f, 23.89f, 2.0f, 23f, 778.98f};
这种情况在初始化的同时就创建了数组,不需要显式的用new操作符创建数组。
也可以在创建数组的同时初始化,如:
float boy[] = new float[] {21.3f, 23.89f, 2.0f, 23f, 778.98f };
此时方括号中不能有值,数组的长度由初值列表的长度决定。
二维数组的初始化,可以有三种形式。如下所示,声明并初始化一个2行3列的二维数组:

1
2
3
4
5
int a[][] = {{1, 3, 5}, {5, 9, 10}}; //{1, 3, 5}是数组第1行,而{5, 9, 10}是数组第2行 
int a[][] = new int[][]{{6, 5, 1}, {9, 7, 2}}; //{6, 5, 1}和{9, 7, 2}分别是数组第1行和第2行
int a[][] = new int[2][3];
a[0] = new int[] {6, 54, 71}; //数组第1行
a[1] = new int[] {1,5,7}; //数组第2行

在创建数组时,如果没有对数组初始化,则系统会执行默认的初始化,具体规则为:

  • 数值类型的数组在创建后,赋默认值0/0L(整型和char型)或0.0D/0.0F(浮点型);
  • 引用类型的数组在创建之后,赋默认值null;
  • boolean类型的数组默认初值为false。

5. length的使用

对于一维数组,“数组名.length”的值就是数组中元素的个数。对于多维数组,“数组名.length”是它的第一维的长度。例如:

1
2
float []a = new float[12];
int [][]b = new int[3][6];

a.length的值12,b.length的值是3。想得到数组b的另一维的长度,则b[0].length、b[1].length、b[2].length的值都是6

6. 数组的引用

数组名是变量,可以赋值。例如:

1
2
int [] a = {1, 2, 3}, []b = {4,5};
a = b;

执行赋值语句a = b后,数组变量a和b都指向同一个数组{4, 5},a[0] = 3是把4的值改为3。

7. for each循环

Java除了提供普通的for循环外,还提供for each循环,语法格式如下:

1
2
3
for(变量声明:数组){
.....
}

圆括号里的“变量声明”用于声明一个临时变量,其类型与数组元素的类型相同。for each循环自动的从前往后依次访问数组的每个元素。每访问一个元素,就把它的值存入临时变量中,这样就可以通过临时变量获取数组各个元素的值。例如:

1
2
3
4
int a [10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
for(int n : a){
System.out.println(n);
}

8. 不规则数组

二维数组可以看作由一维数组嵌套而成,将二维数组的每一行看作一个元素,则二维数组降为一维数组。普通的二维数组每一行的长度相同,而不规则二维数组的每一行长度可以不同。普通二维数组和不规则二维数组的却别如下图所示:

1
2
3
4
5
* * * * * *                                   * * * * * *
* * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * *
普通二维数组 不规则二维数组

创建二维不规则数组,可以有三种方式:

1
2
3
4
5
6
7
8
9
10
// 1)
int a1[][] = new int[2][];
arry1[0]=new int[3];
arry1[1]=new int[2];
// 2)
int a2[][] = new int[2][];
a2[0]=new int[]{1, 2, 3};
a2[1]=new int[]{4, 5};
// 3)
int a3[][]={{1, 2, 3}, {4, 5}};

上机作业:
打印九九乘法表,先创建一个9行的二维不规则数组,然后把乘法表的每一行存入该数组的对应行中,最后用循环语句读取数组的每一行并打印。提示:数组类型是String,数组的每个元素(下标从0开始):a[i][j] = (i+1) + "*" + (j+1) + "=" + (i+1)*(j+1) + "\t";