Java三大版本
JAVA最大的特点:
Java的主要优势在于其做出的WORA:即一次编写(Write Once)、随处运行(Run Anywhere)。简单来讲,这意味着开发团队能够利用Java编写一款应用程序,并将其编译为可执行形式,而后将其运行 在任何支持Java的平台之上。这显然能够极大提高编程工作的实际效率,这种优势来源于Java Virtual Machine(JAVA虚拟机的缩写),JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在 实际的计算机上仿真模拟各种计算机功能来实现的。JAVA语言的一个非常重要的特点就是与平台的无关 性,而使用Java虚拟机是实现这一特点的关键。
JAVA三大版本:
JAVA SE:它是JAVA的标准版,是整个JAVA的基础和核心,这是我们主要学习的一个部分,也是 JAVAEE和JAVAME技术的基础,主要用于开发桌面应用程序。学会后可以做一些简单的桌面应用 如:扫雷,连连看等。
JAVA ME:它是JAVA的微缩版,主要应用于嵌入式开发,比如手机程序的开发。目前来说就业范围不是很广,在一些城市可能相对的不好找工作。
JAVA EE:也叫JAVA的企业版,它提供了企业级应用开发的完整解决方案,比如开发网站,还有企业的一些应用系统,是JAVA技术应用最广泛的领域。主要还是偏向于WEB的开发,而JAVA EE的基础就是JAVA SE,所以我们在学习JAVA SE的时候,基础一定要打好,因为这是最基本的,也是最核 心的。
JDK 和 JRE
JDK
Java 2 SDK (Development Kit)包含:JRE的超集,包含编译器和调试器等用于程序开发的文件
JRE
Java Runtime Environment (JRE) 包含:Java虚拟机、库函数、运行Java应用程序和Applet所必须文件
Java运行环境的三项主要功能:
加载代码:由class loader 完成;
校验代码:由bytecode verifier 完成;
执行代码:由 runtime interpreter完成。
区别和联系:
sdk(也就是jdk)是jre的超集,是在jre的基础上增加了编译器及其他一些开发工具。
jre就是java运行时环境,包括了jvm和其它一些java核心api,任何一台电脑,只有安装了jre才可以行 java程序.
如果只是要运行JAVA程序,之需要JRE就可以。 JRE通常非常小,也包含了JVM.
如果要开发JAVA程序,就需要安装JDK。
JVM(JAVA Virtual Machine)
JVM是一种规范,可以使用软件来实现,也可以使用硬件来实现,就是一个虚拟的用于执byte-codes 字节码的计算机。他也定义了指令集、寄存器集、结构栈、垃圾收集堆、内存区域。
JVM负责将java字节码解释运行,边解释边运行,这样,速度就会受到一定的影响。JAVA提供了另一种 解释运行的方法JIT(just in time),可以一次解释完,再运行特定平台上的机器码,高级的JIT可以只能 分析热点代码,并将这些代码转成本地机器码,并将结果缓存起来,下次直接从内存中调用,这样就大 大提高了执行JAVA代码的效率。这样就实现了跨平台、可移植的功能。
1.JVM是指在一台计算机上由软件或硬件模拟的计算机;它类似一个小巧而高效的CPU。
2.byte-code代码是与平台无关的是虚拟机的机器指令。
3.java字节代码运行的两种方式:
interpreter(解释)
运行期解释字节码并执行
Just-in-time(即时编译)
由代码生成器将字节代码转换成本机的机器代码,然后可以以较高速度执行。
JAVA的跨平台实现的核心是不同平台使用不同的虚拟机
不同的操作系统有不同的虚拟机。Java 虚拟机机制屏蔽了底层运行平台的差别,实现了“一次编译,随处运行”。
JAVA程序运行机制
说到Java的运行机制,不得不提一下什么是编译型语言,什么是解释型语言。
编译型语言
编译型语言是先将源代码编译成机器语言(机器可以读懂的语言),再由机器运行机器码,这样执行程序的效率比较高。像C和C++就是典型的编译型语言。
解释型语言
其实解释型语言是相对编译型语言存在的,解释型语言是在运行的时候才进行编译,每次运行都需要编译,这样效率比较低。像JavaScript,Python就是典型的解释型语言
二者的区别
简单的举个例子:同样一本英文书,找人翻译成中文版的书然后拿给你看就是编译,找一个翻译员在你旁边给你解读书的含义就是解释。两者各有利弊,编译型语言执行效率高,翻译一次可以多次运行。解释性语言执行效率低,每次运行都需要重新翻译。但是解释型的跨平台性相对要好,比如解释给一个懂中文和解释给一个懂日文的人就叫做兼容性。
Java的运行机制
Java属于两者都有,既有编译过程,又是解释型语言
Java语言虽然比较接近解释型语言的特征,但在执行之前已经预先进行一次预编译,生成的代码是介 于机器码和Java源代码之间的中介代码,运行的时候则由JVM(Java的虚拟机平台,可视为解释器)解 释执行。它既保留了源代码的高抽象、可移植的特点,又已经完成了对源代码的大部分预编译工作,所以 执行起来比“纯解释型”程序要快许多。
总之,随着设计技术与硬件的不断发展,编译型与解释型两种方式的界限正在不断变得模糊。
JavaSE基础元素与数组
一、Java基础元素
1. Java的注释
单行注释
//注释的内容
多行注释
/*
注释内容
*/
注意:多行注释不能嵌套
文档注释
/**
文档注释内容
*/
2. 关键字
关键字:50个,系统保留字。
3. 标识符
标识符:凡是代码中自己命名的部分,例如:类名,变量名等
标识符的命名规则:
1)由26个英文字母大小写,数字0-9,下划线_,美元符号$
2)数字不能开头
3)不能直接使用关键字和保留字、特殊值
4)严格区分大小写
5)不能包含空格
标识符的命名规范:
1)见名知意
2)类名、接口名:每一个单词的首字母大写,XxxYyyZzz
3)变量名、方法名:从第二个单词开始首字母大写,xxxYyyZzz
4)包名:所有单词都小写,每个单词使用.分割,xxx.yyy.zzz
5)常量名:所有字母都大写,每个单词之间使用_分割,XXX_YYY_ZZZ
4. 常量与变量
4.1. 常量
常量:在程序执行的过程中,其值不可以发生改变的量
常量的分类:
1)自定义常量:通过final关键字定义(后面在面向对象部分讲解)
2)字面值常量:
字面值常量 | 举例 |
---|---|
字符串常量 | ”HelloWorld“ |
整数常量 | 12,-23 |
浮点常量 | 12.34 |
字符常量 | ‘a’,‘0’,‘我’ |
布尔常量 | true,false |
空常量 | null |
4.2. 变量
变量:用来存储数据的,代表内存的一块区域
变量的三要素:
1)数据类型
2)变量名
3)变量值
如何声明/定义变量?
数据类型 变量名;
变量的赋值:
变量名 = 变量值;
变量使用的四个要求:
1)先声明/定义后使用
2)不能重复声明
3)在使用之前必须先初始化
4)变量有作用域
5. 数据类型
5.1. 数据类型分类
1)基础数据类型
- 整型:byte、short、int、long;特殊:在long类型的数字后面加L或l
- 浮点型:float、double;特殊:在float类型的数字后面加F或f
- 字符型:char;特殊:需要使用单引号
- 布尔型:boolean;特殊:只有两个值true和false
2)引用数据类型
- 例如:String,自定义类、接口,枚举,数组,…
5.2. 数据类型表示范围
1)byte
- 占的内存:1个字节
- 范围:-128~127
2)short
- 占的内存:2个字节
- 范围:-32768~32767
3)int
- 占的内存:4个字节
- 范围:-2的31次方 ~ 2的31次-1
4)long
- 占的内存:8个字节
- 范围:-2的63次方 ~ 2的63次-1
- 某个常量数字要表示为long类型,在数字后面加L
5)float
- 占的内存:4个字节
- 精度范围:科学记数法小数点后7~8位
- 某个常量数字要表示为float类型,在数字后面加F或f
6)double
- 占的内存:8个字节
- 精度范围:科学记数法小数点后15~16位
7)char
- 占的内存:2个字节
- 字符编码范围:0~65535
- 使用的是Unicode字符集
- 程序中有三种字符表示方式:
- 单引号中加单个字符:‘a’,‘尚’
- 单引号中加转义字符:\n,\t,\r,\b,,',"
- 单引号中加编码值:\u5c1a’
8)boolean
- 两个值:true和false
- 实际上底层是使用1表示true,0表示false
5.3. 基本数据类型转换
1)自动类型转换
- 当我们把存储范围或精度范围小的赋值给存储范围或精度范围大的变量时
- 当我们把存储范围或精度范围小的与存储范围或精度范围大的类型一起运算时
- 当两个byte,short,char它们的运算会升级为int
- 当与String进行拼接“+”运算,结果都是String
2)强制类型转换
- 格式:(需要强制为的类型)值/变量
- 当我们把存储范围或精度范围大的赋值给存储范围或精度范围小的变量时(这种强制类型转换有风险,可能溢出或损失精度)
- 故意提升某个变量/值的类型,也可以使用强制类型转换
- 无论是自动类型转换还是强制类型转换:boolean不参与
6. 两种输出
输出并换行
System.out.println();
System.out.println(xx);
输出不换行
System.out.print(xx);
7. 运算符
7.1. 算术运算符
1)加:+
2)减:-
3)乘:*
4)除:/
5)模/取余:%
6)正号:+
7)负号:-
8)自增:++
9)自减:–
7.2. 赋值运算符
基本赋值运算符:=
扩展赋值运算符:+=,-=,*=,/=,%=,>>=,<<=,&=…
注意:无论是基本赋值运算符还是扩展赋值运算符都是最后算,并且是把右边的计算的结果最后赋值给左边的变量,即左边一定是一个变量
byte b1 = 1;
byte b2 = 2;
byte b3 = b1 + b2;//编译错
b1 += b2;//编译通过
7.3. 关系运算符/比较运算符
1)大于:>
2)小于:<
3)大于等于:>=
4)小于等于:<=
5)等于:==
6)不等于:!=
注意:所有比较运算符的结果都是true/false,所以比较运算符通常用作条件判断
7.4. 逻辑运算符
1)逻辑与:&
2)逻辑或:|
3)逻辑非:!
4)逻辑异或:^
5)短路与:&&
6)短路或:||
注意:逻辑运算符的操作数必须是boolean类型
7.5 条件运算符/三元运算符
格式:条件表达式 ? 结果表达式1 : 结果表达式2
当条件表达式为true时,就取结果表达式1的值,否则取结果表达式2的值
7.6 位运算符
Java定义了位运算符,应用于整数类型(int),长整型(long),短整型(short),字符型(char),和字节型 (byte)等类型。位运算符作用在所有的位上,并且按位运算。
1)左移:<<
2)右移:>>
3)无符号右移:>>>
4)按位与:&
5)按位或:|
6)按位异或:^
7)按位取反:~
注意:当左移、右移、无符号右移要移动的位数超过数据类型的总位数,那么会出现循环,当你移的位数没有超过数据类型的总位数时,不会出现循环。这里要注意,byte,short,char在移位时,按照int类型处理。
右移一位相当于除2取商。
左移一位相当于乘2。
假设a = 60,b = 13;它们的二进制格式表示将如下:
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100
A | B = 0011 1101
A ^ B = 0011 0001
~A= 1100 0011
7.7 运算符优先级
大体上:()等 > 算术运算符 > 位运算符 > 比较运算符 > 逻辑运算符 > 条件运算符 > 赋值运算符
自己写的原则:尽量不要太复杂,保证可读性
7.8 字符串连接符
“+” 运算符两侧的操作数中只要有一个是字符串(String)类型,系统会自动将另一个操作数转换为字符串 然后再进行连接。
//字符串
String s1="Hello 中文!";
String s2=1+""; //转换成String
//int
int c = 12;
System.out.println("c=" + c);
8. 初识修饰符
修饰符主要分为:访问修饰符和非访问修饰符
1)访问修饰符:
-
访问修饰符用来定义类、方法或者变量的访问范围,通常放在语句的最前端。
-
包括:default、private、public、protected
2)非访问修饰符:
-
为了实现一些其他的功能,Java 也提供了许多非访问修饰符。
-
包括:static、final、abstract、synchronized等
注意:此处我们仅给出一个简单的修饰符概念,其详细情况会在后续章节讨论。
9. 变量 , 常量
1、变量(variable)
变量是什么:就是可以变化的量!
我们通过变量来操纵存储空间中的数据,变量就是指代这个存储空间!空间位置是确定的,但是里面放 置什么值不确定!
Java是一种强类型语言,每个变量都必须声明其类型。
Java变量是程序中最基本的存储单元,其要素包括变量名,变量类型和作用域。
变量在使用前必须对其声明, 只有在变量声明以后,才能为其分配相应长度的存储单元,声明格式为:
数据类型 变量名 = 值;
可以使用逗号隔开来声明多个同类型变量。
注意事项:
每个变量都有类型,类型可以是基本类型,也可以是引用类型。
变量名必须是合法的标识符。
变量声明是一条完整的语句,因此每一个声明都必须以分号结束
int a, b, c; // 声明三个int型整数:a、 b、c
int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值
byte z = 22; // 声明并初始化 z
String s = "runoob"; // 声明并初始化字符串 s
double pi = 3.14159; // 声明了双精度浮点型变量 pi
char x = 'x'; // 声明变量 x 的值是字符 'x'。
【编码规范】
虽然可以在一行声明多个变量,但是不提倡这个风格,逐一声明每一个变量可以提高程序可读性。
2、变量作用域
变量根据作用域可划分为三种:
类变量(静态变量: static variable):独立于方法之外的变量,用 static 修饰。
实例变量(成员变量:member variable):独立于方法之外的变量,不过没有 static 修饰。
局部变量(lacal variable):类的方法中的变量。
public class Variable{
static int allClicks = 0; // 类变量
String str = "hello world"; // 实例变量
public void method(){
int i =0; // 局部变量
}
}
局部变量
方法或语句块内部定义的变量。生命周期是从声明位置开始到 ”}” 为止
在使用前必须先声明和初始化(赋初值)。
局部变量没有默认值,所以局部变量被声明后,必须经过初始化,才可以使用。
实例变量
方法外部、类的内部定义的变量。
从属于对象,生命周期伴随对象始终。
如果不自行初始化,他会自动初始化成该类型的默认初始值
(数值型变量初始化成0或0.0,字符型变量的初始化值是16位的0,布尔型默认是false)
静态变量
使用static定义。
从属于类,生命周期伴随类始终,从类加载到卸载。
如果不自行初始化,他会自动初始化成该类型的默认初始值
(数值型变量初始化成0或0.0,字符型变量的初始化值是16位的0,布尔型默认是false)
3、常量
常量(Constant):初始化(initialize)后不能再改变值!不会变动的值。
所谓常量可以理解成一种特殊的变量,它的值被设定后,在程序运行过程中不允许被改变。
final 常量名=值;
final double PI=3.14;
final String LOVE=“hello”;
Copy to clipboardErrorCopied
常量名一般使用大写字符。
程序中使用常量可以提高代码的可维护性。例如,在项目开发时,我们需要指定用户的性别,此时可以 定义一个常量 SEX,赋值为 “男”,在需要指定用户性别的地方直接调用此常量即可,避免了由于用户的 不规范赋值导致程序出错的情况。
4、变量的命名规范
所有变量、方法、类名:见名知意
类成员变量:首字母小写和驼峰原则 : monthSalary
局部变量:首字母小写和驼峰原则
常量:大写字母和下划线:MAX_VALUE
类名:首字母大写和驼峰原则: Man, GoodMan
方法名:首字母小写和驼峰原则: run(), runRun()
二、流程控制语句
流程控制语句结构分为:i)顺序结构;ii)分支结构;iii)循环结构
1. 顺序结构
特点:依次从上往下顺序执行
//1、准备键盘输入的变量
java.util.Scanner input = new java.util.Scanner(System.in);
//2、提示输入
System.out.print("姓名:");
String name = input.next();
System.out.print("年龄:");
int age = input.nextInt();
System.out.print("体重:");
double weight = input.nextDouble();
System.out.print("性别:");
char gender = input.next().charAt(0);
System.out.print("是否已婚(true/false):");
boolean marry = input.nextBoolean();
2. 分支结构
单分支条件判断
if(条件表达式){
语句块;
}
双分支条件判断
if(条件表达式){
语句块1;
}else{
语句块2;
}
多分支条件判断
if(条件表达式1){
语句块1;
}else if(条件表达式2){
语句块2;
}else if(条件表达式2){
语句块2;
}
嵌套
在任意一个if的{}或者else的{}中都可以再嵌套任意一种分支结构。执行原则:如果嵌套在if的{}中,当外面的if条件满足时,才会看里面的分支结构;如果嵌套在else的{}中,当外面的if条件不满足时,才会进入else里面的分支结构。
3. 选择结构
switch(表达式){
case 常量值1:
语句块1;
【break;】
case 常量值2:
语句块2;
【break;】
....
default:
语句块n+1;
【break;】
}
4. 循环结构
while循环
while(循环条件){
循环体语句块;
}
do…while循环
do{
循环体语句块;
}while(循环条件);
for循环
for(;;){
循环体语句块;
}
增强for循环
for(声明语句 : 表达式)
{
//代码句子
}
//eg:
for(int x : numbers ){
System.out.print( x );
System.out.print(",");
}
跳转
1)break: 用于switch,表示结束当前switch;用于循环,表示结束当前循环。(说明:如果break在嵌套循环的内循环中,只能结束内循环。)
2)continue: 用于循环,表示提前结束本次循环,同时跳过本次循环剩下的循环体语句块,提前进入迭代。
3)带标签的跳转: “标签”是指后面跟一个冒号的标识符,例如:label:
对Java来说唯一用到标签的地方是在循环语句之前。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另一个循环,由于break和continue关键字通常只中断当前循环,但若随同标签使用,它们就会中断到存在标签的地方。
三、数组
1. 数组的概念
数组就是用于存储数据的长度固定的容器,保证多个数据的数据类型要一致。
所谓数组(array),就是相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,以便统一管理他们,然后用编号区分他们,这个名字称为数组名,编号称为下标或索引(index)。组成数组的各个变量称为数组的元素(element)。数组中元素的个数称为数组的长度(length)。
数组的特点:
1)数组的长度一旦确定就不能修改
2)创建数组时会在内存中开辟一整块连续的空间。
3)存取元素的速度快,因为可以通过[下标],直接定位到任意一个元素。
2. 数组声明与初始化
数组的声明:
//推荐
元素的数据类型[] 二维数组的名称;
//不推荐
元素的数据类型 二维数组名[];
方式一:静态初始化
数据类型[] 数组名 = {元素1,元素2,元素3...};//必须在一个语句中完成,不能分开两个语句写
举例:
int[] arr = {1,2,3,4,5}; //正确
int[] arr;
arr = {1,2,3,4,5}; //错误
方式二:静态初始化
数组存储元素的数据类型[] 数组名字 = new 数组存储元素的数据类型[长度];
//或
数组存储元素的数据类型[] 数组名字;
数组名字 = new 数组存储元素的数据类型[长度];
举例:定义存储1,2,3,4,5整数的数组容器
int[] arr = new int[]{1,2,3,4,5}; //正确
int[] arr;
arr = new int[]{1,2,3,4,5}; //正确
int[] arr = new int[5]{1,2,3,4,5};//错误的,后面有{}指定元素列表,就不需要在[长度]指定长度。
方式三:动态初始化
数组存储的元素的数据类型[] 数组名字 = new 数组存储的元素的数据类型[长度];
//或
数组存储的数据类型[] 数组名字;
数组名字 = new 数组存储的数据类型[长度];
举例:定义可以存储5个整数的数组容器
int[] arr = new int[5];
int[] arr;
arr = new int[5];
3. 数组元素的访问
索引: 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。
索引范围:[0, 数组的长度-1]
格式:
数组名[索引]
索引访问数组中的元素:
1)数组名[索引]=数值,为数组中的元素赋值
2)变量=数组名[索引],获取出数组中的元素
public static void main(String[] args) {
//定义存储int类型数组,赋值元素1,2,3,4,5
int[] arr = {1,2,3,4,5};
//为0索引元素赋值为6
arr[0] = 6;
//获取数组0索引上的元素
int i = arr[0];
System.out.println(i);
//直接输出数组0索引元素
System.out.println(arr[0]);
}
4. 数组的遍历
数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语句为:数组名.length
,属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数组的最大索引值为数组名.length-1
。
数组遍历: 就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
//打印数组的属性,输出结果是5
System.out.println("数组的长度:" + arr.length);
//遍历输出数组中的元素
System.out.println("数组的元素有:");
for(int i=0; i<arr.length; i++){
System.out.println(arr[i]);
}
}
5. 二维数组
二维数组:本质上就是元素为一维数组的一个数组。
二维数组的标记:
int[][] arr; //arr是一个二维数组,可以看成元素是int[]一维数组类型的一个数组
二维数组也可以看成一个二维表,行*列组成的二维表,只不过这个二维表,每一行的列数还可能不同。但是每一个单元格中的元素的数据类型是一致的,例如:都是int,都是String等。
5.1. 二维数组的声明与初始化
//推荐
元素的数据类型[][] 二维数组的名称;
//不推荐
元素的数据类型 二维数组名[][];
//不推荐
元素的数据类型[] 二维数组名[];
静态初始化
元素的数据类型[][] 二维数组名 = new 元素的数据类型[][]{
{元素1,元素2,元素3 。。。},
{第二行的值列表},
...
{第n行的值列表}
};
元素的数据类型[][] 二维数组名;
二维数组名 = new 元素的数据类型[][]{
{元素1,元素2,元素3 。。。},
{第二行的值列表},
...
{第n行的值列表}
};
//以下格式要求声明与静态初始化必须一起完成
元素的数据类型[][] 二维数组的名称 = {
{元素1,元素2,元素3 。。。},
{第二行的值列表},
...
{第n行的值列表}
};
注意:如果是静态初始化,右边new 数据类型[][]中不能写数字,因为行数和列数,由{}的元素个数决定。
举例:
int[][] arr;
arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
arr = new int[3][3]{{1,2,3},{4,5,6},{7,8,9}};//错误,静态初始化右边new 数据类型[]中不能写数字
int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}}; //声明与初始化必须在一句完成
public class Array2Demo1 {
public static void main(String[] args) {
//定义数组
int[][] arr = {{1,2,3},{4,5},{6}};
System.out.println(arr);
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[0][0]); //1
System.out.println(arr[1][0]); //4
System.out.println(arr[2][0]); //6
System.out.println(arr[0][1]); //2
System.out.println(arr[1][1]); //5
//越界
System.out.println(arr[2][1]); //错误
}
}
动态初始化(规则二维表:每一行的列数是相同的)
//(1)确定行数和列数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[m][n];
m:表示这个二维数组有多少个一维数组。或者说一共二维表有几行
n:表示每一个一维数组的元素有多少个。或者说每一行共有一个单元格
//此时创建完数组,行数、列数确定,而且元素也都有默认值
//(2)再为元素赋新值
二维数组名[行下标][列下标] = 值;
public static void main(String[] args) {
//定义一个二维数组
int[][] arr = new int[3][2];
//定义了一个二维数组arr
//这个二维数组有3个一维数组的元素
//每一个一维数组有2个元素
//输出二维数组名称
System.out.println(arr); //地址值 [[I@175078b
//输出二维数组的第一个元素一维数组的名称
System.out.println(arr[0]); //地址值 [I@42552c
System.out.println(arr[1]); //地址值 [I@e5bbd6
System.out.println(arr[2]); //地址值 [I@8ee016
//输出二维数组的元素
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
//...
}
动态初始化(不规则:每一行的列数可能不一样)
//(1)先确定总行数
元素的数据类型[][] 二维数组名 = new 元素的数据类型[总行数][];
//此时只是确定了总行数,每一行里面现在是null
//(2)再确定每一行的列数,创建每一行的一维数组
二维数组名[行下标] = new 元素的数据类型[该行的总列数];
//此时已经new完的行的元素就有默认值了,没有new的行还是null
//(3)再为元素赋值
二维数组名[行下标][列下标] = 值;
public static void main(String[] args) {
//定义数组
int[][] arr = new int[3][];
System.out.println(arr); //[[I@175078b
System.out.println(arr[1][0]);//NullPointerException
System.out.println(arr[0]); //null
System.out.println(arr[1]); //null
System.out.println(arr[2]); //null
//动态的为每一个一维数组分配空间
arr[0] = new int[2];
arr[1] = new int[3];
arr[2] = new int[1];
System.out.println(arr[0]); //[I@42552c
System.out.println(arr[1]); //[I@e5bbd6
System.out.println(arr[2]); //[I@8ee016
System.out.println(arr[0][0]); //0
System.out.println(arr[0][1]); //0
//ArrayIndexOutOfBoundsException
//System.out.println(arr[0][2]); //错误
arr[1][0] = 100;
arr[1][2] = 200;
}
5.2. 二维数组的相关名称及其表示方式
二维数组的长度/行数: 二维数组名.length
二维数组的某一行:二维数组名[行下标];行下标的范围:[0, 二维数组名.length-1]
某一行的列数:二维数组名[行下标].length
某一个元素:二维数组名[行下标][列下标]
5.3. 二维数组的遍历
for(int i=0; i<二维数组名.length; i++){
for(int j=0; j<二维数组名[i].length; j++){
System.out.print(二维数组名[i][j]);
}
System.out.println();
}
6. Arrays 类
数组的工具类java.util.Arrays
由于数组对象本身并没有什么方法可以供我们调用,但API中提供了一个工具类Arrays供我们使用,从 而可以对数据对象进行一些基本的操作。
Arrays类中的方法都是static修饰的静态方法,在使用的时候可以直接使用类名进行调用,而"不用"使用对象来调用(注意:是"不用" 而不是 “不能”)
java.util.Arrays 类能方便地操作数组. 使用之前需要导包!
具有以下常用功能:
给数组赋值:通过 fill 方法。
对数组排序:通过 sort 方法,按升序。
比较数组:通过 equals 方法比较数组中元素值是否相等。
查找数组元素:通过 binarySearch 方法能对排序好的数组进行二分查找法操作。
练习题示例:
1、练习1
使用二维数组存储如下数据,并遍历显示
1
2 2
3 3 3
4 4 4 4
5 5 5 5 5
public static void main(String[] args){
//1、声明一个二维数组,并且确定行数
//因为每一行的列数不同,这里无法直接确定列数
int[][] arr = new int[5][];
//2、确定每一行的列数
for(int i=0; i<arr.length; i++){
/*
arr[0] 的列数是1
arr[1] 的列数是2
arr[2] 的列数是3
arr[3] 的列数是4
arr[4] 的列数是5
*/
arr[i] = new int[i+1];
}
//3、确定元素的值
for(int i=0; i<arr.length; i++){
for(int j=0; j<arr[i].length; j++){
arr[i][j] = i+1;
}
}
//4、遍历显示
for(int i=0; i<arr.length; i++){
for(int j=0; j<arr[i].length; j++){
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args){
//1、声明一个二维数组,并且初始化
int[][] arr = {
{1},
{2,2},
{3,3,3},
{4,4,4,4},
{5,5,5,5,5}
};
//2、遍历显示
for(int i=0; i<arr.length; i++){
for(int j=0; j<arr[i].length; j++){
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args){
//1、声明一个二维数组,并且确定行数
//因为每一行的列数不同,这里无法直接确定列数
int[][] arr = new int[5][];
for(int i=0; i<arr.length; i++){
//2、确定每一行的列数
arr[i] = new int[i+1];
//3、确定元素的值
for(int j=0; j<arr[i].length; j++){
arr[i][j] = i+1;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
2、练习2
请使用二维数组存储如下数据,并遍历显示
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
public static void main(String[] args){
int[][] arr = {
{1,1,1,1,1},
{2,2,2,2,2},
{3,3,3,3,3},
{4,4,4,4,4}
};
for(int i=0; i<arr.length; i++){
for(int j=0; j<arr[i].length; j++){
System.out.print(arr[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args) {
//1、声明二维数组,并确定行数和列数
int[][] arr = new int[4][5];
//2、确定元素的值
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length; j++) {
arr[i][j] = i + 1;
}
}
//3、遍历显示
for(int i=0; i<arr.length; i++){
for(int j=0; j<arr[i].length; j++){
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
3、练习3
请使用二维数组存储如下数据,并遍历显示
String[][] employees = {
{"10", "1", "段誉", "22", "3000"},
{"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
{"11", "3", "任我行", "23", "7000"},
{"11", "4", "张三丰", "24", "7300"},
{"12", "5", "周芷若", "28", "10000", "5000"},
{"11", "6", "赵敏", "22", "6800"},
{"12", "7", "张无忌", "29", "10800","5200"},
{"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
{"12", "9", "杨过", "26", "9800", "5500"},
{"11", "10", "小龙女", "21", "6600"},
{"11", "11", "郭靖", "25", "7100"},
{"12", "12", "黄蓉", "27", "9600", "4800"}
};
其中"10"代表普通职员,"11"代表程序员,"12"代表设计师,"13"代表架构师
public static void main(String[] args) {
String[][] employees = {
{"10", "1", "段誉", "22", "3000"},
{"13", "2", "令狐冲", "32", "18000", "15000", "2000"},
{"11", "3", "任我行", "23", "7000"},
{"11", "4", "张三丰", "24", "7300"},
{"12", "5", "周芷若", "28", "10000", "5000"},
{"11", "6", "赵敏", "22", "6800"},
{"12", "7", "张无忌", "29", "10800","5200"},
{"13", "8", "韦小宝", "30", "19800", "15000", "2500"},
{"12", "9", "杨过", "26", "9800", "5500"},
{"11", "10", "小龙女", "21", "6600"},
{"11", "11", "郭靖", "25", "7100"},
{"12", "12", "黄蓉", "27", "9600", "4800"}
};
System.out.println("员工类型\t编号\t姓名\t年龄\t薪资\t奖金\t股票\t");
for (int i = 0; i < employees.length; i++) {
switch(employees[i][0]){
case "10":
System.out.print("普通职员");
break;
case "11":
System.out.print("程序员");
break;
case "12":
System.out.print("设计师");
break;
case "13":
System.out.print("架构师");
break;
}
for (int j = 1; j < employees[i].length; j++) {
System.out.print("\t" + employees[i][j]);
}
System.out.println();
}
}
4. 冒泡排序
Java中的经典算法之冒泡排序(Bubble Sort)
原理:比较两个相邻的元素,将值大的元素交换至右端。
思路:依次比较相邻的两个数,将小数放到前面,大数放到后面。
1)即第一趟,首先比较第1个和第2个元素,将小数放到前面,大数放到后面。
2)然后比较第2个和第3个元素,将小数放到前面,大数放到后面。
3)如此继续,直到比较最后两个数,将小数放到前面,大数放到后面。
4)重复第一趟步骤,直至全部排序完成。
/*
* 冒泡排序
*/
public class BubbleSort {
public static void main(String[] args) {
int[] arr={6,3,8,2,9,1};
System.out.println("排序前数组为:");
for(int num:arr){
System.out.print(num+" ");
}
for(int i=0;i<arr.length-1;i++){//外层循环控制排序趟数
for(int j=0;j<arr.length-1-i;j++){//内层循环控制每一趟排序多少次
if(arr[j]>arr[j+1]){
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println();
System.out.println("排序后的数组为:");
for(int num:arr){
System.out.print(num+" ");
}
}
}
The End!!创作不易,欢迎点赞/评论!!欢迎关注个人公众号,获取完整MarkDown