第二章 Java语言基础
文章目录
2.1.1 字符集
- 字符是各种文字和符号的总称,包括个国家文字、标点符号、图形符号、数字等。字符集是多个字符的集合,不同的字符集所包含的字符个数也不同
- 常见字符集:
- ASCII字符集
- GB2312字符集
- Unicode字符集
类型 | 长度 | 说明 |
---|---|---|
UTF-8 | 长度可变 | UTF-8使用可变长度字节来存储Unicode字符,例如ASCII字母继续使用1字节储存;重音文字、希腊字母或西里尔字母等使用2字节来储存;而常用的汉字就要使用3字节;辅助平面字符则使用4字节 |
UTF-16 | 16位 | UTF-16大部分字符都以固定长度的2个字节(16位)储存,但UTF-16无法ASCII编码 |
UTF-32 | 32位 | UTF-32将每一个Unicode代码点表示为相同值的32位整数 |
Java语言中基本所有输入元素都是采用ASCII,而标识符、字符、字符串和注解则采用Unicode。
2.1.2 分隔符
- Java中使用多种字符作为分隔符,用于辅助程序编写、阅读和理解。这些分隔符可以分为两类:
- 空白符:没有确定意义,但帮助编译其正确理解源程序,包括空格、回车、换行和制表符(Tab)
- 普通分隔符:拥有确定含义,常用的普通分隔符如下表所示
任意两个相邻的标识符之间至少有一个分隔符,便于编译程序理解;空白符的数量多少没有区别,使用一个和多个空白符实现相同的分隔作用;分隔符不能相互替换,比如该用逗号的地方不能使用空白符。
类型 | 长度 | 说明 |
---|---|---|
() | 小括号 | 1.方法签名 2.表达式,以提升操作符的优先级 3.类型转换 4.循环,已包含要运算的表达式 |
{} | 大括号 | 1.类型声明 2.语句块 3.数组初始化 |
[] | 中括号 | 1.数组声明 2.数组值的引用 |
<> | 尖括号 | 1.泛型 2.将参数传递给参数化类型 |
. | 句号 | 1.隔开域或者方法与引用变量 2.隔开包、子包及类型名称 |
; | 分号 | 1.结束一条语句 2.for语句 |
, | 逗号 | 1.声明变量时,分隔各个变量 2.分隔方法中的参数 |
: | 冒号 | 1.for语句中,用于迭代数组或集合 2.三元运算符 |
2.1.3 标识符
-
在各种编程语言中,通常要为程序中处理的各种变量、常量、方法、对象和类等起个名字作为标记,以便通过名字进行访问,这些名字统称标识符。
-
Java中的标识符由字母、数字、下划线或美元符组成,且必须以字母、下划线(_)或美元符($)开头。
-
Java中标识符的命名规则如下:
- 可以包含数字,但不能以数字开头;
- 除下划线“_”和“$”符以外,不包含任何其他特殊字符,如空格;
- 区分大小写,例如“abc”和“ABC”是两个不同的标识符;
- 不能使用Java关键字。
2.1.4 关键字
abstract | assert | boolean | break | byte |
case | catch | char | class | const |
continue | default | do | double | else |
enum | extends | final | finally | float |
for | goto | if | implememts | import |
instanceof | int | interface | long | native |
new | package | private | protect | public |
return | strictfp | short | static | super |
switch | synchronized | this | throw | throws |
transient | try | void | volatile | while |
2.2.1 变量
-
变量是数据的基本存储形式,因Java是一种强类型的语言,所以每个变量都必须先声明后再使用。变量的定义包括变量类型和变量名,其定义的基本格式如下:
-
语法
数据类型 变量名 = 初始值;
2.2.2 常量
-
常量是指一旦赋值之后其值不能再改变的变量。在Java语言中,使用final关键字来定义常量,其语法格式如下:
final 数据类型 变量名 = 初始值;
在开发过程中常量名习惯采用全部大写字母,如果名称中含有多个单词,则单词之间以“_”分隔。此外常量在定义时,需要对常量进行初始化,初始化后,在应用程序中就无法再对该常量赋值。
2.2.3 变量作用域
- 在变量的使用过程中会涉及到变量的作用域和初始化,根据作用域范围可以将变量分为两种:
- 局部变量
- 成员变量
- 局部变量被定义在某个程序块内或方法体内,局部变量的作用范围有限,只在相应的程序块内或方法体内有效,超出程序块或方法体则这些变量将无效
程序块就是使用“{”和“}”包含起来的代码块,它是一个单独的模块。
示例代码VarScope.java
public static void main(String[] args) {
// 变量a的作用域是main()方法体内
int a = 10;
{
// 变量b的作用域是当前程序块的两个大括号中{}
int b = a * a;
// 此处变量a和变量b都在作用域范围内,都可以访问
System.out.println("a=" + a + ",b=" + b);
}
// 此处变量a在作用域范围内,可以访问
System.out.println("a=" + a);
// 错误,此处变量b已经不在作用域范围内,不可以访问
// System.out.println("b=" + b);
}
2.2.4 变量初始化
- 局部变量在使用之前必须进行初始化,即变量必须有值后才能被使用(先写后读)。
- 变量的初始化有两种方式:
- 在声明变量的同时赋初值;
- 先声明变量,在使用变量前再赋值。
示例代码VarValue.java
public static void main(String[] args) {
//声明变量a并赋初值
int a=10;
//声明变量b
int b;
//a已经有值,可以使用
System.out.println("a="+a);
//错误,b还没有值,不能使用
// System.out.println("b="+b);
//在使用之前先给b赋值
b=20;
//正确,b有值后可以使用
System.out.println("b="+b);
}
2.3 数据类型
Java的数据类型分为两大类:基本类型和引用类型。
- 基本类型是一个单纯的数据类型,表示一个具体的数字、字符或布尔值。基本类型存放在内存的“栈”中,可以快速从栈中访问这些数据。
- 引用类型是一个复杂的数据结构,是指向存储在内存的“堆”中数据的指针或引用(地址)。引用类型包括类、接口、数组和字符串等,由于要在运行时动态分配内存,其存取速度较慢。
- Java的基本数据类型主要包括如下四类:
- 整数类型:byte、short、int、long
- 浮点类型:float、double
- 字符类型:char
- 布尔类型:boolean
2.3.1 基本类型
-
Java各种基本类型的大小和取值范围
类型名称 关键字 大小 取值范围 字节型 byte 8 -27~27-1 短整型 short 16 -215~215-1 整型 int 32 -231~231-1 长整型 long 64 -263~263-1 浮点型 float 32 3.4e-38~3.4e+38 双精度 double 64 1.7e-38~1.7e+38 布尔型 boolean 1 true/false 字符型 char 16 “\u0000”~”\uFFFF”
整数类型
-
byte
-
short
-
int
-
long
-
Java中整数值表示方法
- 二进制
- 八进制
- 十进制
- 十六进制
示例代码IntValueDemo.java:
// 二进制数
int a = 0b1001;
System.out.println("二进制数0b1001的值是:" + a);
// 八进制数
int b = 071;
System.out.println("八进制数071的值是:" + b);
// 十进制数
int c = 19;
System.out.println("十进制数19的值是:" + c);
// Integer.toBinaryString()方法将一个整数以二进制形式输出
System.out.println("19的二进制表示是:" +Integer.toBinaryString(c));
// 十六进制数
int d = 0xFE;
System.out.println("十六进制数0xFE的值是:" + d);
System.out.println("十六进制数0xFE的二进制表示是" + Integer.toBinaryString(d));
// 负数以补码形式存储
int e = -19;
System.out.println("-19的二进制表示是:" + Integer.toBinaryString(e));
字符型
-
字符型char是采用16位的Unicode字符集作为编码方式,每个字符占两个字节
-
表示形式
- 通过单个字符来指定字符型值,例如:‘A’、‘8’、'Z’等;
- 通过转义字符来表示特殊字符型值,例如:’\n’、’\t’等;
- 直接使用Unicode值来表示字符型值,格式是‘\uXXXX’
-
转义字符表
转义字符 说明 Unicode编码 \b 退格符 \u0008 \t 制表符 \u0009 \n 换行符 \u000a \r 回车符 \u000d \" 双引号 \u0022 \’ 单引号 \u0027 \\ 反斜杠 \u005c
2.3.2 引用类型
- 引用类型变量中的值是指向内存“堆”中的指针,即该变量所表示数据的地址。
- 引用类型与基本类型在内存中存储的区别:
- 常用引用类型:
- 数组:具有相同数据类型的变量的集合;
- 类(class):变量和方法的集合;
- 接口(interface):一系列方法的声明,方法特征的集合;
- 枚举(enum):一种独特的值类型,用于声明一组命名的常数。
2.3.3 类型转换
- 类型转换的方式:
- 自动类型转换
- 强制类型转换
自动类型转换
-
自动类型转换是将某种基本类型变量的值直接赋值给另一种基本类型变量
强制类型转换
-
当把一个数值范围大的变量赋值给一个数值范围小的变量时,必须强制类型转换
-
语法:
数据类型 变量1 = (数据类型) 变量2;
强制类型转换示例代码AutoChange.java
byte b = 7;
char c = 'A';
int a = 10;
long l = 789L;
float f = 3.14f;
double d = 5.3d;
// 字符型变量c自动转换为整型,参加加法运算
int i1 = a + c;
System.out.println("i1=" + i1);
// 整型变量i1自动转换为长整型,参加减法运算
long l1 = l - i1;
System.out.println("l1=" + l1);
// 字节型变量b自动转换为浮点型,参加乘法运算
float f1 = b * f;
System.out.println("f1=" + f1);
// 整型变量a自动转换为双精度,参加除法运算
double d1 = d / a;
System.out.println("d1=" + d1);
// 将浮点型变量f1强制类型转换为整数
int i2 = (int) f1;
System.out.println("i2=" + i2);
// 整型变量a自动类型转换为长整型后参加除法运算,算出的长整型结果再强制类型转换为字符型
char c2 = (char) (l / a);
System.out.println("c2=" + c2);
2.4 操作符
- 操作符也称为运算符,是一种特殊的符号,用来将一个或多个操作数连接成执行性语句,以实现特定功能。
- 操作符类型:
- 一元操作符:只操作一个操作数;
- 二元操作符:操作两个操作数;
- 三元操作符:操作三个操作数。
分类 | 说明 | 符号 |
---|---|---|
一元操作符 | 自增、自减 | ++、– |
逻辑非 | ! | |
按位非 | ~ | |
强制类型转换 | (type) | |
二元操作符 | 算数运算 | +、-、*、/、% |
位运算 | &、|、^、<<、>>、>>> | |
关系运算 | >、>=、<、<=、==、!= | |
逻辑运算 | &&、|| | |
赋值 | =、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=、>>>= | |
三元操作符 | 三元判断 | ? : |
2.4.1 一元操作符
- 一元操作符之操作一个操作数
- 在运算符的两边只有一个操作数
1.自增运算只能操作单个数值型的变量(整型、浮点型都行),不能操作常量或表达式;
2.自增运算可以放在操作数的前面(前缀自增),也可以放在操作数后面(后缀自增)。
-
++ 运算,变量自己增长1。反之,-- 运算,变量自己减少1,用法与 ++ 一致。
-
独立运算:
- 变量在独立运算时,前++ 和 后++ 没有区别
- 变量前++ :例如 ++i 。
- 变量后++:例如 i++ 。
-
混合运算
-
和其他变量放在一起,前++ 和 后++ 就产生了不同。
-
变量前++ :变量a自己加1,将加1后的结果赋值给b,也就是说a先计算。a和b的结果都是2。
public static void main(String[] args){ int a = 1; int b = ++a; System.out.println(a); System.out.println(b);
-
}
```-
变量 后++ :变量a先把自己的值1,赋值给变量b,此时变量b的值就是1,变量a自己再加1。a的结果是2,b 的结果是1。
-
public static void main(String[] args){ int a = 1; int b = a++; System.out.println(a); System.out.println(b); }
-
非运算
- !是逻辑非运算,如果操作数为true,则返回false;如果操作数为false,则返回true。
- ~是按位非运算,将操作数对应的二进制数的每一位(包括符号位)全部取反,即原来是0,则为1;原来为1,则为0。
int a = 5;
// a先自增变为6,再与8相加,最后b的值是14
int b = ++a + 8;
System.out.println("b的值是:" + b);
int c = a++;
System.out.println("c的值是:" + c);
System.out.println("a的值是:" + a);
int d = 10;
System.out.println("前缀自减--d的值是:" + --d);
System.out.println("当前d的值是:" + d);
System.out.println("后缀自减d--的值是:" + d--);
System.out.println("当前d的值是:" + d);
boolean flag = true;
System.out.println("逻辑非:" + !flag);
int t = 10;
// Integer.toBinaryString()以二进制形式输出一个整数
System.out.println("整数10的二进制表示:" + Integer.toBinaryString(t));
// 按位非后的二进制是11111111111111111111111111110101
System.out.println("按位非的二进制表示:" + Integer.toBinaryString(~t));
// 按位非后的数值是-11,因为11111111111111111111111111110101是-11的补码
System.out.println("按位非的十进制表示:" + ~t);
2.4.2 二元运算符
算术运算
操作符 | 描述 | 示例 | |
---|---|---|---|
+ | 两个数相加,或两个字符串连接 | int a=5,b=3; //c的值为8 int c=a+b; | String s1=“abc”,s2=“efg”; //s3的值为"abcefg" String s3=s1+s2; |
- | 两个数相减 | int a=5,b=3; //c的值为2 int c=a-b; | |
* | 两个数相乘 | int a=5,b=3; //c的值为15 int c=a*b; | |
/ | 两个数相除 | int a=5,b=3; //c的值为1(整数) int c=a/b; | double a=5.1,b=3; //c的值为1.7(浮点数) double c=a/b; |
% | 取余:第一个数除以第二个数,整除后剩下的余数 | int a=5,b=3; //c的值为2 int c=a%b; | double a=5.2,b=3.1; //c的值为2.1 double c=a%b; |
如果/和%的两个操作数都是整数类型,则除数不能是0,否则引发除以0异常。但如果两个操作数有一个是浮点数,或者两个都是浮点数,此时允许除数是0或0.0,任何数除0得到的结果是正无穷大(Infinity)或负无穷大(-Infinity),任何数对0取余得到的结果是非数:NaN。
int a = 5;
int b = 3;
int c = a + b;
System.out.println(c);
// 字符串连接
String s1 = "abc";
String s2 = "efg";
String s3 = s1 + s2; // s3的值为"abcefg"
System.out.println(s3);
// 两个数相减,结果为2
System.out.println(a - b);
// 两个数相乘,结果为15
System.out.println(a * b);
// 两个整数相除,结果为1
System.out.println(a / b);
// 两个浮点数相除,结果为1.7
System.out.println(5.1 / 3);
// 两个整数取余,结果为2
System.out.println(a % b);
// 两个浮点数取余,结果为2.1
System.out.println(5.2 % 3.1);
//正浮点数除以0,结果为Infinity
System.out.println(3.1/0);
//负浮点数除以0,结果为-Infinity
System.out.println(-8.8/0);
//正浮点数对0取余,结果为NaN
System.out.println(5.1%0);
//负浮点数对0取余,结果为NaN
System.out.println(6.6%0);
//整数除以0,将引发异常
System.out.println(3/0);
位运算符
操作符 | 描述 | 示例 |
---|---|---|
& | 按位与,当两位同时为1才返回1 | 00101010 & 00001111 = 00001010 |
| | 按位或,只要有一位为1即可返回1 | 00101010 | 00001111 = 00101111 |
^ | 按位异或,当两位相同时返回0,不同时返回1 | 00101010 | 00001111 = 00100101 |
<< | 左移,N<<S的值是将N左移S位,右边空出来的位填充0,相当于乘2的S次方 | 11111000<<1 =11110000 |
>> | 右移,N>>S的值是将N右移S位,左边空出来的位如果是正数则填充0,负数则填充1,相当于除2的S次方 | 11111000>>1 =1111100 |
>>> | 无符号右移,无论正数还是负数,无符号右移后左边空出来的位都填充0 | 11111000>>>1 =0111100 |
int a = 0b00101010;
int b = 0b00001111;
// 按位与
System.out.println(Integer.toBinaryString(a & b));
// 按位或
System.out.println(Integer.toBinaryString(a | b));
//按位异或
System.out.println(Integer.toBinaryString(a^b ));
int c=0b11111000000000000000000000000000;
//左移
System.out.println(Integer.toBinaryString(c<<1 ));
//右移
System.out.println(Integer.toBinaryString(c>>1));
//无符号右移
System.out.println(Integer.toBinaryString(c>>>1));
关系运算符
操作符 | 描述 | 示例 |
---|---|---|
> | 大于,左边操作数大于右边操作数,则返回true | int a=5,b=3; System.out.println(a>b);//true |
>= | 大于等于,左边操作数大于或等于右边操作数,则返回true | int a=5,b=3; System.out.println(a>=b);//true |
< | 小于,左边操作数小于右边操作数,则返回true | int a=5,b=3; System.out.println(a<b);//false |
<= | 小于等于,左边操作数小于或等于右边操作数,则返回true | int a=5,b=3; System.out.println(a<=b);//false |
== | 等于,两个操作数相等,则返回true | int a=5,b=3; System.out.println(a==b);//false |
int a = 5;
int b = 3;
System.out.println(a + ">" + b + "结果为" + (a > b));
System.out.println(a + ">=" + b + "结果为" + (a >= b));
System.out.println(a + "<" + b + "结果为" + (a < b));
System.out.println(a + "<=" + b + "结果为" + (a <= b));
System.out.println(a + "==" + b + "结果为" + (a == b));
//'a'的ASCII值为97,因此相等,结果为true
System.out.println("'a'==97结果为"+('a'==97));
关系运算符中==比较特别,如果进行比较的两个操作数都是数值类型,即使它们的数据类型不同,只要它们的值相等,都将返回true。
例如’a’97返回true,55.0也返回true。
如果两个操作数都是引用类型,则只有当两个引用变量的类型具有继承关系时才可以比较,且这两个引用必须指向同一个对象(地址相同)才会返回true。如果两个操作数是布尔类型的值也可以进行比较。
例如true==false返回false。
逻辑运算符
操作符 | 描述 | 示例 |
---|---|---|
&/&& | 逻辑与,前后两个操作数都为true,则返回true | boolean a=true,b=false; System.out.println(a&&b);//false |
|/|| | 逻辑或,前后两个操作数都为false,则返回false | boolean a=true,b=false; System.out.println(a||b);//true |
&& | 短路与,第一个操作数为假则不判断第二个操作数 | |
|| | 短路或,第一个操作数为真则不判断第二个操作数 | |
^ | 逻辑异或 |
- 逻辑运算真值表
A | B | A && B | A || B |
---|---|---|---|
true | true | true | true |
true | false | false | true |
false | true | false | true |
false | false | false | false |
// &&
System.out.println("true && true = " + (true && true));
System.out.println("true && false = " + (true && false));
System.out.println("false && true = " + (false && true));
System.out.println("false && false = " + (false && false));
// ||
System.out.println("true || true = " + (true || true));
System.out.println("true || false = " + (true || false));
System.out.println("false || true = " + (false || true));
System.out.println("false || false = " + (false || false));
在逻辑运算时,为了提高运行效率,Java提供了“短路运算”功能。&&运算符检查第一个操作数是否为false,如果是false则结果必为false,无需检查第二个操作数。||运算符检查第一个表达式是否为true,如果是true则结果必为true,无需检查第二个操作数。检查其他内容。因此,对于&&当第一个操作数为fasle时会出现短路;对于||当第一个操作数为true时会出现短路。
赋值运算符
-
赋值运算符用于为变量指定变量值,Java中使用“=”作为赋值运算符
-
可以直接将一个值赋给变量
-
将一个变量值或表达式的值赋给另一个变量
类赋值运算符:
混合赋值运算符 | 示例 | 等价于 |
---|---|---|
+= | 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 |
&= | 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 |
>>>= | a>>>=b | a=a>>>b |
int a = 8;
int b = 3;
System.out.println(a += b);
System.out.println(a -= b);
System.out.println(a *= b);
System.out.println(a /= b);
System.out.println(a %= b);
System.out.println(a &= b);
System.out.println(a |= b);
System.out.println(a <<= b);
System.out.println(a >>= b);
System.out.println(a >>>= b);
2.4.3 三元操作符
-
语法
表达式 ? value1 : value2
表达式的值必须为布尔类型,可以是关系表达式或逻辑表达式;
若表达式的值为true,则返回value1的值;
表达式的值为false,则返回value2的值。
2.4.4 运算符优先级
优先级(由高到低) | 运算符 |
---|---|
分割符 | . [] () {} , ; |
一元运算 | ++ – ! ~ |
强制类型转换 | (type) |
乘、除、取余 | * / % |
加、减 | + - |
移位运算符 | >> >>> << |
关系大小运算符 | > < >= <= |
等价运算符 | == != |
按位与 | & |
按位异或 | ^ |
按位或 | | |
逻辑与 | && |
逻辑或 | || |
三元运算符 | ?: |
赋值运算符 | = += -= *= /= %= ^= &= |= <<= >>= >>>= |
不要把一个表达式写得太复杂,如果一个表达式过于复杂,则把它分成多步来完成;
不要过多依赖运算符的优先级来控制表达式的执行顺序,以免降低可读性,尽量使用()来控制表达式的执行顺序。
2.5 流程控制
- 分支语句:if和switch语句;
- 循环语句:while、do-while和for循环语句
- 转移语句:break、continue和return语句
2.5.1 分支结构
-
分支结构是根据表达式条件的成立与否,决定执行哪些语句的结构。其作用是让程序根据具体情况有选择性地执行代码。
-
分支语句有以下两个:
- if条件语句
- switch多分支语句
if语句:
-
语法:
if(条件表达式1) {语句块1} [else if(条件表达式2) {语句块2}] [else if(条件表达式3) {语句块3}] ...... [else {语句块n}]
1.所有条件表达式的结果为布尔值(true或false);
2.当“条件表达式1”为true时执行if语句中的“语句块1”部分;
3.当“条件表达式1”为false时,执行else if语句,继续向下判断条件表达式,哪个条件表达式成立,执行相应的语句块;
4.当所有条件表达式为false时执行else语句中的“语句块n”部分。
5.else if可以有多个;
6.[]括起来的else if、else可以省略。
-
语法形式一:
-
if(条件表达式){
语句块
}
```
-
语法形式二
if(条件表达式) {
语句块
}else{
语句块
}
```
-
语法形式三
if(条件表达式) {
语句块
}else if(条件表达式){
语句块
} else if(条件表达式){
语句块
}
…//可以有多个else if语句
else{
语句块
}
```
int g = 67;
// 判断g是否是负数
if (g < 0) {
System.out.println("负数");
}
// 判断g是偶数还是奇数
if (g % 2 == 0) {
System.out.println("偶数");
} else {
System.out.println("奇数");
}
// 判断g的等级
if (g >= 90) {
System.out.println("优秀");
} else if (g >= 80) {
System.out.println("良好");
} else if (g >= 70) {
System.out.println("中等");
} else if (g >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
switch语句
- switch语句是由一个控制表达式和多个case标签组成
- 与if语句不同的是,switch语句后面的控制表达式的数据类型只能是byte、short、char、int四种类型,boolean类型等其他类型是不被允许的
- 但从Java 7开始允许枚举类型和String字符串类型
语法:
switch (控制表达式){
case value1 :
语句1;
break;
case value2 :
语句2;
break;
......
case valueN :
语句N;
break;
[default : 默认语句; ]
}
1、控制表达式的数据类型只能是byte、short、char、int、String和枚举类型;
2、case标签后的value值必须是常量,且数据类型必须与控制表达式的值保持一致;
3、break用于跳出switch语句,即当执行完一个case分支后,终止switch语句的执行;只有在一些特殊情况下,当多个连续的case值要执行一组相同的操作时,此时可以不用break。
4、default语句是可选的。用在当所有case语句都不匹配控制表达式值时,默认执行的语句。
int g = 67;
switch (g / 10) {// 使用switch 判断g的等级
case 10:
case 9:
System.out.println("优秀"); break;
case 8:
System.out.println("良好"); break;
case 7:
System.out.println("中等"); break;
case 6:
System.out.println("及格"); break;
default:
System.out.println("不及格");
}
// 声明变量season是字符串,注意JDK版本是7以上才能支持
String season = "秋天";
// 执行swicth分支语句
switch (season) {
case "春天":
System.out.println("春暖花开.");break;
case "夏天":
System.out.println("夏日炎炎.");break;
case "秋天":
System.out.println("秋高气爽.");break;
case "冬天":
System.out.println("冬雪皑皑.");break;
default:
System.out.println("季节输入错误");
}
2.5.2 循环结构
-
循环结构可以在满足循环条件的情况下反复执行某一段代码,这段被重复执行的代码被称为“循环体”。
-
提供的循环语句有以下三种:
- for循环
- while循环
- do-while循环
for循环
语法:
for ([初始化表达式];[条件表达式];[迭代表达式]){
循环体
}
初始化表达式只在循环开始之前执行一次;
初始化表达式、条件表达式以及迭代表达式都可以省略,但分号不能省,当三者都省略时将成为一个无限循环(死循环);
在初始化表达式和迭代表达式中可以使用逗号隔开多个语句。
流程图:
public class ForDemo1 {
public static void main(String[] args) {
// 循环的初始化,循环条件,循环迭代语句都在下面一行
for (int count = 1; count <= 10; count++) {
System.out.println(count);
}
System.out.println("循环结束!");
}
}
public class ForDemo2 {
public static void main(String[] args) {
// 使用for循环求1~100的和
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
System.out.println("1~100的和是:" + sum);
}
}
// 嵌套的for循环打印九九乘法表
//第一个for控制行
for (int i = 1; i <= 9; i++) {
//第二个for控制列,即每行中输出的算式
for (int j = 1; j <= i; j++) {
// 输出j*i=n格式,例如2*3=6
System.out.print(j + "*" + i + "=" + i * j + " ");
}
// 换行
System.out.println();
}
while循环
语法
while (条件表达式){
循环体
}
流程图
public class WhileDemo {
public static void main(String[] args) {
// 使用while循环求1~100的和
int sum = 0;
int i = 1;
while (i <= 100) {
sum += i;
i++;
}
System.out.println("1~100的和是:" + sum);
}
}
do-while循环
语法
do {
循环体
} while (条件表达式);
流程图
public static void main(String[] args) {
// 使用do-while循环求1~100的和
int sum = 0;
int i = 1;
do {
sum += i;
i++;
} while (i <= 100);
System.out.println("1~100的和是:" + sum);
}
2.5.3 转移语句
-
Java提供一些转移语句来控制分支和循环结构,使程序员更方便地控制程序执行的方向
-
提供的转移语句有以下三种:
- break语句
- continue语句
- return语句
break语句
- break语句用于终止分支结构或循环结构,其主要用在以下3种情况:
- 在switch语句中,用于终止case语句,跳出switch分支结构;
- 在循环结构中,用于终止循环语句,跳出循环结构。
- 与标签语句配合使用从内层循环或内层程序块中退出。
public class BreakDemo1 {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
System.out.println("找到目标,结束循环!");
// 终止循环
break;
}
System.out.println(i);// 打印当前的i值
}
}
}
public static void main(String[] args) {
// 外层循环,outer作为标识符
outer: for (int i = 0; i < 5; i++) {
// 内层循环
for (int j = 0; j < 3; j++) {
System.out.println("i的值为:" + i + " j的值为:" + j);
if (j == 1) {
// 跳出outer标签所标识的循环。
break outer;
}
}
}
}
continue语句
- continue的功能与break有点类似,区别是continue只是忽略本次循环体剩下的语句,接着进入到下一次循环,并不会终止循环;而break则是完全终止循环。
for (int i = 1; i <= 10; i++) {
if (i == 5) {
System.out.println("找到目标,继续循环!");
// 跳出本次循环,进入下一次循环
continue;
}
// 打印当前的i值
System.out.println(i);
}
return语句
- return语句主要有以下两种使用格式:
- 单独一个return关键字;
- return关键字后面可以跟变量、常量或表达式,例如:return 0;
// 一个简单的for循环
for (int i = 0; i < 3; i++) {
System.out.println("i的值是" + i);
if (i == 5) {
//返回,结束main方法
return;
}
System.out.println("return后的输出语句");
}
2.6 数组
数组是编程语言中常见的一种数据结构。通常,数组用来存储一组大小固定并且类型相同的数据,这些数据可以通过索引进行访问。根据数组存放元素的组织结构,可将数组分为一维数组、二维数组以及多维数组(三维及以上)。
2.6.1 创建数组
语法:
数据类型[] 数组名;
数据类型 数组名[];
数组被创建后,其大小不能改变,但数组中的各个元素值是可以改变的;且访问数组中的元素时,下标索引不能越界,范围必须在0~length-1,否则容易引发数组越界异常。
// 声明一个整型数组a
int[] a;
// 给数组a分配存储空间:10*4个字节
a = new int[10];
// 定义一个长度为10的双精度浮点型数组
double[] b = new double[10];
// 定义一个长度为100的字符型数组c
char[] c = new char[100];
// 定义一个长度为20的布尔型数组
boolean[] d = new boolean[20];
//定义一个长度为5的字符串数组
String[] s=new String[5];
/* 下面输出各数组的数组名,注意输出的内容 */
// 输出数组地址
System.out.println(a);
System.out.println(b);
//输出字符数组中的内容
System.out.println(c);
//输出数组地址
System.out.println(d);
System.out.println(s);
System.out.println("*****************");
//输出各数组中第一个元素的值,注意输出的内容
System.out.println(a[0]);
System.out.println(b[0]);
System.out.println(c[0]);
System.out.println(d[0]);
System.out.println(s[0]);
System.out.println("*****************");
//输出各数组的长度
System.out.println("a.length=" + a.length);
System.out.println("b.length=" + b.length);
System.out.println("c.length=" + c.length);
System.out.println("d.length=" + d.length);
System.out.println("s.length=" + s.length);
- 当数组使用new分配存储空间后,数组中的元素会具有默认初始值,其中:
- 数值类型的数组初始值为0;
- 布尔类型的为false;
- 字符型的为‘\0’(字符串结束标识);
- 引用类型的则为null(空引用)。例如,字符串String就是引用类型。
数组在内存中的组织结构
2.6.2 初始化数组
- 程序应用中数组元素的值经常是指定值,而非默认值,此时就需要将数组进行初始化。Java中数组的初始化方式有两种:静态初始化和动态初始化。
// 定义并初始化数组,使用静态初始化
int[] a = { 5, 7, 20 };
// 定义并初始化数组,使用动态初始化
int[] b = new int[4];
for (int i = 0; i < b.length; i++) {
b[i] = i + 1;
}
// 循环输出a数组的元素
System.out.println("数组a中的元素是:");
for (int i = 0, len = a.length; i < len; i++) {
System.out.print(a[i] + " ");
}
System.out.println();
// 输出b数组的长度
System.out.println("b数组的长度为:" + b.length);
System.out.println("数组b中的元素是:");
// 循环输出b数组的元素
for (int i = 0, len = b.length; i < len; i++) {
System.out.print(b[i] + " ");
}
System.out.println();
// 因为a是int[]类型,b也是int[]类型,所以可以将a的值赋给b。
// 也就是让b引用指向a引用指向的数组
b = a;
// 再次输出b数组的长度
System.out.println("b数组的长度为:" + b.length);
2.6.3 for each遍历数组——增强for语句
语法
for(数据类型 变量名 : 数组名)
foreach语句的代码
for (int e : a) {
System.out.println(e);
}
等价于:
for (int i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
2.6.4 复制数组
-
System.arraycopy方法提供了数组元素复制功能:
//原数组 int[] source = {1,2,3,4,5,6}; //目的数组 int[] dest={10,9,8,7,6,5,4,3,2,1}; /*赋值原数组中从下标0开始的source.length个元素 到目的数组,从下标0的位置开始存储*/ System.arraycopy(source,0,dest,0,source.length);
数组复制的常用方法:
- for循环,效率最低
- System.arraycopy() 效率最高
- Arrays.copyOf() 效率次于第二种方法
- Object.clone() 效率次于第二种和第三种
2.6.5 二维数组
语法
数据类型[][] 数组名;
内存中的二维数组
// 二维数组静态初始化
int[][] a = { { 1, 2, 3 }, { 4, 5, 6 } };
System.out.println("数组a一维长度:" + a.length);
System.out.println("数组a二维长度:" + a[0].length);
System.out.println("数组a中的元素:");
for (int i = 0; i < a.length; i++) {// 使用嵌套的for循环输出
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j] + " ");
}
System.out.println();
}
System.out.println("-------------------------");
// 二维数组动态初始化,一维和二维都指定长度
int[][] c = new int[3][4];
// 使用嵌套的for循环初始化二维数组
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < c[i].length; j++) {
c[i][j] = i + j;
}
}
System.out.println("数组c中的元素:");
// 使用嵌套的for循环输出
for (int i = 0; i < c.length; i++) {
for (int j = 0; j < c[i].length; j++) {
System.out.print(c[i][j] + " ");
}
System.out.println();
}
System.out.println("-------------------------");
// 声明二维数组时,只给出一维长度
int[][] d = new int[2][];
// 二维长度不等
d[0] = new int[3];
d[1] = new int[4];
// 初始化
for (int i = 0; i < d.length; i++) {
for (int j = 0; j < d[i].length; j++) {
d[i][j] = i + j;
}
}
}
System.out.println("数组d中的元素:");
// 使用嵌套的for循环输出
for (int i = 0; i < d.length; i++) {
for (int j = 0; j < d[i].length; j++) {
System.out.print(d[i][j] + " ");
}
System.out.println();
}
2.7 练习
案例分析
-
用“埃氏筛法”求2~100以内的素数。2~100以内的数,先去掉2的倍数,再去掉3的倍数,再去掉5的倍数,……依此类推,最后剩下的就是素数。(要求使用数组及增强的for语句。)
-
小分析:题目所要求的即是将不大于根号n(题目:100)的所有素数的倍数剔除,剩下的就是素数。
-
定义一个数组a[99],放置2,3,4,5,…,100.
-
数组中每个数都除2,能整除的除2之外的数组元素都赋0剩余的便是:
2,3,5,7,…
-
同样除3,5,7,…,11(11大于题目所给的n的根号)
-
将数组中不为0的数输出
-
案例实现
public class Eratosthenes {
public static void main(String[] args) {
int[] list = new int[99];
for (int i = 0; i < list.length; i++) {
list[i] = i + 2;
}
for (int m = 1; check(list, m) * check(list, m) < list.length; m++) {
for (int n = 0; n < list.length; n++) {
if (check(list, m) != 0) {
if (list[n] % (check(list, m)) == 0 && list[n] != (check(list, m))) {
list[n] = 0;
}
} else {
break;
}
}
}
show(list);
}
public static int check(int[] list, int m) {
int n = 0;
int c = 0;
for (int i = 0; n < m; i++) {
c++;/
if ((list[i]) != 0) {
n++;
}
}
return list[c - 1];
}
public static void show(int[] list) {
for (int value : list) {
if (value != 0) {
System.out.println(value);
}
}
}
}
总结
-
Java中数据类型分为两类:基本数据类型和引用类型
-
局部变量在使用之前必须进行初始化
-
一元运算符有:++、–、~、!
-
算术运算符有:+、-、*、/、%
-
位运算符有:~、&、|、^、>>、>>>、<<
-
关系运算符有:>、>=、<、<=、==、!=
-
逻辑运算符有:!、&&、||
-
三元运算符是“ ? : ”
-
Java中通常使用()来改变运算符的优先级
-
Java的分支语句有if-else,switch-case
-
Java的循环语句有for,while,do-while,foreach
-
Java的转移语句有break,continue,return
-
数组用来存储一组相同数据类型的数据结构
-
数组的下标索引是从0开始,其取值范围必须在0~数组的长度-1
-
Java中数组是静态结构,其大小不能改变