方法、重载、数组(动态初始化、静态初始化)、jvm虚拟机、二维数组、值传递

目录

方法

方法重载

数组(一维)

数组的动态初始化

jvm虚拟机

 数组的静态初始化

二维数组

值传递


方法

引例:文件上传是做一个电商网站所必不可少的功能,比如每一个商品都需要上传若干商品图片,网站上各种品牌都需要上传其logo,用户在注册时可以上传头像... 假设你现在已经写了100行代码完成了文件上传功能,但问题是网站的很多地方都要使用这一功能,比如管理商品数据的商品服务,管理用户数据的用户信息服务等等。

问题来了,这些地方都要使用文件上传的功能,怎么办呢?

方案1:在每个用到文件上传功能的地方重写这些100行代码,但是方案1会引发一系列的问题!!

方案2:复用这100行代码,将这些代码放在一个{ }中,并给它们起个名字,通过名字来复用这段代码

 方法定义:完成特定功能的代码块(相当于c语言的函数)

格式:  

修饰符 方法返回值类型 方法名(参数1类型 参数1名称, 参数2类型 参数2名称, ...){
    方法体语句;
    return 返回值;
}

方法定义的格式说明:
    1.修饰符: 现在先认为是固定的public static
    2.返回值类型: 方法体中的代码执行结果的数据类型
    3.方法名: 标识符
    4.参数: 类比数学中函数的自变量 z = f(x, y)
    5.方法体: 实现具体功能的语句结合
    6.return: 跳转控制关键字
    7.返回值: 方法执行的到的最终结果

注意: return 返回值; (这句并非必须)

方法调用有两种:

        1)有返回值的方法调用
        2)没有返回值的方法调用

两式求和(add)

//定义方法 执行 3 + 4
public static int add1() {
    int result = 3 + 4;
    return result;
}
//定义方法 执行 5 + 6
public static int add2() {
    int result = 5 + 6;
    return result;
}

//以上两数求和都是固定数不方便,优化
//声明两个参数变量,让他们来传数进行运算
//定义实现两数求和的加法运算
public static int add(int x, int y) {
    int result = x + y;
    return result;
}

//不需要先声明后使用
public static void main(String[] args) {
    //用变量接收有返回值的方法调用
    int result = add(3, 4);
    System.out.println(result);// 7
    System.out.println(add(3, 4));// 7
    add(3, 4);//可以调用,但有返回值的方法调用无意义
}

 如何写一个方法呢?

    返回值类型 明确功能结果的数据类型
​    参数列表 明确有几个参数,以及参数的类型

方法执行过程:

 定义没有返回值的方法,void 表示方法没有返回值

public static void main(String[] args) {
    //调用没有返回值的方法
    print("你好");
}
public static void print(String s) {
    System.out.println("我是没有返回值的方法:" + s);
    //return;//可以有可以没有,通常省略
}
//输出: 我是没有返回值的方法:你好

注意:方法体中不能定义方法(不能嵌套)

练习:键盘录入一个数据n(1<=n<=9),输出对应的nn乘法表

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    printMulti(n);
}
public static void printMulti(int n) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            System.out.print(j + " x " + i + " = " + j * i + "  ");
        }
        System.out.println();
    }
}
/*
输入:3
1 x 1 = 1  
1 x 2 = 2  2 x 2 = 4  
1 x 3 = 3  2 x 3 = 6  3 x 3 = 9  
*/

方法重载

        同一个类中定义多个同名方法,方法名相同参数列表:个数不同、数据类型、顺序不同(数据类型的顺序)


数组(一维)

引例:假设一个班有80个人。我们现在需要统计,其某一门课程的平均成绩, 思路很简单,先求和,在平均,想一想,如果使用我们之前所学的知识,该怎么做呢?

//1.定义80个变量
//2.用这80个变量存储80个同学的成绩
//3.求和表达式 80变量的求和 al + a2 + ... + a80

大致想一想都会觉得真的好麻烦!! ! 为了应对以上的使用场景,我们就需要学习数组。

数组的概念(一组数据)
    相同数据类型的数据元素的有序集合(容器)
            存储多个数据元素
            这多个数据元素的数据类型必须一致(为什么呢?)

 

数据宽度:数据占的字节的数量 随机存取(数组的访问特征):访问数组内任意一个元素的时间都相同

要想实现随机存取,必须数据类型相同,不然用不了上面公式

数组中究竟可以存储哪些类型的数据呢?

基本类型数据:byte short int char double float

引用类型数据:对象

数组的定义格式

格式1: 数据类型[ ] 数组名;

格式2: 数据类型 数组名[ ];

注意,这只是数组的定义,如何给定义好的数组“赋值”呢

//存放int类型值的数组   官方推荐的写法
int[] arr;
//声明int类型的数组
int arr1[];
//使用之前必须赋初值
System.out.println(arr);//报错:Variable "arr" might not have been initialized

 

数组的初始化
    Java中的数组必须先初始化,然后才能使用。
    所谓初始化:就是为数组中的数组元素分配内存空间,并为每个数组元素赋初值

数组的初始化方式
    动态初始化
        初始化时程序猿只指定数组长度,由系统(JVM)为数组分配初始值。
    静态初始化
        初始化时指定每个数组元素的初始值,由系统决定数组长度。 int[] a = {1, 2, 3}

数组的动态初始化

​    格式:数据类型[] 数组名 = new 数据类型[数组长度];(数组长度就是数组中元素的个数)

 

int[] arr = new int[3];

 

jvm虚拟机

栈(Stack):存储局部变量 (迄今为为止我们代码中几乎所有的变量都在栈)【Java没有全局变量】

堆(Heap):存储new出来的东西 (数组对应的存储空间在这里)

方法区:(后面讲)

本地方法栈:(系统相关)Java语言调用的C/C++语言存储的

程序计数器:(最无用的东西)指明代码的执行位置,记录java代码运行到哪

 一行代码在 jvm 中做了什么事情?

 图解1:
    定义一个数组,输出数组名及元素。然后给数组中的元素赋值,再次输出数组名及元素。
图解2:
    定义两个数组,分别输出数组名及元素。然后分别给数组中的元素赋值,分别再次输出数组名及元素。
图解3:
    定义两个数组,先定义一个数组,赋值,输出。然后定义第二个数组的时候把第一个数组的地址赋值给第二个数组。然后给第二个数组赋值,再次输出两个数组的名及元素。

//图解1:定义一个数组,输出数组名及元素。然后给数组中的元素赋值,再次输出数组名及元素。
int[] a = new int[3];
//输出数组名
System.out.println(a);//[I@4554617c:[表示一维数组 I整数类型 4554617c数组实际存储的首地址
//输出
System.out.println(a[0]);//0
System.out.println(a[1]);//0
System.out.println(a[2]);//0
//给数组中的元素赋值
a[0] = 10;
a[1] = 20;
System.out.println(a);//[I@4554617c
System.out.println(a[0]);//10
System.out.println(a[1]);//20
System.out.println(a[2]);//0

 

//图解2:定义两个数组,分别输出数组名及元素。然后分别给数组中的元素赋值,分别再次输出数组名及元素。
int[] arr1 = new int[3];
System.out.println(arr1);//[I@4554617c

System.out.println(arr1[0]);//0
System.out.println(arr1[1]);//0
System.out.println(arr1[2]);//0
System.out.println("------------------------");

int[] arr2 = new int[2];
System.out.println(arr2);//[I@74a14482
System.out.println(arr2[0]);//0
System.out.println(arr2[1]);//0

arr1[0] = -100;
System.out.println(arr1);//[I@4554617c
System.out.println(arr1[0]);//-100
System.out.println(arr1[1]);//0
System.out.println(arr1[2]);//0

arr2[1] = 30;
System.out.println(arr2);//[I@74a14482
System.out.println(arr2[0]);//0
System.out.println(arr2[1]);//30

//图解3:定义两个数组,先定义一个数组,赋值,输出。
byte[] bytes1 = new byte[2];
bytes1[0] = 10;
bytes1[1] = 20;
System.out.println(bytes1);//[B@4554617c
System.out.println(bytes1[0]);//10
System.out.println(bytes1[1]);//20
//然后定义第二个数组的时候把第一个数组的地址赋值给第二个数组。
//然后给第二个数组赋值,再次输出两个数组的元素。
byte[] bytes2 = bytes1;
bytes2[0] = -10;
bytes2[1] = 110;
System.out.println("---------第一个数组----------");
System.out.println(bytes1);//[B@4554617c
System.out.println(bytes1[0]);//-10
System.out.println(bytes1[1]);//110
System.out.println("---------第一个数组----------");
System.out.println("---------第二个数组----------");
System.out.println(bytes2);//[B@4554617c
System.out.println(bytes2[0]);//-10
System.out.println(bytes2[1]);//110
System.out.println("---------第二个数组----------");

 数组的静态初始化

!!!初始化时指定每个数组元素的初始值,由系统决定数组长度。

格式:数据类型[ ] 数组名 = new 数据类型[ ]{元素1, 元素2, ...};

int[] arr = new int[]{1, 2, 3};
//简化写法:
int[] arr = {1,2,3};

arr = {1,2,3};//错误

注意: 简化写法只在数组定义时有效!

数组操作中,常见的两个问题

1、数组索引越界 ArrayIndexOutOfBoundsException

2、空指针异常 NullPointerException

//数组索引越界
int[] arr = new int[2];//包含的元素 位置 0、1、2
//访问了数组中并不存在的索引对应的元素
System.out.println(arr[2]);//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException

//空指针异常
arr = null;
System.out.println(arr[0]);//Exception in thread "main" java.lang.NullPointerException

 

练习:

1、数组遍历(依次输出数组中的每一个元素)

2、数组元素逆序

3、对取值范围在1~100的数据集合排序

4、数组获取最值(获取数组中的最大值最小值)

5、数组查表法(根据键盘录入索引,查找对应星期)

6、数组元素查找(查找指定元素第一次在数组中出现的索引)

答案:

public static void main(String[] args) {
    /*//1、数组遍历
    int[] arr1 = new int[10];
    arr1[0] = 1;
    arr1[1] = 2;
    traverse(arr1);*/
    //len10
    //1 2 0 0 0 0 0 0 0 0 
    
    /*//2、数组逆序
    int[] arr2 = {1, 2, 6, 7};
    reverseArray(arr2);
    //Arrays.toString()将数组里的元素拼接成字符串后返回
    System.out.println(Arrays.toString(arr2));*/
    //[7, 6, 2, 1]
    
    /*//3、对取值范围在1~100的数据集合排序
    int[] arr3 = {1, 3, 5, 2, 1, 1, 55};
    sort(arr3);
    System.out.println(Arrays.toString(arr3));
    //[1, 1, 1, 2, 3, 5, 55]
    //4、数组获取最值
    System.out.println(findMax(arr3));*/
    //55
    
    /*//5、数组查表法(根据键盘录入索引,查找对应星期)
    System.out.println(findDayOfWeek(7));*/
    //星期日
    
    /*//6、数组元素查找(查找指定元素第一次在数组中出现的索引)
    int location = findLocation(arr2, 1);
    System.out.println(location);*/
    //1
}

//1、数组遍历方法(依次输出数组中的每一个元素)
public static void traverse(int[] arr) {
    //数组有一个属性length(数组长度,不是元素个数),数组取值范围:[0, length-1]
    int len = arr.length;
    System.out.println("len" + len);
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }
}

//2、数组元素逆序 [1,2,3,6,7]->[7,6,3,2,1]
//奇数个元素:关于3对称,交换对称的位置
//偶数个元素:交换对称的位置
//思路:对称位置元素交换位置,先遍历数组
public static void reverseArray(int[] arr) {
    for (int i = 0; i < arr.length / 2; i++) {
        int tmp;
        tmp = arr[i];
        arr[i] = arr[arr.length - 1 - i];
        arr[arr.length - 1 - i] = tmp;
    }
}

//3、计数排序:对取值范围在1~100的数据集合排序
public static void sort(int[] arr) {
    //1、根据题意创建包含101个元素的数组
    int[] countArray = new int[101];
    //2、遍历待排序集合,在countArray中,对待排序的数据计数
    for (int i = 0; i < arr.length; i++) {
        //得到待排序集合中当前元素的值
        int resultIndex = arr[i];
        countArray[resultIndex]++;
    }
    //3、在原数组中排序
    int index = 0;
    for (int i = 0; i < countArray.length; i++) {
        for (int j = 0; j < countArray[i]; j++) {
            arr[index++] = i;
        }
    }
}

//4、数组获取最值(获取数组中的最大值最小值)
public static int findMax(int[] arr) {
    //存储数组中最大值,假设第一个最大
    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

//5、数组查表法(根据键盘录入索引,查找对应星期)
public static String findDayOfWeek(int index) {
    String[] daysOfWeek = {"星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日",};
    return daysOfWeek[index - 1];
}

//6、数组元素查找(查找指定元素第一次在数组中出现的索引)
public static int findLocation(int[] arr, int value) {
    int resultIndex = -1;
    for (int i = 0; i < arr.length; i++) {
        if (arr[i] == value) {
            resultIndex = i;
            break;
        }
    }
    return resultIndex + 1;
}

二维数组

我们已经学习了基本的一维数组,可以持有大量数据。

思考如下场景:
    假设我现在要统计,学校中某个年级中,各班的数学成绩的平均分。
思考一下,用一维数组可以吗?会遇到什么问题?
分析一下出现问题的原因是什么呢?不同的维度

看起来,该问题的解决:
    用一个一维数组,存储所有班级(每一个班级本身的数据,又需要用一个一维数组存储)
    看起来就好像,我们定义了这样一个一维数组:
    这个一维数组的,每一个存储单元,又存储了一个一维数组
    定义了一个一维数组的数组——二维数组

 

二维数组的实质:一维数组的数组 二维数组的初始化格式1:

数据类型[][]   变量名 = new 数据类型[m][n];
//m代表二维数组中一维数组的个数
//n代表二维数组中包含的每个一维数组,所能包含的元素个数

特征:二维数组中每一个一维数组包含的元素的个数相同(格式1)

//例如:
int[][] arr = new int[2][2];
//在简单看下其内存映象
//1、输出二维数组引用变量的值
System.out.println(arr);//[[I@1540e19d [[:表示一个二维数组
//2、输出二维数组中,第一个一维数组的引用的值
System.out.println(arr[0]);//[I@677327b6
//3、访问二维数组中,一维数组的元素值
System.out.println(arr[1][0]);//0
arr[1][0] = 10;
System.out.println(arr[1][0]);//10

 二维数组定义的格式2

数据类型[][] 变量名 = new 数据类型[m][];
//m表示这个二维数组有多少个一维数组
//这一次没有直接给出一维数组的元素个数,可以动态的给出。
举例:
int[] arr2 = new int[2][];
arr[0] = new int[1];
arr[1] = new int[2];
//注意:这种方式从存储角度讲更加灵活!

 二维数组定义的格式3:

数据类型[][] 变量名 = new 数据类型[][]{{元素...},{元素...},{元素...}};

//简化版格式: 
数据类型[][] 变量名 = {{元素...},{元素...},{元素...}};
//注意:简化版只能在定义数组的引用变量时使用!
public static void main(String[] args) {
	//三个一维数组,每个数组的初值都已经被指定
	int[][] arr3 = {{1}, {2, 3}, {4, 5, 6}};
	trverseTwoDeimensionArray(arr3);
	/*1 
    2 3 
	4 5 6 */
}

public static void trverseTwoDeimensionArray(int[][] arr) {
    //arr指向的是代表二维数组的那个一维数组 arr.length 表示二维数组中的一维数组个数
    for (int i = 0; i < arr.length; i++) {
        //arr[i]代表二维数组中的第i个一维数组 arr[i].length 表示的就是二维数组中第i个一维数组的元素个数
        for (int j = 0; j < arr[i].length; j++) {
            System.out.print(arr[i][j] + " ");
        }
        System.out.println();
    }
}

练习:

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

public static void main(String[] args) {
    int[][] arr = {{22, 66, 44}, {77, 33, 88}, {25, 45, 65}, {11, 66, 99}};
    System.out.println(sum(arr));//641
}
public static int sum(int[][] arr) {
    int sum = 0;
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr[i].length; j++) {
            sum += arr[i][j];
        }
    }
    return sum;
}

2、打印杨辉三角形(行数可以键盘录入)

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    int[][] yanghui = yanghui(n);
    for (int i = 0; i < yanghui.length; i++) {
        for (int j = 0; j < yanghui[i].length; j++) {
            System.out.print(yanghui[i][j] + " ");
        }
        System.out.println();
    }
    /*5
    1 
    1 1 
    1 2 1 
    1 3 3 1 
    1 4 6 4 1 */
}
//对于杨辉三角,第一行和第二行是固定的
//每一行元素个数和行数相同
//每一行的第一个和最后一个元素值固定,都是1
//  每一行出首尾位置之外,其他位置的元素值都有规律:
//  第i行第j列 = 第i-1行第j列的值 + 第i-1行j-1列
public static int[][] yanghui(int n){
    if (n==1){
        return new int[][]{{1}};
    }
    if (n==2){
        return new int[][]{{1},{1,1}};
    }
    //最终返回的二维数组的结果
    int[][] result=new int[n][];
    result[0]=new int[]{1};
    result[1]=new int[]{1,1};
    //计算并初始化每一行数据
    for (int i=2;i<n;i++){
        //对于杨辉三角的第i行数据,初始化首尾元素的值
        result[i]=new int[i+1];
        result[i][0]=1;
        result[i][i]=1;
        for (int j=1;j<i;j++){
            result[i][j]=result[i-1][j-1]+result[i-1][j];
        }
    }
    return result;
}

值传递

(引用数据类型和基本数据类型)

在java语言中,不管参数的类型,是引用类型,还是基本数据类型,在实际参数和形式参数进行值传递的方式只有一种: 实际参数的值复制一份赋值给形式参数 所以,实参的值,其实就有两份,调用方法中一份,被调用方法中一份

1.当方法的参数是基本数据类型的参数的时候,参数有两份,同时参数对应的数据的值,也有两份 2.当方法的参数是引用数据类型的时候参数值有两份,但是两个数组类型引用变量,对应的值(数组),只有一个

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值