1.数组
1.1 数组的定义
1 数组是相同数据的有序集合
2 描述的是相同类型的若干数据 按照一点过的先后顺序排列组合 , 其中每一个数据成为元素 ,每个元素都可以通过数组的索引或下标来定位
1.2 数组的特点 (掌握)
1 数组本身是引用数据类型 ,而数组中的元素可以使用任意类型(基本/引用)。
2 创建数组对象会在内存中开辟一块空间 ,空间是连续的, 数组名中引用的是这块连续空间的首地址。
3 数组的长度一旦确定就不能修改。
4 数组中存储的数据类型必须是相同的 不能出现混合类型。
1.3 数组的分类
维度: 一维数组 二维数组 三维数组……
数据类型:基本类型(整型数组、浮点型数组、布尔型数组……)、引用数据类型
2 一维数组
2.1 数组的创建和初始化
2.1.1数组的定义格式:
格式一: 数组类型 [ ] 变量名; // (掌握)
int[ ] arr //定义一个int型的一维数组 数组名为arr
格式二: 数据类型 变量名[ ];
2.1.2数据的初始化:
Java中的数组必须先初始化,然后才能使用
初始化: 为数组中的元素分配内存关键,并未每一个元素赋值
2.1.3 初始化方式
静态初始化、动态初始化
1 动态初始化
数组声明和数组元素的分配空间及赋值分开进行
格式如下:
数据类型[ ] 变量名 = new 数据类型 [数组的长度]
int[] arr = new int[5]
//表明声明了一个长度为5的整型数组
等号的左边: | 等号的右边; |
---|---|
int----数组的类型 | int 数组的类型,决定了数组中每个元素的空间大小 |
arr----是这个数组的名称 | new 位数组开辟内存空间 |
[ ] ----这是一个数组 | 5 表明数组的长度 |
索引是从0开始的 并且是连续的 直到数组的长度(length-1)
public static void main(String[] args) {
int[] arr = new int[5];
//赋值操作
arr[0]= 2;
arr[1]= 5;
arr[3] = 8;
//取值操作
int a1 = arr[0];
int a2 = arr[1];
int a3 =arr[3];
int a4 = arr[4];
//声明一个长度为6的字符串类型的数组,赋值
String[] arr = new String[6];
arr[0]= "马云";
arr[1]= "马化腾";
arr[2] = "雷军";
}
2 静态初始化:
在定义数组的同时就为数组元素分配空间并赋值
数据类型[] 变量名 = new 数据类型[] {数据1,数据2,……};
数据由“,”分开
此声明 :数组不需要指定长度 系统会根据给出的数据自动分配长度
简化格式: 数组类型[] 变量名={数据1,数据2,……};
//静态初始化:
int[] arrInt = new int[]{2,1,3,5,2,1,5,6};
String[] arrStr = {"aaa" ,"bbbb " , "cccc"};
2.2 数组的默认值
类型 | 默认值 |
---|---|
byte short int | 0 |
long | 0L |
float double | 0.0 |
char | “\u000” |
boolean | false |
String | null |
String为代表的引用类型为null
2.3 数组的长度
数组的一个属性 length
变量名.length // 获取数组长度
当数组的索引超过数组长度之后 会发生一个异常
3.内存管理
程序向jvm申请内存 jvm向操作系统申请内存
计算机内存是非常重要的组件 程序要运行 必须加载到内存中才可以运行 但是由于内存空间有限 当运行结束之后,要清空内存
java虚拟机要运行程序,必须对内存进行空间的分配和管理。
3.1 java中的内存分配
堆区:存储对象或数组 new出来的都在堆内存中。如果申请不到空间 则会抛出内存溢出异常
虚拟机栈; 栈里面是栈帧 每个栈帧对应一次方法的调用。栈帧中存放了局部变量表。(基本数据类型的变量和引用的对象)操作数栈,方法出露以及其他信息。
当栈的深度大于jvm所允许的范围时 也会出现异常
4 数组使用中需要注意的两个问题
4.1 数组下标越界异常
在使用数组的下摆哦访问数组元素时 不能超过数组长度
异常显示:ArrayIndexoutOfBoundsException
解决方案:将越界的数组索引修改到正常范围即可
4.2 空指针异常
意味着引用类型的变量不指向任何对象(引用类型的变量没有引用到任何数据)
异常显示:NullPointerException
结局方案:给引用类型的变量一个真正的堆内
空间引用即可
5. 数组的常见操作
主要包括:遍历 拷贝 最值
5.1 遍历
就是获取数组中的每一个元素
程序如下:
public static void main(String[] args) {
int[] arr = {2,3,52,11,4,5,43,2,1};
for(int i = 0 ; i < arr.length;i++){
System.out.println(arr[i]);
}
}
增强for循环:专门用户读取数组或集合中的所有元素(遍历数组或集合)
for (int a : arr){
System.out.println(a);
}
/*
*增强for 第一部分 遍历的数组或集合中的元素的类型
* 第二部分 a 用来存储每一次获取的元素
* 第三部分 arr 表示要便利的数组或者集合对象
*/
增强for循环:在遍历时相对于putongfor更加简洁、
普通for循环:可以通过索引精确到每个元素 而增强for则不可以
5.2 拷贝
public static void main(String[] args) {
int[] arrSrc = new int[5];
int[] arrNew=null;
int count=0;
for(int i = 0 ; i< 100;i++ ){
if(count < arrSrc.length){//当数组中的元素的个数小于数组的长度 则可以保存数据到数组中
arrSrc[i]=i;//给数组添加元素
}else{//当数组中的数据的个数大于等于数组的长度
arrNew = new int[arrSrc.length +(int)(arrSrc.length * 0.75)];
for (int j = 0 ; j < arrSrc.length;j++){
arrNew[j]= arrSrc[j];
}
arrSrc = arrNew;
arrSrc[i]=i;//给数组添加元素
}
count++;//统计数组中数据的个数
}
for(int a : arrNew){//遍历
System.out.println(a);
}
}
5.3 获取数组中的最值
两种方法:
1 记录元素的值
2 记录元素的地址
public static void main(String[] args){
int arr[]={12,34,23,54,24,75,62,46};
// 方法一:记录元素的值
int min1 = arr[0];
for (int i =0;i < arr.length;i ++){
if (min1 > arr[i]){
min1 = arr[i];
}
}
System.out.println(min1);
// 方法二:记录元素的位置
int min2 = 0;
for (int i=0;i<arr.length;i++){
if(arr[i]<arr[min2]){
arr[min2] = arr[i];
}
}
System.out.println(arr[min2]);
}
6 二维数组
6.1 二维数组的初始化
初始化格式:
//动态初始化;
int[][] arr = new int[3][5]; //3行5列的数组
或 int[][] arr = new int[3][]; //行必须指定
// 静态初始化;
int[][] arr = {{1,3,2,3,},{3,3,4,2}{3}};
或 int[][] arr = int[][]{{1,3,2,3,},{3,3,4,2}{3}};
//在Java中二维数组可以不必是规则的矩阵
遍历:
int[][] arr = new int[3][5];
arr[0][0] = 32;
arr[2][4] = 54;
//遍历
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) {
int[][] arr = new int[6][];
for (int i = 0; i < arr.length; i++) {
arr[i] = new int[i+1];
for(int j= 0;j<i+1;j ++){//第一行 1个元素 第n行 n个元素
if(j==0||i==j){
arr[i][j]=1;//每一个的第一个和最后一个元素都是1
}else {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j]; //剩下的元素
}
}
}
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();
}
}
7 方法
方法就是具有独立功能的代码库组织成为一个整体,使其具有特殊功能的代码集
注意:
1 方法必须先创建才可以使用 过程就称为方法的定义
2 方法定义之后不能直接运行 需要手动调用才可以执行 过程称为调用
7.1 定义方法
7.1.1 无参方法的定义和调用
//定义格式
public static void 方法名(){
方法体;
}
//调用格式;
方法名();
方法的调用过程:
1 main方法入栈
2 执行main方法中的代码
3 调用方法(方法入栈 -----> 方法出栈)
4 main方法出栈
每个方法在被调用的时侯,都会被加载到栈内存,并且拥有自己独立的内存空间,方法内部的代码执行完毕之后,会从栈中出栈
7.1.2 带参方法的定义和调用
//定义格式;
public static void 方法名(参数类型 参数名称,参数类型 参数类型……){方法体;}
//调用:
方法名称 (参数1,……参数n)
方法调用时,传入的参数的数量和类型必须和方法定义中的类型和数量相匹配。否则程序会报错
形参: 方法定义时的参数
实参:方法调用时传递进来的参数
实参和形参的功能就是传递数据,发生方法调用时 实参会传递给形参
形参和实参的区别与联系:
1 . 形参变量只有在方法被调用时才会分配内存,调用结束后就会被立即释放。所以形参变量只在方法内有效,不能在方法外部使用。
2. 实参可以是常量 变量 表达式 方法等。无论实参是何种数据类型,在进行方法调用时,都必须有确定的值。
3. 实参和形参在数量上 类型上 顺序上都必须严格一致。但其中能够自动类型转化的除外。
4. 方法调用中,发生的数据传递是单向的。 只有实参能传递给形参,而不能把形参传递给实参。一旦参数完成传递,则式餐盒形参将不会再有任何关系。在方法的调用过程中,形参的改变不会影响实参。
7.1.3 带返回值的方法的定义和调用
public static 返回值类型 方法名称(参数列表){
方法体;
return 数据; //return 表示将数据返回给方法的调用者
}
注意
return 后面不要存在任何语句 执行不到
当一个方法的返回值类型是void时,可以写return,但是写法为: return;
7.2 方法的注意事项
1 方法的定义不能嵌套 方法和方法之间是平行关系 方法只能调用方法
2 void表示无返回值,可以省略return,也可以单独属性 后边不跟任何数据
3 方法只有在被调用才能执行 方法不调用是不会执行的。
7.3 方法使用引用类型作为形参和返回值
public static void main(String[] args) {
yh(10);//此时的10就是实参
}
public static void yh(int row){ //row 就是形参 需要客户传递给你的数据
int[][] yh = new int[row][];
for(int i = 0 ; i < yh.length; i++){
yh[i] = new int[i+1];
for(int j = 0; j < i + 1;j++){
if(j==0 || i==j){
yh[i][j]= 1;
}else{
yh[i][j] = yh[i-1][j-1] + yh[i-1][j];
}
}
}
// 调用遍历数组的方法
printArr(yh);
}
// 遍历任意的二维数组
public static void printArr(int[][] arr){
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) {
int[] arr = {3,2,1,5,7,9};
swap(arr,1,3);
printArr(arr);
}
/* 交换数组中两个元素的位置
arr 我们操作的目标数组
index1 和index2 就是要交换的两个元素的索引
*/
public static void swap(int[] arr,int index1,int index2 ){
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2]= temp;
printArr(arr);
}
// 遍历数组
public static void printArr(int[] arr){
for(int a : arr){
System.out.print (a + " ");
}
System.out.println();
}
方法的参数传递:
值传递:传递的是数据本生
引用传递:传递的是地址 传递的是一个引用 所以引用的只要是同一个地址空间,那么任何地方对空间内容的修改都将引起整个的变化。
7.4方法的重载
public class MethodDemo5 {
public static void main(String[] args) {
int sum = add(2,1,7,8);
System.out.println(sum);
}
public static int add(int a , int b){
return a + b;
}
public static int add(int a , int b, int c){
return a + b + c;
}
public static int add(int a , int b, int c,int d){
return a + b + c + d;
}
构成方法重载的条件:
1 形参个数不同
2 参数类型不同
3 不同类型参数 如果类型顺序不同,也构成重载
特别注意: 方法的返回类型不能不能作为方法是否重载的判断依据
练习:
-
定义一个方法 处理迟到情况的处罚:
1 根据迟到时间和月薪 的不同 ,进行不同的处罚:
2 处罚的逻辑:
迟到1-10分钟 警告
迟到 11–20 分钟 罚款100
迟到21–30分钟 罚款200
迟到30分钟以上 扣除半天工资‘
迟到1小时以上 按照旷工处理 扣除3天工资
根据迟到时间和月薪 来计算员工应缴罚款的金额。
方法中 需要明确:
1 方法是否需要参数 如果需要 需要几个 每个参数什么类型
2 方法是否有返回值 如果有 什么类型 如果没有 就是void上述练习:
参数 需要 迟到时间 (int) 月薪(double)
返回值 有 罚款金额 double
对于日工资的计算 月薪 /21天
public static void main(String[] args){
int tim =0;
double sal = 0;
Scanner input = new Scanner(System.in);
System.out.println("请输入迟到的时间:");
tim = input.nextInt();
System.out.println("请输入月工资:");
sal = input.nextDouble();
double f =fakuan(tim,sal);
System.out.println("罚款为:"+ f+"元");
}
public static double fakuan(int t,double s){
double f;
if(t<=10){
System.out.println("给与警告一次!");
f = 0;
}else if(20>=t){
f = 100;
}else if(t<=30){
f = 200;
}else if(t<60){
f = s/21/2;
}else {
f =s/21 *3;
}
return f;
}