Java基础 - 基础语法
基础语法(上)
1.关键字和保留字
关键字(keyword):被java语言赋予了特殊含义,用于专门用途的字符串。(注意:关键字都是小写字母)
保留字(reserved word): 现在java版本中尚未使用的,但在以后版本可能会作为关键字使用。自己命名标识符时要避免使用。(保留字:goto const)
2.标识符(Identifier)
标识符:对 **变量、方法、类、接口、包名**等要素命名时,使用的字符序列就是标识符。
简单说 **标识符** 就是自定义起名字的地方都叫 **标识符**。
(1)标识符命名规则:
1. 26个英文字符(区分大小写)、数字(0-9)、_ 、$ 组成;
2. 数字不能开头;
3. 不可以使用关键字或者保留字,但是能包含关键字和保留字。
4. 标识符中 不能使用空格;
5. java是严格区分大小写的; 如:定义变量 int A; int a; A 和 a 指的是两个不同的变量。
6. 标识符的长度没有限制;
注意:如果不遵守上述规则,编译不通过,需要严格遵守。
(2)标识符的命名规范:
1. 包名:所有字母小写;如:yu.bai
2. 类名、接口名 : 单个单词或多个单词组成时,首字母大写。 如:MyName
3. 变量名、方法名:多单词组成时,首字母小写,第二个单词开始每个单词的首字母大写。如:myName
4. 常量名 : 所有字母大写,单词与单词之间使用 _ 分隔; 如:MY_NAME
注意 : 如果不遵守上述的规范,编译也是可以通过的,但是建议遵守。(要规范编码)
补充 :java采用的是 **unicode** 字符集,因此 标识符也可以使用中文,但是不建议。
3. 变量
(1)变量声明与赋值
变量类型 变量名 = 变量值;
int num = 0;
(2)变量定义:
内存中的一个存储空间(区域)。
该空间(区域)的数据可以在同一类型范围内不断变化。
变量是程序中最基本的存储单元。
变量的包括 变量类型 变量名称 变量存储的值。
(3)变量的作用:
用于在内存中保存数据;
(4)使用变量需要注意:
Java中每个变量必须先声明,后使用。(【编译错误】不先声明变量,则内存中就没有该变量的空间,则就使用不了)
Java中 未被初始化值的变量,也不能直接使用。(【编译错误】变量没有被赋值,内存中只是有了空间名称。但是不知道具体值)
通过 变量名 来访问 该变量所在的区域。
变量的作用域: {} 花括号 ,变量只有在其作用域内才有效,同一个作用域中,不能定义同名的变量名。
(5)变量的类型:
对于每一种数据都定义了明确的数据类型(强类型语言),在内存中分配了不同大小的内存空间。
数据类型分为 : 基本数据类型 和 引用数据类型
1)基本数据类型:
-
数值型
整数类型 : byte short int long
浮点类型 : float double
字符型 : char
布尔型 : boolean
2) 引用数据类型:
类 (class) 如:String、自定义的任何类型等;
接口 (interface)
数组 ([])
(6)变量的分类(按声明的位置不同)
-
在方法体外,类体内声明的变量称为成员变量。
成员变量的体现形式:
实例变量 (对象变量【不是static修饰】)
类变量 (以static修饰)
-
在方法体内部声明的变量称为局部变量。
局部变量的体现形式:
形式参数 (方法、构造器中参数定义的变量)
方法中定义的变量 (在方法的 {} 作用域中的)
在代码块中定义的变量 (在 代码块 {} 作用域中的)
-
注意:二者在初始化值方面的异同点:
相同:都有生命周期
不同点:局部变量除了形式参数外,需要显示初始值。
(7)基本数据类型详解
整数类型
类型 | 占用字节(1字节(byte) = 8位(bit)) | 表数范围 |
---|---|---|
byte | 1字节 | -128 ~ 127 |
short | 2字节 | -2^15 ~ 2^15 - 1 |
int | 4字节 | -2^31 ~ 2^31 - 1 |
long | 8字节 | -2^63 ~ 2^63 - 1 |
Java 个整数类型有固定的表数范围和字符长度,不受具体OS(操作系统)的影响,保证Java程序的可移植性。
Java 中默认的整数类型为 int
声明 long 型变量时,需在变量值后 添加 L 或 l; 如:long l1 = 100L; long l1 = 100l;
bit(位) 是 计算机中最小的存储单位
byte(字节) 是 计算机中基本存储单元。计算机处理数据的最小单位是1个字节
浮点类型
类型(精度) | 占用字节 | 表数范围 |
---|---|---|
float (单精度) | 4字节 | -3.403E38 ~ 3.403E38 |
double(双精度) | 8字节 | -1.798E308 ~ 1.798E308 |
E 表示 :E是计算机中的科学技术法的标志。 你可以把它理解成 10^x 次方
float:单精度,尾数可以精确到7位有效数字。很多情况下,精度很难满足需求。
double:双精度,精度是float的两倍。通常采用此类型。
Java 的浮点型常量默认为double型,声明float型常量,须后加 f 或 F。如:float f1 = 100F;
字符类型
类型 | 占用字节 | 表数范围 |
---|---|---|
char | 2字节 |
char 型数据用来表示通常意义上“字符”(2字节)
Java中的所有字符都使用Unicode编码,故一个字符可以存储一个字母,一个汉字,或其他书面语的一个字符。
字符型变量的三种表现形式:
字符常量是用单引号(' ')括起来的单个字符。如:char c1 = 'a'; char c2 = '中'; char c3 = '9';
-
Java中还允许使用转义字符' \ '来将其后的字符转变为特殊字符型常量。
例如:char c3 = ‘\n’; // '\n'表示换行符
-
直接使用 Unicode 值来表示字符型常量:‘\uXXXX’。其中,XXXX代表一个十六进制整数。
如:\u000a 表示 \n。
char类型是可以进行运算的。因为它都对应有Unicode码。
布尔类型
类型 | 占用字节 | 表数范围 |
---|---|---|
boolean | 4字节 (《java虚拟机规范 8版》) |
-
Java虚拟机中没有任何供boolean值专用的字节码指令,
Java语言表达所操作的boolean值,在编译之后都使用java虚拟机中的int数据类型来代替:
true用1表示,false用0表示。———《java虚拟机规范 8版》
boolean 的 取值 只能是 true | false
(8)基本数据类型的容量排序
从小到大排序:(boolean 类型不进行排序)
编号 | 类型 | 占用字节 | 所属类型 |
---|---|---|---|
1 | byte | 1字节 | 整数型 |
2 | char | 2字节 | 字符型 |
3 | short | 2字节 | 整数型 |
4 | int | 4字节 | 整数型 |
5 | long | 8字节 | 整数型 |
6 | float | 4字节 | 浮点型 |
7 | double | 8字节 | 浮点型 |
浮点型的容量要比整数型的存储容量大。
[图片上传失败...(image-e136ff-1607962841161)]
(9)基本数据类型之间的转换
1) 自动类型转换:
byte 、char 、 short ---> int ---> long ---> float ---> double
特别说明:当 byte 、 char 、short 三种类型的变量做运算时或各类型与自己作用算时,结果为 int 类型。
容量小的类型 自动向 容量大的类型转换。
有多种类型的数据混合运算时,系统首先自动将所有数据转换成容量最大的那种数据类型,然后在进行计算。
byte short char 之间不会相互转换,他们三者在计算时,首先转换为 int 类型。
boolean 类型不能与其他数据类型进行运算。
当基本数据类型的值,与字符串(String)进行 加法运算时,基本数据类型的值,将为自动转换为字符串(String)类型。
2) 强制类型转换:
将容量大的数据类型转换为容量小的数据类型。转换时,要加上强制转换符号 ()。在进行强制转换时,可能造成精度降低或溢出,需要格外小心。
-
通常,字符串不能直接转换为基本数据类型。但通过基本类型的包装类,可以实现将字符串转换为基本数据类型。
如: String str = "43";
int i = Integer.parseInt(str);
boolean 类型不能转换为其他的数据类型。
(10) 基本数据类型 与 String 类型之间的转换
String类型变量的使用:
String属于引用数据类型,翻译为:字符串
声明String类型变量时,使用一对""
String可以和8种基本数据类型变量做运算,且运算只能是连接运算:+
运算的结果仍然是 String 类型;
4.进制
所有数字在计算机底层都是以 二进制 形式存在。
对于整数,有四种进制的表现形式:
进制名称 | 底层表示 | 进位方式 | 以什么符号开头 |
---|---|---|---|
二进制 | 0 和 1 | 满 2 进 1 | 以数字0和字母B开头 :0b 或者 0B |
十进制 | 0 ~ 9 | 满 10 进 1 | |
八进制 | 0 ~ 7 | 满 8 进 1 | 以数字 0 开头 |
十六进制 | 0 ~ 9 以及 A ~ F | 满 16 进 1 | 以数字0和字母X开头:0x 或者 0X |
5.运算符
算数运算符 赋值运算符 比较运算符(关系运算符) 逻辑运算符 位运算符 三元运算符
(1) 算数运算符
运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
+ | 正号 | +3 | 3 |
- | 符号 | b=4; -b; | b=-4 |
+ | 加 | 5+5 | 10 |
- | 减 | 6-4 | 2 |
* | 乘 | 3*5 | 15 |
/ | 除 | 5(被除数) / 5(除数) | 1 |
% | 取模(取余) | 7(被模数) % 5(模数) | 2 |
++ | 自增(前):先运算后赋值 | a=2; b=++a; | a=3 b=3 |
++ | 自增(后):先赋值后运算 | a=2; b=a++; | a=3 b=2 |
-- | 自减(前):先运算后赋值 | a=2; b=--a; | a=1 b=1 |
-- | 自减(后):先赋值后运算 | a=2; b=a--; | a=1 b=2 |
+ | 字符串连接 | "he"+"llo" | "hello" |
(2) 赋值运算符
赋值运算符:=
等号 右边 的值,赋值给等号 左边 的变量。 int a = 10;
当 " = " 两侧数据类型不一致时,可以使用自动类型转换或强制类型转换原则进行处理。
支持连续赋值: int a = 10; int b = 20; int c = a = b;
扩展赋值运算符:+= -= *= /= %=
自动强制类型转换的功能。(原变量的类型不会变化)
(3) 比较运算符
比较运算符 | 运算 | 范例 | 结果 |
---|---|---|---|
== | 相等于 | 4==3 | false |
!= | 不等于 | 4 != 3 | true |
< | 小于 | 4 < 3 | false |
> | 大于 | 4 > 3 | true |
<= | 小于或等于 | 4 <= 3 | false |
>= | 大于或等于 | 4 >= 3 | true |
instanceof | 检查是否是类的对象 | "hello" instanceof String | true |
比较运算符的结果都是 boolean 型的。结果只有 true 或 false.
(4) 逻辑运算符
& : 逻辑与 (判断是否有false)
&& :短路与 (判断是否有 false,第一个为false时,则不执行后面表达式)
只要有一个表达式的结果为 false,则这个逻辑判断的返回值就是 false
如果所有的表达式的结果都为true,则这个逻辑判断的返回值就是 true
| :逻辑或 (判断是否有true)
|| : 短路或 (判断是否有true,第一个为true时,则不执行后面的表达式)
只要有一个表达式的结果为 true,则这个逻辑判断的返回值就是 true
如果所有的表达式的结果都为 false,则这个逻辑判断的返回值就是 false
! :逻辑非
^ :逻辑异或
多个表达式的结果都为 true 或者 都为 false 时, 则 逻辑异或 的结果是 false
多个表达式的结果 有 true 也有 false 时,则 逻辑异或 的结果是 true
a | b | a&b | a&&b | a|b | a||b | !a | a^b |
---|---|---|---|---|---|---|---|
true | true | true | true | true | true | false | false |
true | false | false | false | true | true | false | true |
false | true | false | false | true | true | true | true |
false | false | false | false | false | false | true | false |
- 逻辑运算符操作的都是boolean类型的变量。
(5) 位运算符
位运算符 | 运算 | 范例 | ||
---|---|---|---|---|
<< | 左移 | 3 << 2 = 12 ---> 322=12 | ||
>> | 右移 | 3 >> 1 = 1 ---> 3 / 2 = 1 | ||
>>> | 无符号右移 | 3 >>> 1 = 1 ---> 3 / 2 = 1 | ||
& | 与运算 | 6 & 3 = 2 | ||
或运算 | 6 | 3 = 7 | ||
^ | 异或运算 | 6 ^ 3 = 5 | ||
~ | 取反运算 | ~ 6 = -7 |
位运算是直接对整数的二进制进行的运算。
位运算符操作的是 整数型 ,不能操作字符 、字符串 、布尔型
位运算符 | 补位 |
---|---|
<< | 空位补0,被移除的高位丢弃,空缺位补0 |
>>> | 被移除的二进制最高位是0,右移后,空缺位都补0。最高位是1.空缺位都补1. |
>>> | 被移位二进制最高位无论是0或者是1,空缺位都用0补。 |
& | 二进制位 进行 & 运算,只有 1 & 1时,结果是 1 ,否则是0 |
| | 二进制位 进行 | 运算,只有 0 | 0 时,结果是 0,否则是1 |
^ | 相同二进制位进行 ^ 运算,结果是 0; 如:1 ^ 1 = 0 、 0 ^ 0 = 0 ; 不同二进制位进行 ^ 运算结果是 1 。 如: 1 ^ 0 = 1 、 0 ^ 1 = 1 |
~ | 正数取反,各二进制码按补码各位取反 负数取反,各二进制码按补码各位取反 |
[图片上传失败...(image-7ea475-1607962841161)]
[图片上传失败...(image-27794e-1607962841161)]
[图片上传失败...(image-8a80c4-1607962841161)]
(6) 三元运算符
符号语法: 条件表达式 ? 表达式1 : 表达式2;
说明: 条件表达式的结果是 boolean 类型。 条件表达式成立 true,则结果是 表达式 1 条件表达式不成立 false ,则结果是 表达式 2
能使用 三元运算符的地方,都可以改成使用 if-else 如果在实际开发中,遇到了既可以使用三元运算符也可以使用 if-else 的地方。那么优先选择使用 三元运算符,原因是 简洁执行效率高
(7) 运算符的优先级
小括号() 的优先级最高,如果想先计算的话,则加上小括号就行。
基础语法(下)
1.程序流程控制
顺序结构:程序从上到下逐行的执行,中间没有任何判断和跳转。
分支结构:根据条件,选择性的执行某段代码。有 if ... else 和 switch-case 两种分支语句。
循环结构:根据循环条件,重复的执行某段代码。有 while 、 do...while 、for 三种循环语句。
注:JDK1.5提供了 foreach 循环,方便的遍历集合、数组元素。
2.分支结构
(1) if else
if 语句,条件表达式成立才会执行if中的代码块。
if(条件表达式){
代码块;
}
其他代码;
if - else 语句,又叫 二选一(表明给出的两个代码块,必须执行其中的一个)
if(条件表达式){
代码块1;
}else{
代码块2;
}
if - else if ... - else 语句,又叫多选一 (表明给出的多个代码块,必须执行其中的一个(前提是有else语句时))
if(条件表达式1){
代码块1;
}else if(条件表达式2){
代码块2;
}else if(条件表达式3){
代码块3;
}
...
else{
代码块n;
}
(2)switch-case
语法:
switch(表达式){
case 常量1:
语句块1;//(可以写多条语句,每条语句以分号结束)
break; // break 按照实际的需求决定加不加
case 常量2: 语句块2;
break;
...
case 常量n: 语句块n;
break;
default: 语句块;
//break; // 最后面的这个 break 可以不加,因为位置在最后,执行完直接就跳出了switch case
}
[图片上传失败...(image-d1fe43-1607962841160)]
- 根据 switch 表达式中的值,依次匹配各个 case 中的常量。一旦匹配成功,则进入相应的 case 结构中,执行该case中的语句块。当执行完语句块后,如果没有遇见 break关键字或到了此switch语句的结果处,则仍然向下执行其他的case结构中的语句块。直到遇到break关键字或到了此switch-case结构末尾结束为止。
- break,可以使用在 switch-case 结构中,表示一旦执行到此关键字,就跳出 switch-case 结构。
- switch 结构中 [switch(表达式)] 的表达式的结果,只能是如下6种类型:
byte
short
char
int
枚举类型 (JDK5.0新增的支持类型)
String类型 (JDK7.0新增的支持类型)
- case 之后 只能声明常量,不能设定(声明)范围
- break 关键字是可选的。根据实际情况来判定是否需要 break
- default 相当于 if-else 结构中的 else 。
default 可选的,根据实际情况来决定要不要编写 default:
default 的位置是灵活的。(可以放在最后面,也可以放在case 前面,也可以放在 case 和 case 中间),
但是不管位置在哪里,都是最后执行的。需要注意的是,放在前面或者中间位置,需要添加break关键字.
(3)if和switch语句很像,具体什么场景下,应用哪个语句呢?
如果判断的具体数值不多,而且符合byte、short 、char、int、String、枚举等几种类型。虽然两个语句都可以使用, 建议使用switch语句。因为效率稍高。
其他情况:对区间判断,对结果为boolean类型判断,使用if,if的使用范围更广。 也就是说,使用switch-case的,都可以改写为if-else。反之不成立。
3.循环结构
在某些条件满足的情况下,反复执行特定代码的功能。
java中循环的分类:
for 循环
while 循环
do-while 循环
循环语句的四个组成部分:
初始化部分(init_statement)
循环条件部分(test_exp)
循环体部分(body_statement)
迭代部分(alter_statement)
[图片上传失败...(image-2cfb25-1607962841160)]
(1) for 循环
语法:
for (①初始化部分; ②循环条件部分; ④迭代部分){
③循环体部分;
}
执行过程:
1. 先执行 :
① 初始化部分 (该部分只会被执行一次)
2. 在执行:
② 循环条件部分 (该部分的结果值必须是 boolean 类型的)
循环条件成立 则 执行 ③循环体部分
循环条件不成立,则退出循环不执行。
3. ③循环体部分 执行完后 执行:
④迭代部分
-
执行 ② 循环条件部分
循环条件成立 则 执行 ③循环体部分
循环条件不成立,则退出循环不执行。
......
[图片上传失败...(image-ec204a-1607962841142)]
说明:
②循环条件部分 为 boolean类型表达式,当值为false时,退出循环;
①初始化部分 可以声明多个变量,但必须是同一个类型,用逗号分隔;
④迭代部分 可以有多个变量更新,用逗号分隔;
(2) while 循环
语法:
①初始化部分
while(②循环条件部分){
③循环体部分;
④迭代部分;
}
执行过程:
先执行:
①初始化部分 (该部分只会被执行一次)
然后执行:
②循环条件部分 -----> 循环条件是 boolean 类型
注意:循环条件为 false 时,不会进入循环执行 ③ 和 ④
循环条件为 true 时,才会进入循环执行 ③ 和 ④
在执行:
③循环体部分;
④迭代部分;
......
说明:
1. 注意不要忘记声明④迭代部分。否则,循环将不能结束,变成死循环。
2. for循环和while循环可以相互转换</pre>
(3) do-while循环
语法:
①初始化部分;
do{
③循环体部分
④迭代部分
}while(②循环条件部分);
执行过程:
先执行 :
①初始化部分 (该部分只会被执行一次)
然后执行:
③循环体部分;
④迭代部分;
然后执行:
②循环条件部分 -----> 循环条件的类型一定是 boolean
说明:
循环条件的结果为 false ,则不继续执行 ③ 和 ④
循环条件的结果为 true ,则继续执行 ③ 和 ④
然后执行:
③循环体部分;
④迭代部分;
......
说明:
1. do-while循环至少执行一次循环体。
- 开发中,使用 for 和 while 较多,使用 do-while 较少。
(4) 无限循环
最简单“无限” 循环格式:
方式一:while(true) {}
方式二:for(;;){}
无限循环存在的原因是并不知道循环多少次,需要根据循环体内部某些条件,来控制循环的结束。
结束循环的两种方式:
方式一:使循环条件部分的值变为 false
方式二:在循环体中,使用 break 关键字
(5) 嵌套循环(多重循环)
将一个循环放在另一个循环体内,就形成了嵌套循环。其中:for ,while ,do-while 均可以作为外层循环或内层循环。
实质上,嵌套循环就是把内层循环当成外层循环的循环体。当只有内层循环的循环条件为false时,才会完全跳出内层循环,才可结束外层的当次循环,开始下一次的循环。
设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。
总结:
嵌套循环的使用
1. 嵌套循环:将一个循环结构A声明在另一个循环结构B的循环体中,就构成了嵌套循环
2. 外层循环:循环结构B
内层循环:循环结构A</pre>
说明 ① 内层循环结构遍历一遍,只相当于外层循环循环体执行了一次 ② 假设外层循环需要执行m次,内层循环需要执行n次。此时内层循环的循环体一共执行了m * n次
技巧: 外层循环控制行数,内层循环控制列数
4. 特殊关键字的使用 break | continue
关键字 | 使用范围 | 循环中使用的作用(不同点) | 相同点 |
---|---|---|---|
break | switch-case | ||
循环结构中 | 结束当前循环 | 关键字后面不能声明执行语句 | |
continue | 循环结构中 | 结束当次循环 | 关键字后面不能声明执行语句 |
数组
1.数组的概念
数组(Array),是多个 相同类型数据 按 一定顺序排列的集合 ,并使用 一个名字命名,并通过 编号 的方式对这些数据进行统一的管理。
2.数组相关的概念
数组名
元素
下标(角标、索引)
数组的长度:也就是一个数组中元素的个数
3.数组的特点
(1) 数组是有序排列的
(2) 数组属于 引用数据类型 的变量,但是数组中的元素,既可以是基本数据类型,也可以是引用数据类型。
(3) 创建数组的对象时,会在内存中开辟一块连续的空间。
(4) 数组的长度一旦确定就不能修改。
4.数组的分类
(1) 按照维数:一维数组、二维数组、三维数组、......
(2) 按照数组元素的类型:基本数据类型元素的数组、引用数据类型元素的数组。
5.一维数组
(1) 使用
a 如何 声明和初始化 一维数组
b 如何调用 数组 的指定位置的元素
c 如何获取数组的长度
d 如何遍历数组
e 数组元素的默认初始化值是多少?
f 数组的内存解析
a 如何 声明和初始化 一维数组
//1.1 静态初始化的方式:数组的初始化和数组的赋值操作同时进行
int[] ids = new int[]{1001,1002,1003,1004};
//先声明,在创建数组对象的方式
//int[] ids;
//ids = new int[]{1001,1002,1003,1004};
//1.2 动态初始化的方式:数组的初始化和数组的赋值操作分开进行
String[] names = new String[4];
//先声明,在创建数组对象的方式
//String[] names;
//names = new String[4];</pre>
//一维数组的错误写法:
int[] arr1 = new int[]; //动态实例化数组,不指定长度的错误写法。
int[5] arr2 = new int[]; //动态实例化数组,将长度的位置写错了位置。
int[15] arr3 = new int[15]; //动态实例化数组,将数组的长度也写在了 声明数组的位置
int[] arr4 = new int[2]{1,2}; //静态和动态初始化数组的方式进行了混合使用的错误写法
总结:一维数组一旦初始化(实例化)完成,数组的长度就确定了。
b 如何调用数组给指定位置的角标赋值元素:通过角标的方式调用
//2.如何调用数组给指定位置的角标赋值元素:通过角标的方式调用
//数组的角标 从0开始,到数组的 长度 - 1 结束。
names[0] = "张零";
names[1] = "张一";
names[2] = "张二";
names[3] = "张三";</pre>
总结: 数组的角标 从 0 开始,到数组 的 长度 - 1 结束。
如:
int[] arr = new int[5]; // 声明数组,并设定数组的 长度为 5
上述代码中的数组角标 分别是: 0 1 2 3 4
c 如何获取数组的长度
int length = names.length;
System.out.println("names数组的长度是:" + length);</pre>
总结:获取数组的长度,通过数组提供的 属性 length 获取。
d 如何遍历数组
System.out.print("names数组的遍历结果是:");
for (int i = 0; i < names.length ; i++) {
System.out.print(names[i] + " ");
}
System.out.println();</pre>
总结:遍历数组,获取数组中的元素,需要使用 数组名[角标] 的方式获取,该角标所对应的数组元素。
e 数组元素的默认初始化值
总结:
数组元素为 整型 (byte short int long)时,数组元素的默认值: 0
数组元素为 浮点型 (float double)时,数组元素的默认值: 0.0
数组元素为 字符型 (char)时,数组元素的默认值:0 或写为:’\u0000’(表现为空)
数组元素为 布尔型 (boolean)时,数组元素的默认值:false
数组元素为 引用数据类型 (String Integer 等)时,数组元素的默认值:null
//整型元素
//(1) 演示 数组中 元素为 byte 型时,默认值是多少? 答: 0
byte[] arrByte = new byte[3];
System.out.print("数组中元素为byte时,默认值为:");
for (int i = 0; i < arrByte.length ; i++) {
System.out.print(arrByte[i] + " ");
}
System.out.println();
//(2) 演示 数组中 元素为 short 型时,默认值是多少? 答: 0
short[] arrShort = new short[3];
System.out.print("数组中元素为short时,默认值为:");
for (int i = 0; i < arrShort.length ; i++) {
System.out.print(arrShort[i] + " ");
}
System.out.println();
//(3) 演示 数组中 元素为 int 型时,默认值是多少? 答: 0
int[] arrInt = new int[3];
System.out.print("数组中元素为int时,默认值为:");
for (int i = 0; i < arrInt.length ; i++) {
System.out.print(arrInt[i] + " ");
}
System.out.println();
//(3) 演示 数组中 元素为 long 型时,默认值是多少? 答: 0
long[] arrLong = new long[3];
System.out.print("数组中元素为long时,默认值为:");
for (int i = 0; i < arrLong.length ; i++) {
System.out.print(arrLong[i] + " ");
}
System.out.println();
/**
* 总结:数组中元素为 整型时(byte、short、int), 这默认的初始化值为 0
*/
//浮点型元素
//(1)演示 数组中 元素为 float 型时,默认值是多少? 答: 0.0
float[] arrFloat = new float[4];
System.out.print("数组中元素为 float 时,默认值为:");
for (int i = 0; i < arrFloat.length ; i++) {
System.out.print(arrFloat[i] + " ");
}
System.out.println();
//(2)演示 数组中 元素为 double 型时,默认值是多少? 答: 0.0
double[] arrDouble = new double[3];
System.out.print("数组中元素为 double 时,默认值为:");
for (int i = 0; i < arrDouble.length ; i++) {
System.out.print(arrDouble[i] + " ");
}
System.out.println();
/**
* 总结:数组中的元素 为 浮点型时,数组元素的默认值为: 0.0
*/
//字符型元素:char
//演示 数组中 元素为 char 型时,默认值是多少? 答:0 或写为:’\u0000’(表现为空)
char[] arrChar = new char[5];
System.out.print("数组中元素为 char 时,默认值为:");
for (int i = 0; i < arrChar.length ; i++) {
System.out.print("-*" + arrChar[i] + "*- ,");
}
System.out.println();
//打印的结果像是一个 空格,那我们测试下这 像空格 的代表的是 0 么
if(arrChar[0] == 0){
System.out.println("arrChar[0] 的元素就是等于 0 ");
}
/**
* 总结:数组中的元素为 char 型时,数组元素的默认值为: 0 或写为:’\u0000’(表现为空)
*/
//boolean 型元素
//演示 数组中 元素为 boolean 型时,默认值是多少? 答:false
boolean[] arrBoolean = new boolean[2];
System.out.print("数组中元素为 boolean 时,默认值为:");
for (int i = 0; i < arrBoolean.length ; i++) {
System.out.print(arrBoolean[i] + " ");
}
System.out.println();
/**
* 总结: 数组中元素为 boolean 时,数组的默认值为:false
*
* 因为在二进制的底层, false 是用 0 表示的。所以,这里自然而然的默认结果就是 false
*/
//引用型元素时,数组的默认值为:null 注意不是 'null' 或者 "null"
//(1) 演示 String
String[] arrString = new String[5];
System.out.print("数组中的元素类型为引用数据类型时(String),数组的默认值为:");
System.out.println(arrString[1]);
//(2) 演示 Integer
Integer[] arrInteger = new Integer[3];
System.out.print("数组中的元素类型为引用数据类型时(Integer),数组的默认值为:");
System.out.println(arrInteger[1]);
/**
* 总结:数组中的元素类型为 Integer 时,数组元素的默认值为: null 而不是为 "null"
*/
//演示 引用数据类型的值到底是 null 还是 "null"
if(arrString[0] == "null"){
System.out.println("我是双引号的 null");
}else{
System.out.println("我是没有带引号的 null");//执行结果为 这个
}
f 数组的内存解析
1) 内存的简单图示
内存中简单的换份为了 三份空间:
- 栈 空间: 用来存放 局部变量。 (局部变量就是出现在方法中的变量)
- 堆 空间: 用来存放 new 出来的结构(对象、数组)
- 方法区 空间:包括了 常量池、静态域
[图片上传失败...(image-5dbb32-1607962841158)]
2)一维数组的内存解析
int[] arr = new int[]{1,2,3};
String[] arr1 = new String[4];
arr1[1] = "刘德华";
arr1[2] = "张学友";
arr1 = new String[3];
System.out.println(arr1[1]); // null
[图片上传失败...(image-9389c4-1607962841157)]
6.多维数组-二维数组
对于二维数组的理解,我们可以看成是一维数组arr1 又作为另一个一维数组 arr2 的元素而存在。其实,从底层的运行机制来看,其实没有多维数组。
(1) 使用
a 如何 声明和初始化 二维数组
b 如何调用 数组 的指定位置的元素
c 如何获取数组的长度
d 如何遍历数组
e 数组元素的默认初始化值是多少?
f 数组的内存解析
a 如何 声明和初始化 二维数组
//1.二维数组的 声明 和 初始化
//静态方式:一维数组
int[] arrOne = new int[]{20,30,40};
//静态方式:二维数组
int[][] arrTwo = new int[][]{{10,20,30},{50,60},{100,300,600}};//标准写法
int arrTwo1[][] = new int[][]{{10,20,30},{50,60},{100,300,600}};//扩展写法
int[] arrTwo2[] = new int[][]{{10,20,30},{50,60},{100,300,600}};//扩展写法
/**
* 解析二维数组:
* 有三个一维数组
* 这三个一维数组中存放了 另外一个数组
* arrTwo[0] 中存放了 {10,20,30} 三个元素的数组
* arrTwo[1] 中存放了 {50,60} 二个元素的数组
* arrTwo[2] 中存放了 {100,300,600} 三个元素的数组
*/
//动态方式:一维数组
int[] arrOne1 = new int[5];
//动态方式1:二维数组 表示3个一维数组中,分别存放了一个元素个数为2的一维数组。
String[][] arrTwo11 = new String[3][2];//标准写法
String arrTwo12[][] = new String[3][2];//扩展写法
String[] arrTwo13[] = new String[3][2];//扩展写法
//动态方式2:二维数组 表示3个一维数组中,还没有存放一维数组
String[][] arrTwo22 = new String[3][];//标准写法
String arrTwo23[][] = new String[3][];//扩展写法
String[] arrTwo24[] = new String[3][];//扩展写法
//二位数组错误的声明 和 赋值演示
//String[][] arr1 = new String[][4];
//String[][] arr2 = new String[][4];
//String[4][] arr3 = new String[][];
//String[][2] arr4 = new String[][];
//String[5][2] arr5 = new String[][];
//String[][] arr6 = new String[2][2]{{1,2},{1,2}};
b 如何调用数组给指定位置的角标赋值元素:通过角标的方式调用
//静态方式:二维数组
int[][] arrTwo = new int[][]{{10,20,30},{50,60},{100,300,600}};//标准写法
//动态方式1:二维数组 表示3个一维数组中,分别存放了一个元素个数为2的一维数组。
String[][] arrTwo1 = new String[3][2];//标准写法
//动态方式2:二维数组 表示3个一维数组中,还没有存放一维数组
String[][] arrTwo2 = new String[3][];//标准写法
//2.如何调用 二位数组 的指定位置的 元素
//调用 arrTwo 数组中的 {{10,20,30},{50,60},{100,300,600}} 的 第0个数组中的第1个元素
System.out.println(arrTwo[0][1]);//20
//调用 arrTwo11 数组中的 第 1 个一维数组中 存放的 一维数组的 第 1 个元素
System.out.println(arrTwo1[1][1]);//null
//如何给数组赋值
//arrTwo2[0] = new int[2];//编译报错,因为 arrTwo2 数组的类型是 String
arrTwo2[0] = new String[2];// 给 arrTwo2 的数组 的 外层 下标0 的元素赋值 一个长度为2的空数组。
arrTwo2[0][1] = "ni"; //给 arrTwo2 的数组 的 外层 下标0 的元素中的数组下标1的元素赋值。
System.out.println(arrTwo2[0][1]);//ni
c 如何获取数组的长度
//3.获取二位数组的长度
//获取arrTwo数组的长度:int[][] arrTwo = new int[][]{{10,20,30},{50,60},{100,300,600}};
System.out.println(arrTwo.length);//3
//获取二维数组中外层一维数组的下标1的元素中存放的数组的长度。
System.out.println(arrTwo[1].length);//2
//获取二维数组中外层一维数组的下标0的元素中存放的数组的长度。
System.out.println(arrTwo[0].length);//3
//获取二维数组中外层一维数组的下标2的元素中存放的数组的长度。
System.out.println(arrTwo[2].length);//3
d 如何遍历数组
//4.如何遍历二维数组
//遍历 arrTwo 数组 :int[][] arrTwo = new int[][]{{10,20,30},{50,60},{100,300,600}};
//arrTwo.length 获取数组的长度
for (int i = 0; i < arrTwo.length ; i++) {
System.out.print("arrTwo[" + i + "] = ");
//arrTwo[i].length 获取外层数组中元素数组的长度。
for (int j = 0; j < arrTwo[i].length ; j++) {
System.out.print(arrTwo[i][j] + ",");
}
System.out.println();
}
e 数组元素的默认初始化值
//1.整数类型 byte short int long ,我们使用 int 来举例
int[][] arr = new int[3][2];
System.out.println(arr);//[[I@4554617c
/**
* [[I@4554617c 表示地址值。
* 剖析地址值:
* [[ 表示这个是一个 二维数组
* I 表示 这个数组的类型是 int 型的
* @ 中间连接的词语(我认为跟 微信群聊的@ 是一个意思)
* 4554617c 表示这个二维数组的地址值
*/
System.out.println(arr[0]);//[I@74a14482 外层的数组也是地址值
//为什么外层的数组也是个地址值呢?
//答:因为外层数组存放的元素也是个数组,需要通过地址值去找内层的数组中的元素
/**
* [I@74a14482
* [ : 表示对象是个一维数组
* I :表示数组的类型为 int
*/
System.out.println(arr[0][0]); // 0
System.out.println("------------------------ 浮点类型 -----------------------------");
//2.浮点类型 double float ,使用 float 举例
float[][] arr1 = new float[3][2];
System.out.println(arr1);//地址值
System.out.println(arr1[0]);//地址值
System.out.println(arr1[0][0]);//0.0
System.out.println("------------------------ 字符类型 -----------------------------");
//3.字符类型 char
char[][] arr2 = new char[3][2];
System.out.println(arr2);//地址值
System.out.println(arr2[1]);//地址值?
System.out.println(arr2[0][0]);//0 或写为:’\u0000’(表现为空)
System.out.println("------------------------ 布尔类型 -----------------------------");
//4.布尔类型 boolean
boolean[][] arr3 = new boolean[3][2];
System.out.println(arr3);//地址值
System.out.println(arr3[1]);//地址值
System.out.println(arr3[0][0]);//false
System.out.println("------------------------ 引用类型 -----------------------------");
String[][] arr4 = new String[3][2];
System.out.println(arr4);//地址值 [[Ljava.lang.String;@135fbaa4
System.out.println(arr4[1]);//地址值 [Ljava.lang.String;@45ee12a7
System.out.println(arr4[0][0]);//null
System.out.println("------------------------ [3][] -----------------------------");
//演示 int[][] arr5 = new int[3][];
int[][] arr5 = new int[3][];
System.out.println(arr5[0]);//null 因为数组是引用数据类型,在外层数组中么有元素的情况下,则为 null
System.out.println(arr5[0][0]);//报错:空指针异常java.lang.NullPointerException
f 数组的内存解析
二维数组的内存解析---图一:
[图片上传失败...(image-ec253f-1607962841155)]
二维数组内存解析 --- 图2:
[图片上传失败...(image-148e44-1607962841155)]
二维数组内存解析 --- 图3:
[图片上传失败...(image-5f2749-1607962841155)]
复习一维数组内存图:将代码转换为内存图
public class TestQuestions2 {
public static void main(String[] args){
int[] array1 = new int[]{2,3,5,7,11,13,17,19};
System.out.print("显示array1数组中的元素:");
for (int i = 0; i < array1.length ; i++) {
System.out.print(array1[i] + " ");
}
System.out.println();
// array1 和 array2 指向了同一个 堆内存空间
//注意:这个操作不能称为是数组的复制,因为此操作,堆内存中仅仅只有一块数组存储空间。
int[] array2 = array1;
for (int i = 0; i < array2.length ; i++) {
if (i % 2 == 0){
array2[i] = i;
}
}
//遍历 array1 和 遍历 array2 的结果是一样的
System.out.print("array1 数组中的元素:");
for (int i = 0; i < array1.length ; i++) {
System.out.print(array1[i] + " ");
}
System.out.println();
System.out.print("array2 数组中的元素:");
for (int i = 0; i < array2.length ; i++) {
System.out.print(array2[i] + " ");
}
System.out.println();
}
}
[图片上传失败...(image-269bfc-1607962841154)]
7.数组中涉及到的算法
算法相关的请关注 数据结构和算法 相关内容的文档(待上传)。
(1) 数组中涉及的常见算法
数组元素的赋值(杨辉三角、回形数等)
求数值型数组中元素的最大值、最小值、平均数、总和等
-
数组的复制、反转、查找(线性查找、二分法查找)
[图片上传失败...(image-fde2e3-1607962841141)]
数组元素的排序算法
(2) 十大内部排序算法
-
选择排序
直接选择排序
堆排序
-
交换排序
冒泡排序
快速排序
-
插入排序
直接插入排序
折半插入排序
Shell排序
归并排序
桶式排序
基数排序
8. Arrays工具类的使用
Java 类库中提供的:
在 java.util.Arrays 包 , 需要时去查询相关的API,这里不做过多的说明。
9. 数组使用中的常见异常
数组脚标越界异常 (ArrayIndexOutOfBoundsException)
int[] arr = new int[2];
System.out.println(arr[2]);
System.out.println(arr[-1]);
//访问到了数组中的不存在的脚标时发生
空指针异常 (NullPointerException)
int[] arr = null;
System.out.println(arr[0]);
//arr引用没有指向实体,却在操作实体中的元素时。