1、方法
1.1、方法概述
假设有一个游戏程序,程序在运行过程中,要不断地发射炮弹(植物大战僵尸)。发射炮弹的动作需要编写100行的代码,在每次实现发射炮弹的地方都需要重复地编写这100行代码,这样程序会变得很臃肿,可读性也非常差。为了解决代码重复编写的问题,可以将发射炮弹的代码提取出来放在一个{}中,并为这段代码起个名字,这样在每次发射炮弹的地方通过这个名字来调用发射炮弹的代码就可以了。上述过程中,所提取出来的代码可以被看作是程序中定义的一个方法,程序在需要发射炮弹时调用该方法即可。
1.2、方法的定义格式
格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2…) {
方法体;
return 返回值;
}
名词解释:
修饰符:修饰符比较多,但是呢目前我们只需要记住一个组合 public static
由于目前我们还没有学到面向对象的知识,就现在只需要记住使用即可,后面会解释。
返回值类型:参考我们一直使用的Scanner
定义return返回的数据类型
方法名:给方法起个名字(必须要符合标识符规则)
参数:
1、形参
定义在方法上的参数名
2、实参
将来调用方法实际传入的值
参数类型:
限定将来调用方法时需要传入实参的数据类型
参数名:(形参)
是一个变量,用于接收将来调用方法传入的实参,起名字的时候符合标识符规则,并且见名之意
函数体:
将来要实现功能的代码,主要实现方法的主要逻辑。
return:
一般情况下,有返回值的方法,才会有return。return的作用时将计算好的结果返回给调用者。
注意,return返回的结果类型要和方法定义的返回值类型要一致。
返回值:
程序被return带回的结果,返回给调用者。
使用方法的注意事项:
1、方法不调用坚决不会执行
2、方法的使用在哪里使用?就目前为止来说,要想调用定义好的方法,只能在main方法中调用
3、方法的返回值可以不用加小括号,小括号的作用是改变运算顺序的。
如何写一个方法呢?首先要明确返回值类型:结果的数据类型和参数列表:有几个参数,以及参数的类型。
public class FunctionDemo1 {
public static void main(String[] args) {
//需求;计算两个int类型的数据之和
int a = 10;
int b = 20;
/**
* 有返回值的方法调用的时候,一般情况下,有两种处理方式
* 1、定义一个变量接收方法的返回值,推荐使用这种方式,因为这种方式灵活度更高。
* 2、直接输出或者直接使用
*/
int res1 = sum(a,b);
System.out.println("a+b的和为:" + sum(a,b));
//注意:方法与方法之间是平级关系,不能嵌套定义!!!
}
/**
* 用方法改进
* 有返回值 int
* 参数是两个int类型的数据
*/
public static int sum(int a1, int b1) {
return a1 + b1;
}
}
1.3、方法的重载
概述:在同一个类中,允许存在一个以上的同名方法,只要它们的参数个数或者参数类型不同即可。
方法重载特点:与返回值类型无关,只看方法名和参数列表 ,在调用时,虚拟机通过参数列表的不同来区分同名方法。
public class FunctionDemo3 {
public static void main(String[] args) {
//需求:求两个数之和
int a = 10;
int b = 20;
int res1 = sum(a, b);
System.out.println(res1);
//需求:求三个数之和
int c = 30;
int res2 = sum(a, b, c); //实际参数列表和形式参数列表长度不同
System.out.println(res2);
double d = 40;
double res3 = sum(a, b, d);
System.out.println(res3);
}
public static double sum(int a, int b, double d) {
return a + b + d;
}
public static int sum(int a, int b, int c) {
return a + b + c;
}
public static int sum(int a, int b) {
return a + b;
}
}
2、数组
2.1、一维数组的定义
需求:现在需要统计某公司员工的工资情况,例如计算平均工资、找到最高工资等。
假设该公司有80名员工,用前面所学的知识,程序首先需要声明80个变量来分别记住每位员工的工资,然后在进行操作,
这样做会显得很麻烦。为了解决这种问题,Java就提供了数组供我们使用。
那么数组到底是什么呢?有什么特点呢?通过上面的分析:我们可以得到如下两句话:
1、数组是存储同一种数据类型多个元素的集合。也可以看成是一个容器。
2、数组既可以存储基本数据类型,也可以存储引用数据类型。
语句定义格式:
//格式1:数据类型[] 数组名; 举例:
int[] arr;
//格式2:数据类型 数组名[];举例:
int arr[];
//定义一个存放int类型数据的数组,推荐第一种方式。
为什么不推荐使用第二种方式:
1、从辨识度来看,第一种一眼就能识别是一个数组。
2、从使用长久来看,今后使用的趋势是第一种,第二种渐渐会被淘汰。
数组不初始化不能被使用,初始化?
初始化就是给这个变量开辟一个内存空间,为将来的值提供存放的空间
那么数组如何初始化呢?
两种:
1、动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
动态初始化的语句格式:
//存放元素的数据类型[] 数组名 = new 存放元素的数据类型[数组的长度];
//举例:定义一个可以存放3个int类型数据的数组。
int[] bigdata15 = new int[3];
2、静态初始化:初始化时指定每个数组元素的初始值,由系统决定数组长度。
//存放元素的数据类型[] 数组名 = {数据1,数据2,...};
//举例:定义一个可以存放3个int类型数据的数组。
int[] bigdata15 = {1,2,3};
数组遍历:
获取的长度的属性:length
使用格式:数组名.length
常见错误
数组索引越界 ArrayIndexOutOfBoundsException 访问到了数组中的不存在的索引时发生。
空指针异常 NullPointerException 数组引用没有指向实体,却在操作实体中的元素时。
不能同时使用两种初始化方法!
//错误示范!!!
//int[] arr = new int[]{1,2,3};
*/
public class ArrayDemo1 {
public static void main(String[] args) {
//第一种格式定义
// int[] arr;
//第二种格式定义
// int arr1[];
//没有初始化能直接赋值
// System.out.println(arr);
//动态初始化一个数组:定义一个可以存放3个int类型数据的数组。
/**
* 左半部分:
* int: 表示数组中存放元素的数据类型是int类型
* []: 表示是一个一维数组
* arr: 数组名字,符合标识符规则
*
* 右半部分:
* new: 就是为数组在堆内存中开辟一个内存空间
* int: 表示数组中存放元素的数据类型是int类型
* []: 表示是一个数组
* 3: 表示数组中最多可以存放元素的个数(数组本身的长度)
* ;: 表示一个语句的结尾
*
*/
int[] arr = new int[3];
//[I@4554617c arr数组在堆内存中的地址值,地址是一个十六进制的形式。
System.out.println(arr);
//我们仅仅获取的是一个地址值是没有任何意义的,
//我们更期望获取的是数组中的元素
//如何获取数组中的元素呢?
//java在数组中提供了一个类似于下标的说法,我们可以通过下标获取到该下标位置上的元素
//这个下标有一个专业的叫法:索引(index)
//从左往右编号,从0开始
// 举例:现在数组的长度是3,索引从0开始,最大可以到2,也就是长度-1
// 获取数组元素的格式:数组名[想要获取元素的对应索引]
System.out.println(arr[0]); //获取第一个元素 0
System.out.println(arr[1]); //获取第二个元素 0
System.out.println(arr[2]); //获取第三个元素 0
}
}
2.2、内存分配
Java 程序在运行时,需要在内存中的分配空间。为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。
栈 :存储局部变量
堆 :存储new出来的东西
方法区 (面向对象部分讲)
本地方法区 (和系统相关)
寄存器 (给CPU使用)
2.3、二维数组的定义
我们每个班有很多个学生,所以,可以用数组来存储,而我们又同时有很多个班。
这个也应该用一个数组来存储。如何来表示这样的数据呢?Java就提供了二维数组供我们使用。
由此可见:其实二维数组其实就是一个元素为一维数组的数组。
二维数组的语句定义格式:
//数据类型[][] 变量名 = new 数据类型[][]{{元素…},{元素…},{元素…}};
//简化版格式:
//数据类型[][] 变量名 = {{元素…},{元素…},{元素…}};举例:
int[][] arr = {{1,2,3},{4,6},{6}};
//数据类型[][] 变量名 = new 数据类型[m][];
//m表示这个二维数组有多少个一维数组
//这一次没有直接给出一维数组的元素个数,可以动态的给出。举例:
int[][] arr = new int[3][];
arr[0] = new int[2];
arr[1] = new int[3]
arr[2] = new int[1];
//数据类型[][] 变量名 = new 数据类型[m][n]; (推荐这种写法)
//m表示这个二维数组有多少个一维数组
//n表示每一个一维数组的元素个数,举例:
int[][] arr = new int[3][2];
//定义了一个二维数组arr
//这个二维数组有3个一维数组,名称是arr[0],arr[1],arr[2]
//每个一维数组有2个元素,可以通过arr[m][n]来获取
//表示获取第m+1个一维数组的第n+1个元素
//还有可能看到以下几个写法,它们也是正确的:
int[] arr[] = new int[3][2];
int arr[][] = new int[3][2];
*/
public class Array2Demo1 {
public static void main(String[] args) {
//定义一个二维数组,使用格式一做初始化
int[][] arr = new int[3][2];
System.out.println(arr); // [[I@4554617c
System.out.println(arr[0]); // [I@74a14482
System.out.println(arr[1]); // [I@1540e19d
System.out.println(arr[2]); // [I@677327b6
//想获取第一个一维数组中的第一个元素怎么办呢?
//首先,得获取第一个一维数组
// int[] array1 = arr[0];
// //然后通过索引获取第一个元素
// System.out.println(array1[0]);
System.out.println(arr[0][0]);
System.out.println(arr[0][1]); //获取二维数组中第一个一维数组中的第二个元素
//ArrayIndexOutOfBoundsException: 2
// System.out.println(arr[0][2]); //获取二维数组中第一个一维数组中的第二个元素
System.out.println(arr[1][0]); //获取二维数组中第二个一维数组中的第一个元素
System.out.println(arr[1][1]); //获取二维数组中第二个一维数组中的第二个元素
System.out.println(arr[2][0]); //获取二维数组中第三个一维数组中的第一个元素
System.out.println(arr[2][1]); //获取二维数组中第三个一维数组中的第二个元素
}
}