方法
方法,也叫函数,是完成特定功能的代码块。简单来说,一个方法就是一个功能,一个动作或者一种行为。
方法的作用:当一些代码被反复使用时,可以把他们提取出来,放到一个方法里,以方法的形式来使用这些代码。
方法的好处:大大提高了代码的复用性,方便维护。
格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数2……) {
//方法体语句;
return 返回值;
}
格式说明:
修饰符:public static(固定格式)
返回值类型:方法执行结果的数据类型
方法名:方法的名称,符合标识符命名规则即可
参数列表:方法执行需要的条件
参数来兴:可以是基本类型,也可以是引用类型
参数名:即变量名
方法体语句:完成特定功能的代码
return:意思是返回,用于结束方法
返回值:方法执行之后的结果,返回给方法的使用者。若方法没有返回值,则它的返回值类型为void,比如main方法(里面的return已经省略了)
如何定义一个方法:
1.明确方法名;
2.明确返回值类型(想要获取什么样的返回值);
3.明确参数列表;
需求:求两个数之和
方法的调用
概念:使用方法的过程称为方法的调用
调用方式(先定义后调用):
1.通过方法名调用方法
2.根据形式参数列表将实际参数传递给方法
形式参数:在定义方法时需明确方法参数的形式,比如参数的类型和个数,故方法定义时的参数列表称为形式参数
实际参数:调用方法时传递给方法的数据,必须符合形式参数的个数和对应位置的数据类型
调用方法的注意事项:
1.可以根据方法名来调用方法 通俗的说就是要调用哪个方法就写该方法的名字
2.方法要什么,你就给什么 方法需要什么类型的参数,你就传入什么类型的值
3.方法返回什么,你就用什么类型的变量来接手
package study.demo;
/*
方法格式:
修饰符 返回值的类型 方法名(参数类型 参数值1,参数类型 参数值2……) { //方法名后面的括号里的参数也可以不写
方法体语句
return 返回值;
}
*/
public class MethodDemo {
public static void main(String[] args) {
/*
调用方法的注意事项:
1.可以根据方法名来调用方法 通俗的说就是要调用哪个方法就写该方法的名字
2.方法要什么,你就给什么 方法需要什么类型的参数,你就传入什么类型的值
3.方法返回什么,你就用什么类型的变量来接手
*/
int s = sum(3,4);
System.out.println(s);
}
/*注意:方法和方法之间是平级的关系,不能嵌套定义
如何定义一个方法:
1.确定方法名;
2.确定返回值类型(想要获取什么样的返回值);
3.确定参数列表;
*/
//需求:定义一个方法,用来获取两个整数的和;两个整数和也是一个整数,那么返回值类型就是int
public static int sum(int a,int b) {
//方法体语句就是具体的运算过程
int c = a + b;
return c;
}
}
方法调用过程:
1.通过方法名调用方法
int s = sum();
2.传递实际参数
int s = sum(3,4);
3.方法执行时,实际参数值赋值给形式参数
int sum(int a,int b)
4.在方法中进行运算,并将结果赋值给变量c
int c = a + b;
5.方法的返回值c赋值给接受者s;(如果方法没有返回值,则不需要接收)
int s = sum(3,4);
案例:比较两个整数是否相同
需求:键盘录入两个整数,比较他们是否相同
package study.demo;
import java.util.Scanner;
public class MethodDemo2 {
public static void main(String[] args) {
//需求:键盘录入两个数字,比较它们是否相同
//2.通过键盘录入功能,接受用户输入的两个数字
//2.1先创建键盘录入对象
Scanner sc = new Scanner(System.in);
//2.2提示用户输入数字
System.out.println("请输入第一个整数");
int num1 = sc.nextInt();
System.out.println("请输入第二个整数");
int num2 = sc.nextInt();
//3.调用方法,获取结果并打印
boolean is = compare(num1,num2);
System.out.println(is);
}
//1.定义方法,实现比较两个int类型整数是否相同的功能(判断两个整数是否相等)
public static boolean compare(int a,int b) {
//原始做法
// boolean c = (a==b);
// return c;
//优化做法
return a == b;
}
}
定义方法的注意事项:
1.方法必须定义在类中
2.方法之间是平级关系,不能嵌套
3.方法没有返回值时,也要有返回值类型:void
4.方法返回值类型为void时,可以省略return语句
5.return语句后的数据类型必须和返回值类型匹配
6.return之后不能再放置语句,return语句代表代码块的结束
小贴士:方法调用时,若不关心方法的返回结果,可以直接调用,省略接收返回值的动作
package cn.hjh.demo;
/*
定义方法的注意事项:
1.方法必须定义在类中
2.方法之间是平级关系,不能嵌套
3.方法没有返回值时,也要有返回值类型:void
4.方法返回值类型为void时,可以省略return语句
5.return语句后的数据类型必须和返回值类型匹配
6.return之后不能再放置语句,return语句代表方法的结束
*/
public class MethodDemo3 {
public static void main(String[] args) {
boolean c = compare(10,20);
System.out.println(c);
} //这个反括号是main方法的结束标记
//定义方法,比较两个整数是否相等
public static boolean compare(int a,int b) {
return a == b; //a == b 是关系运算,结果是布尔(boolean)类型,若写了其他的类型,则会报错
} //这个反括号是compare方法的结束标记
} //MethodDemo3类的结束
方法重载
在同一个类中的多个方法,它们的方法名相同,参数列表不同,这样的情况,称为方法重载。方法重载与返回值类型无关
参数列表不同:参数的个数不同;对应位置的参数类型不同
方法签名:方法名+参数列表
方法重载的作用:当实现的功能相同,但具体的实现方式不同时,我们可以通过定义名称相同,参数(条件)不同的方法,来更好的识别和管理类中的方法。
案例:比较两个数是否相同
需求:分别比较两个int/long/double型的数是否相同
package cn.hjh.demo;
public class OverLoadDemo {
public static void main(String[] args) {
/*
方法重载的概念:
同一个类中的多个方法,出现方法名相同,但是参数列表不同的情况
参数列表的不同:参数的个数不同;对应位置的参数类型不同
方法重载与方法的返回值类型不同
*/
//需求:定义方法,分别比较两个int/long/double型的数是否相同
//4.调用比较两个int类型数据的方法
int a = 5;
int b =50;
boolean i = compare(a,b);
System.out.println(i);
System.out.println("————————————");
//5.调用比较两个long类型数据的方法
long d = 20L;
long c = 20L;
boolean l = compare(d,c);
System.out.println(l);
System.out.println("————————————");
//6.调用比较两个double类型数据的方法
double e = 3.14;
double f = 2.25;
boolean o = compare(e,f);
System.out.println(o);
}
public static boolean compare(int a,int b) {
System.out.println("比较两个int类型的数字是否相同");
return a == b;
}
public static boolean compare(long a,long b) {
System.out.println("比较两个long类型的数字是否相同");
return a == b;
}
public static boolean compare(double a,double b) {
System.out.println("比较两个double类型的数字是否相同");
return a == b;
}
}
判断方法之间的重载关系:前面的修饰符是不影响的,所以不用比较修饰符;看方法名是否相同;看参数列表是否不同。
数组
数组就是为存储多个数据值。数组是用来存储同一种数据类型多个元素的容器
数据类型:可以是基本数据类型,也可以是引用类型
容器:比如箱子,衣柜等,可以存放多个事物
数组的定义格式:
1.数据类型[] 数组名 = new 数据类型[长度]
定义格式详解:
数据类型:即数组中存储元素的数据类型,可以是基本数据类型,也可以是引用数据类型
[]:表示数组,固定写法
数组名:数组的变量名,遵循标识符命名规范
new:创建数组的关键字,通过new开辟内存空间(数组是存在内存中的)
长度:即数组长度,数组最多能够存放元素的个数。数组长度在定义时指定,不可更改
2.数据类型[] 数组名 = new 数组类型[]{元素1,元素2,元素3……}
格式二的好处:定义时元素是确定的,避免内存空间的浪费
3.数据类型[] 数组名 = {元素1,元素2,元素3……}
格式三是格式二的变形,简化了代码的编写
package cn.hjh.demo;
public class ArrayDemo {
public static void main(String[] args) {
/*数组的定义格式
格式1:数据类型[] 变量名 = new 数据类型[长度]
格式2:数据类型[] 变量名 = new 数据类型[] {元素1,元素2,元素3……}
格式3:数据类型[] 变量名 = {元素1,元素2,元素3……}
*/
// 需求:定义一个长度为3的int类型的数组
// 虽然定义了长度为3的数组,但是具体是哪3个数字,不确定
int[] arr = new int[3];
// 具体的数字是10,20,30
int[] arra = new int[] {10,20,30};
// 具体的数字是1,2,3,4,5
int[] array = {1,2,3,4,5};
}
}
数组的访问:通过数组的索引访问数组的元素
索引:也叫下标,脚标,是数组元素距离数组起始位置的偏移量
第一个元素的偏移量为0,所以数组的所以从0开始
格式:数组名[索引]
取值:数组名[索引]
赋值:数组名[索引] = 值
package cn.hjh.demo;
public class ArrayDemo2 {
public static void main(String[] args) {
/*
需求:打印数组中的指定元素
操作数组中的元素的格式:
数组名[索引],索引是从0开始的,往后以此类推
*/
int[] arr = new int[]{1,2,3,4};
arr[2]=6; //3改为6
System.out.println(arr[2]);
}
}
数组的遍历
获取数组的长度:数组名.length
结论:
1.数组的最大索引为数组长度-1
2.数组中未手动赋值的元素,有默认值0。例如:int型数组默认值是0,double型数组默认值是0.0
3.直接输出数组变量名,得到的是数组的内存地址值
案例
需求:定义一个长度为5的int型数组,将前三个元素分别赋值为1,2,3,通过for循环遍历数组,打印数组中每一个元素的值
package cn.hjh.demo;
public class ArrayDemo3 {
public static void main(String[] args) {
// 直接输出数组变量名,得到的是数组的内存地址值
// 数组中未手动赋值的元素,有默认值0;例如:int型数组默认值是0,double型数组默认值是0.0
// 数组的最大索引为数组长度-1;获取数组的长度:**数组名.length**
// 定义一个长度为5的int型数组,将前三个元素分别赋值为1,2,3,通过for循环遍历数组,打印数组中每一个元素的值
// 定义一个长度为5的int型数组
int[] arr = new int[5];
// 将前三个元素分别赋值为1,2,3
arr[0]= 1;
arr[1] = 2;
arr[2] = 3;
// 传统做法
// System.out.println(arr[]); 输出数组的内存地址值
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
System.out.println("arr数组的长度为:"+arr.length);
System.out.println("arr数组的最大索引是:"+(arr.length-1)); //记得加括号(从左到右的顺序)
//通过for循环遍历数组,打印数组中每个元素的值;i < arr.length:表示i的值小于arr数组的长度(5)
for (int i =0;i < arr.length;i ++) {
System.out.println(arr[i]);
}
}
}
数组的初始化
数组初始化就是在内存中为数组开辟连续空间并为每个元素赋值的过程
内存:计算机的重要组件,用于程序运行中临时存储数据
连续空间:数组元素在内存空间中存放位置时是连续的
动态初始化:只指定长度,由系统给出默认值
格式一是动态初始化;(只给长度,未赋值)
整数型:0
浮点型:0.0
字符型:’\u0000’ (空字符)
布尔型:false
引用型:null
静态初始化:给出初始化值,由系统决定数组长度
格式二和格式三是静态初始化;(已赋值)
Java程序的内存分配
变量名存储在栈里面(如int [] arr);new出来的对象是存储在推里面的(如new int[5]);当java程序看到new,就会向(推)内存申请开辟空间。new开辟空间之后会有一个地址值的,然后把地址值给arr,arr就会指向该空间,在使用数组时,可以根据该地址值找到指定的空间内的元素
方法区(Method Area):存储可运行的class文件,包含方法,静态成员,常量等(面向对象部分详解)
栈(Stack):方法运行时使用的内存,特点是“后进先出”,即最先进入栈区的方法最后出栈,比如main方法。(比如子弹(1~6),1号子弹先放进去,但是最后才出来)
推(Heap):存储new出来的数组或对象(面向对象部分详解)
本地方法栈:JVM在调用操作系统功能时使用,与开发无关
寄存器:CPU使用,与开发无关
数组类型:变量(如arr)存储的是数组在推内存中的地址值,而不是数组元素的值,变量(arr)通过内存地址引用推内存中的数组,所以数组是引用类型
main方法会先加载在方法区中存储,main方法是程序的主入口,之后会按照从上到下,从左到右的顺序执行程序中的代码。
package cn.hjh.demo;
public class ArrayDemo4 {
public static void main(String[] args) {
// 需求:一个数组两个引用烦人内存图解
int[] arr1 = new int[3];
arr1[0] = 0;
arr1[1] = 1;
arr1[2] = 2;
System.out.println(arr1[0]);
System.out.println(arr1[1]);
System.out.println(arr1[2]);
System.out.println("————————————");
int[] arr2 = arr1; //数组arr1和数组arr2共享同一份推内存空间(同样的数据)
arr2[0] = 3; //索引为0的数据改为3,那么arr1[0]也改为3
System.out.println(arr1[0]);
System.out.println(arr2[0]);
}
}
数组的常见操作
1.数组索引越界异常:ArrayIndexOutOfBoundsException(访问了不存在的索引时出现)
异常:即非正常情况,可以简单理解为程序运行过程中出现错误
package cn.hjh.demo;
public class ArrayDemo5 {
public static void main(String[] args) {
int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
// System.out.println(arr[3]); //在此输出的话,将会报错,程序停止,后面的代码将不会被执行(从上到下执行) 报错信息:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
// at cn.hjh.demo.ArrayDemo5.main(ArrayDemo5.java:9)
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//报错,因为数组中不存在,数组长度为3,因此没有索引3,越界了
System.out.println(arr[3]); // 报错信息:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
// at cn.hjh.demo.ArrayDemo5.main(ArrayDemo5.java:14)
}
}
2.空指针异常:NullPointerException(数组引用存储的值为null而非数组的地址值时)
package cn.hjh.demo;
public class ArrayDemo6 {
public static void main(String[] args) {
// 需求:演示空指针异常(NullPointerException)
int[] arr = new int[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr = null; //数组arr的数据为空
System.out.println(arr[0]);
}
}
需求:给定一个int型数组,找出它的最大元素
package cn.hjh.demo;
public class ArrayDemo7 {
public static void main(String[] args) {
// 需求:给定一个int型数组,找出它的最大元素
// 1.定义int[]
int[] arr = new int[] {25,40,16,20,10};
// 2.定义一个临时变量(max),用来表示最大值
int max = arr[0];
// 3.通过for循环遍历数组,获取每一个数据
for (int i =0;i < arr.length;i ++) {
// arr[i]表示的就是数组中的每一数据
// 4.把获取到的数据依次和临时变量(max)比较,并将最大值赋给临时变量(max)
if (arr[i] > max) {
max = arr[i];
}
}
// 5.for循环执行结束后,临时变量(max)记录的就是最大值,打印输出即可
System.out.println("数组中的最大值为:"+max);
}
}
案例:定义打印数组元素的方法并调用
需求:给定一个int型数组,调用自定义方法打印数组的每一个元素
package cn.hjh.demo;
public class ArrayDemo8 {
public static void main(String[] args) {
// 需求:定义一个方法用来打印数组,并调用
// 1.定义一个数组
int[] arr = new int[] {2,4,6,3,5,9};
printArray(arr); //因为返回值类型是void,没有返回值的,所以可以不设值接受,直接调用即可
}
/* 自定义一个方法,用来打印数组
明确方法名: printArray
明确参数列表:int[] arr
明确返回值的类型:void
* */
public static void printArray (int[] arr) {
for (int i = 0;i < arr.length;i ++) {
// 这里边写的是具体的遍历数组的代码
System.out.println(arr[i]);
}
}
}
结论:引用类型的变量作为参数递给方法时,传递的是地址值
1.基本类型的变量作为参数传递时,传的是 值 (相当于是复制,复制过去后,可以随便修改,但是原来的不受影响)
2.引用类型的变量作为参数传递时,传的是地址值
package cn.hjh.demo;
public class ArrayDemo9 {
public static void main(String[] args) {
//结论:
// 1.基本类型的变量作为参数传递时,传的是 值 (相当于是复制,复制过去后,可以随便修改,但是原来的不受影响)
// 2.引用类型的变量作为参数传递时,传的是地址值
int x = 3;
int y = 4;
int z = sum(x,y); //sum(3,4)
System.out.println(x); //这个不受自定义方法的影响,还是原来的值
System.out.println(y); //这个不受自定义方法的影响,还是原来的值
System.out.println(z);
}
public static int sum(int a,int b) { //int 3,int 4
int c = a + b; //c=7
a ++; //4
b ++; //5
return c; //返回7
}
}