Java基础(二)

snzjz / 2024-10-29 / 原文

第三章 Java基础(二)

1、while循环 双重for循环

1、while循环:
    for循环语句和while循环语句可以等价转换,但还是有些小区别的
使用区别:控制条件语句所控制的那个变量,在for循环结束后,就不能再被访问到了,而while循环结束还可以继续使用,如果你想继续使用,就用while,否则推荐使用for。原因是for循环结束,该变量就从内存中消失,能够提高内存的使用效率。
场景区别:
for循环适合针对一个范围判断进行操作
while循环适合判断次数不明确操作

    
/*
    while循环:
        语句定义格式1:
            初始化条件语句;
            while(判断条件语句){
               循环体语句;
               控制条件语句;
            }

         语句定义格式2:
            初始化条件语句;
            do{
                循环体语句;
               控制条件语句;
            }while(判断条件语句);

     注意:
        1、while循环可以和for循环等价转换
        2、for循环和while循环的使用场景:
            for循环适合明确的范围内循环  【吃葡萄🍇】
            当循环次数不明确获取就是要求次数的时候,优先考虑while循环【喝水】
 */
public class WhileDemo1 {
    public static void main(String[] args) {
        //输出10行hello world
        for (int i = 1; i < 0; i++) {
            System.out.println("hello world");
        }
        System.out.println("---------------------------");
        int i = 1;
        while (i < 0){
            System.out.println("hello world");
            i++;
        }
        System.out.println("---------------------------");
        int i2 = 1;
        do{
            System.out.println("hello world");
            i2++;
        }while (i2 < 0);
    }
}

2、(do…while循环语句)
do…while循环语句格式:
基本格式
   do {
         循环体语句;
   }while((判断条件语句);
扩展格式
   初始化语句;
   do {
         循环体语句;
         控制条件语句;
    } while((判断条件语句);
            
            
3、循环结构(区别及注意事项)
三种循环语句其实都可以完成一样的功能,也就是说可以等价转换,但还是有小区别的:
do…while循环至少会执行一次循环体。
for循环和while循环只有在条件成立的时候才会去执行循环体
注意事项:
写程序优先考虑for循环,再考虑while循环,最后考虑do…while循环。
如下代码是死循环
while(true){}
for(;;){}

2、跳转控制语句 方法

1、跳转控制语句(break)
break的使用场景:
在选择结构switch语句中
在循环语句中
离开使用场景的存在是没有意义的
break的作用:
跳出单层循环
跳出多层循环
带标签的跳出
格式:标签名: 循环语句
标签名要符合Java的命名规则

/*
    跳转控制语句:
        break关键字
        continue
        return

    break: 打破,打碎,终止

    使用break的注意事项:
        1、break的使用需要在特定的场景下使用才有意义
        2、break只能在switch选择语句或者循环中使用
 */
public class BreakDemo {
    public static void main(String[] args) {
//        break;

        //输出1-10,当遇到5的时候,使用break
        for(int i=1;i<=10;i++){
            if(i==5){
                break; // 终止整个for循环
            }
            System.out.println(i);
        }

        System.out.println("-------------------------------------");
        //需求:当j==5的时候,使用break
        jc:for (int i = 1; i <= 10; i++) {
            lg:for (int j = 1; j <= i; j++) {
                if(j==5){
//                    break; // 终止最近的整个for循环
                    break jc;
                }
                System.out.print(j + "*" + i + "=" + (i * j)+"\t");
            }
            System.out.println();
        }

    }
}
    

2、跳转控制语句(continue)
continue的使用场景:
在循环语句中
离开使用场景的存在是没有意义的
continue的作用:
单层循环对比break,然后总结两个的区别
break  退出当前循环
continue  退出本次循环

package com.shujia.day03;

public class ContinueDemo {
    public static void main(String[] args) {
//        continue; //不能单独使用,需要在特定的场景下使用 ,只能在循环中使用
        //输出1-10,当遇到5的时候,使用continue
        for(int i=1;i<=10;i++){
            if(i==5){
                continue; // 结束当次循环,继续下一次循环
            }
            System.out.println(i);
        }
    }
}

3、跳转控制语句(return)
return关键字不是为了跳转出循环体,更常用的功能是结束一个方法,也就是退出一个方法。跳转到上层调用的方法。这个在方法的使用那里会在详细的讲解。
演示案例:
结束循环其实是结束了main方法
    
/*
    return必须在方法中写,一个方法只会有一个return生效,表示结束整个方法
 */
public class ReturnDemo {
//    return; // return必须在方法中写

    public static void main(String[] args) {
//        return; // 结束整个方法
//        System.out.println("hello world");
//        return;

        for(int i=1;i<=10;i++){
            if(i==5){
                return;
            }
            System.out.println(i);
        }
        System.out.println("hello world");
    }
}    
    
    

3、方法重载

方法重载概述:
在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载特点
与返回值类型无关,只看方法名和参数列表
在调用时,虚拟机通过参数列表的不同来区分同名方法

4、数组初始化和二维数组

/*
    数组:是一块连续固定大小的内存空间,有着索引的概念

    定义数组的语句格式:
        数据类型[] 数组名;【推荐】
        数据类型 数组名[];

    如果只是定义一个数组的话,没有给初始化值,相当于一个变量没有值,是不能够直接使用的
    如何对一个数组进行初始化?
        1、动态初始化:我们自己给定数组的大小,数组中的默认值由JVM来赋值
        2、静态初始化:我们自己给元素值,由JVM根据我们给的值数量来设置数组的大小

    动态初始化语句定义格式:
        数据类型[] 数组名 = new 数据类型[元素的个数];

 */
public class ArrayDemo1 {
    public static void main(String[] args) {
        //定义一个存储int类型元素的数组
        //数据类型 变量名 = 初始化值;
        int[] arr = new int[3];
        /*
            左边:
                int: 表示该数组中元素的数据类型,需要一致
                []: 表示一个一维数组
                arr:是数组名,符合标识符变量的命名规则
            右边:
                new:将来看到new,表示在堆内存中开辟一个空间
                int: 表示该数组中元素的数据类型,需要一致
                []: 表示一个一维数组
                3: 表示该数组最大只能存储3个int类型的元素
         */

        System.out.println(arr); // [I@4554617c 地址值【16进制】
        //数组有索引的概念,从左向右,索引下标从0开始编号,我们可以通过这个索引下标来定位到具体位置的元素
        //语法格式:数组名[索引]
        //获取数组中的第一个元素
        int i = arr[0];
        System.out.println(i);
        //获取数组中的第二,三个元素
        System.out.println(arr[1]);
        System.out.println(arr[2]);
        //我们以后使用数组的时候,肯定是希望将我们自己元素值放在数组中
        //将数组第一个元素值进行修改
        arr[0] = 100;
        System.out.println(arr[0]);

    }
}
============================================================
/*
    定义两个数组,先定义一个数组,赋值,输出。
    然后定义第二个数组的时候把第一个数组的地址赋值给第二个数组。
    然后给第二个数组赋值,再次输出两个数组的名及元素。

 */
public class ArrayDemo2 {
    public static void main(String[] args) {
        int[] arr1 = new int[3];
        arr1[0] = 11;
        arr1[1] = 22;
        arr1[2] = 33;
        System.out.println(arr1);
        System.out.println(arr1[0]);
        System.out.println(arr1[1]);
        System.out.println(arr1[2]);
        System.out.println("-----------------------------");
        int[] arr2 = arr1;
        arr2[1] = 100;
        System.out.println(arr2);
        System.out.println(arr2[0]);
        System.out.println(arr2[1]);
        System.out.println(arr2[2]);
    }
}

============================================================
    
/*
    我们上一个案例中,学习了数组的定义以及数组的动态初始化
    但是,有一个地方不太方便,如果我们想要赋值自己的元素在数组中的话,动态初始化需要我们先将数组创建出来
    然后再一个一个赋值,其实挺麻烦的。能不能直接在初始化的时候,将元素赋值进去?

    数组的静态初始化:
        数据类型[] 数组名 = new 数据类型[]{元素1,...};
        举例:int[] arr1 = new int[]{11,22,33,44,55};
        简化写法:
            数据类型[] 数组名 = {元素1,...};

 */
public class ArrayDemo3 {
    public static void main(String[] args) {
//        int[] arr1 = new int[]{11,22,33,44,55};
//        System.out.println(arr1);
//        System.out.println(arr1[3]);

//        int[] arr1;
//        arr1 = new int[]{11,22,33,44,55};
//        System.out.println(arr1);

        int[] arr1 = {11,22,33,44,55};
        System.out.println(arr1[0]);
        System.out.println(arr1[1]);
        System.out.println(arr1[2]);
        System.out.println(arr1[3]);
        System.out.println(arr1[4]);
//        System.out.println(arr1[5]); // ArrayIndexOutOfBoundsException 数组越界异常

        arr1 = null;
//        System.out.println(arr1[0]); // NullPointerException
    }
}

============================================================
    
/*
    1、当基本数据类型当作参数传递的时候,传递的是具体的数值,不会对原本的变量值进行修改影响
    2、当引用数据类型当作参数传递的时候,传递的是地址值,方法内部可能会对地址值对应的堆内存空间中的数值进行修改。
 */
public class ArrayDemo4 {
    public static void main(String[] args) {
//        int a = 10;
//        int b = 20;
//        System.out.println("a:" + a + ",b:" + b); // a:10,b:20
//        change(a, b);
//        System.out.println("a:" + a + ",b:" + b); // a:10,b:20

        int[] arr = {1, 2, 3, 4, 5};
        change(arr);
        System.out.println(arr[1]);
    }

    public static void change(int[] arr) {
        for (int x = 0; x < arr.length; x++) {
            if (arr[x] % 2 == 0) {
                arr[x] *= 2;
            }
        }
    }

    public static void change(int a, int b) {
        System.out.println("a:" + a + ",b:" + b); // a:10,b:20
        a = b;
        b = a + b;
        System.out.println("a:" + a + ",b:" + b); // a:20,b:40
    }
}

二维数组:
    
/*
    二维数组的遍历
 */
public class Array2Test1 {
    public static void main(String[] args) {
        //创建一个二维数组
        int[][] arr = {{11, 22, 33, 44}, {100, 200}};


        for (int i = 0; i < arr.length; i++) { // 外层循环遍历到每一个一维数组
            for (int j = 0; j < arr[i].length; j++) { //内层循环遍历的是每一个一维数组的元素
                System.out.println(arr[i][j]);
            }
        }
    }
}

============================================================
    
/*
    公司年销售额求和
    某公司按照季度和月份统计的数据如下:单位(万元)
    第一季度:22,66,44
    第二季度:77,33,88
    第三季度:25,45,65
    第四季度:11,66,99

 */
public class Array2Test2 {
    public static void main(String[] args) {
        int[][] arr = {{22, 66, 44}, {77, 33, 88}, {25, 45, 65}, {11, 66, 99}};
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                sum += arr[i][j];
            }
        }
        System.out.println("该公司年销售总额为:" + sum);
    }
}

============================================================

数组操作常见的两个小问题:
数组索引越界
ArrayIndexOutOfBoundsException
访问到了数组中的不存在的索引时发生。
空指针异常
NullPointerException
数组引用没有指向实体,却在操作实体中的元素时。


jvm内存划分:

二维数组内存图:

基本数据类型传值:

两个变量共享一个地址值:

数组静态初始化:

引用数据类型当作参数传递: