一、方法(非常重要)
1.1 方法的概念
方法(method),又称为函数(function)。代表一个、独立的、可复用的、功能。
-
一个方法代表一个功能,
-
例如:Math.random()方法 代表产生1个[0,1)范围的小数的功能
-
例如:Scanner类中 next() 方法 代表从键盘接收1个字符串的功能
-
例如:System.out 中 println() 方法代表输出xx内容到控制台,然后立刻换行的功能
-
-
方法的功能可以反复被使用 =》 可复用
-
方法的功能最好具有独立性 ,即一个方法只干一件事
public class MethodDemo {
public static void main(String[] args) {
int x = 5;
int y = 6;
max(x,y);
min(x,y);
}
public static void method(int a, int b){//同时完成了两件事,找最大值和最小值,后期复用不方便
int max = a > b ? a : b;
System.out.println("max = " + max);
int min = a < b ? a : b;
System.out.println("min = " + min);
}
public static void max(int a, int b){//只完成了一件事,找最大值
int max = a > b ? a : b;
System.out.println("max = " + max);
}
public static void min(int a, int b){//只完成了一件事,找最小值
int min = a < b ? a : b;
System.out.println("min = " + min);
}
}
1.2 方法的特点
-
方法必须先声明后使用
-
方法调用一次才执行执行,不调用不执行。调用1次执行1次。
public class MethodDemo2 {
public static void main(String[] args) {
int a = 2;
int b = 1;
}
//max方法没有被使用,调用,根本不会执行
public static void max(int a, int b){
int max = a > b ? a : b;
System.out.println("max = " + max);
}
}
public class MethodDemo2 {
public static void main(String[] args) {
int a = 2;
int b = 1;
max(a,b);
max(a,b);
max(a,b);
//max方法调用1次执行一次
}
public static void max(int a, int b){
int max = a > b ? a : b;
System.out.println("max = " + max);
}
}
1.3 方法的声明格式(重要)
【修饰符】 class 类名{
【修饰符】 返回值类型 方法名(【形参列表】){
【方法体语句;】
}
}
1、方法的修饰符
方法的修饰符会有很多:public,static,abstract,synchronized等。
今天把所有方法都声明为public static。因为我们的main方法,现在是public static。暂时不区分不加public或static有什么影响。
2、方法名
方法名就是一个标识符。便于使用。
方法名的命名规则和规范:
-
规则与其他的标识符一样
-
和变量名一样,遵循小驼峰命名法,从第二个单词开始首字母大写,形式:xxxYyyZzz,例如:nextInt(),nextDouble()
-
建议方法名尽量见名知意,方法名最好能代表功能
3、返回值类型
方法完成功能后,是否需要给调用者明确返回一个结果?
-
如果需要,这个结果的类型是什么,返回值类型就是什么。并且在方法体中,必须有return 结果; 的语句来返回这个结果。
-
如果不需要,返回值类型统一写void。
4、形参列表
完成方法功能,是否需要调用者给你传递数据?
-
如果需要,要说明需要几个,分别是什么类型的,例如(int a, int b ) 需要2个int整数,至于a,b就是这两个数据在当前方法中的名字
-
如果不需要,就直接()空着
5、方法体
方法体:实现方法的功能的语句。
1.4 方法的调用格式
方法名(实参列表);
变量 = 方法名(实参列表); //表示用变量接收了方法的返回结果
1.5 方法的几种常见形式
1、无参无返回值
方法名();
public class MethodDefineDemo1 {
//编写一个方法,可以输出5行5列的*组成的图形
//void表示没有结果返回
public static void printRectangle(){
for(int i=1; i<=5; i++){
for(int j=1; j<=5; j++){
System.out.print("*");
}
System.out.println();
}
}
public static void main(String[] args) {
printRectangle();//调用无参无返回值方法的格式 方法名();
System.out.println("================");
printRectangle();
// System.out.println(printRectangle());//报错,printRectangle()没有结果返回,println()方法不知道要打印什么
// String result = printRectangle();//错误,printRectangle()没有结果返回,result变量接收不到值
}
}
2、有参无返回值
方法名(实参列表);
实参列表必须与形参列表的类型、个数、顺序完全一致。
public class MethodDefineDemo2 {
//编写一个方法,可以输出m行n列的某字符组成的图形
//void表示没有结果返回
public static void printRectangle(int m, int n,char c){
if(m<=0 || n<=0){
System.out.println("m,n必须大于0");
return;//结束当前方法的执行,这里不返回结果
}
for(int i=1; i<=m; i++){
for(int j=1; j<=n; j++){
System.out.print(c);
}
System.out.println();
}
}
public static void main(String[] args) {
printRectangle(5, 10, '@');//调用无参无返回值方法的格式 方法名(实参列表);
System.out.println("================");
printRectangle(10,20,'%');
System.out.println("================");
printRectangle(-10,20,'%');
}
}
3、无参有返回值
变量 = 方法名();//用变量接收返回值
System.out.println(方法名()); //直接打印返回值
public class MethodDefineDemo3 {
public static void main(String[] args) {
System.out.println(getANumberBetween0And100());
System.out.println(getANumberBetween0And100());
System.out.println(getANumberBetween0And100());
}
//main方法与我们定义的其他方法的顺序是随意的
//定义一个方法,可以实现产生1个[0,100)的整数,
// 结果是一个int整数,所以返回值类型是int
public static int getANumberBetween0And100(){
int num = (int)(Math.random()*100);
return num;
}
}
4、有参有返回值
变量 = 方法名(实参列表);//用变量接收返回值
System.out.println(方法名(实参列表)); //直接打印返回值
public class MethodDefineDemo4 {
public static void main(String[] args) {
System.out.println(getANumberBetween0And100(10,20));
System.out.println(getANumberBetween0And100(0,100));
System.out.println(getANumberBetween0And100(50,70));
}
//main方法与我们定义的其他方法的顺序是随意的
//定义一个方法,可以实现产生1个[a,b)的整数,
// 结果是一个int整数,所以返回值类型是int
public static int getANumberBetween0And100(int a, int b){
int num = (int)(Math.random()*(b-a) + a);
return num;
}
}
1.6 练习题
1.6.1 练习题1
(1)定义一个add方法,可以实现两个整数求和
(2)定义一个subtract方法,可以实现两个整数求差
(3)定义一个multiply方法,可以实现两个整数求乘积
(4)定义一个divide方法,可以实现两个整数求商
(5)定义一个remainder,可以实现两个整数求余数
(6)定义一个方法calulate,可以实现同时返回两个整数的和、差、乘积、商、余数
(7)测试调用,从键盘输入两个整数,调用上面的方法测试
import java.util.Scanner;
public class MethodExercise1 {
public static int add(int a, int b){//花店
return a + b;
}
public static int subtract(int a, int b){//花店
return a - b;
}
public static int multiply(int a, int b){//花店
return a * b;
}
public static int divide(int a, int b){//花店
return a / b;
}
public static int remainder(int a, int b){//花店
return a % b;
}
/*
如果返回值类型是int,只能返回1个int值
如果你需要返回多个int值,返回值类型必须是int[]
*/
public static int[] caculate(int a, int b){
//定义一个数组,用来存储+,-,*,/,%的结果
int[] results = new int[5];
results[0] = a + b;
results[1] = a - b;
results[2] = a * b;
results[3] = a / b;
results[4] = a % b;
return results;//results里面存储的是数组的首地址
//返回的是数组的首地址
//这里比喻 caculate方法替你盖了一个房子,然后把房子的地址或钥匙给你返回去了
}
public static void main(String[] args) {//我自己
Scanner input = new Scanner(System.in);
System.out.print("请输入第一个整数:");
int a = input.nextInt();
System.out.print("请输入第二个整数:");
int b = input.nextInt();
/* int result = add(a, b);//先用变量接收add方法返回的结果
System.out.println("和:" + result);*/
System.out.println("和:" + add(a, b));//直接输出add方法返回的结果
System.out.println("差:" + subtract(a, b));//直接输出subtract方法返回的结果
System.out.println("乘积:" + multiply(a, b));//直接输出multiply方法返回的结果
System.out.println("商:" + divide(a, b));//直接输出divide方法返回的结果
System.out.println("余数:" + remainder(a, b));//直接输出remainder方法返回的结果
/* System.out.print("计算的和、差、乘积、商、余数是:");
int[] arr = caculate(a, b);//这里拿到的那个房子的钥匙。
//main方法就可以根据房子的地址和钥匙,找到房子里面的东西
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}*/
input.close();
}
}
1.6.2 练习题2
/*
(1)定义一个maxInArray方法,查找int[]数组中最大值
(2)定义一个minInArray方法,查找int[]数组中最小值
(3)测试
A:随机产生10个[0,100)的整数放到数组中
B:调用上面的方法找出最大值和最小值
*/
public class MethodExercise2 {
public static int maxInArray(int[] arr){
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i] > max){
max = arr[i];
}
}
return max;
}
public static int minInArray(int[] arr){
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if(arr[i] < min){
min = arr[i];
}
}
return min;
}
public static int[] getTenNumbersBetween0And100(){
int[] nums = new int[10];
for(int i=0; i<nums.length; i++){
nums[i] = (int)(Math.random()*100);
}
return nums;
}
public static void printElements(int[] arr){
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
System.out.println();
}
public static void main(String[] args) {
//随机产生10个[0,100)的整数放到数组中
int[] arr = getTenNumbersBetween0And100();
printElements(arr);
int max = maxInArray(arr);
System.out.println("max = " + max);
int min = minInArray(arr);
System.out.println("min = " + min);
}
}
1.6.3 小结
-
方法的形参类型:
-
可以是基本数据类型,8种
-
也可以是引用数据类型:String,数组
-
-
方法的返回值类型:
-
void:代表无返回值
-
可以是基本数据类型,8种 ,返回1个值
-
可以是引用数据类型,例如:数组,返回一组数
-
3.7 方法的调用过程分析(理解)
内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。Java虚拟机要运行程序,必须要对内存进行空间的分配和管理,每一片区域都有特定的处理数据方式和内存管理方式。
JVM的运行时内存区域分为:方法区、堆、虚拟机栈、本地方法栈、程序计数器几大块。
区域名称 | 作用 |
---|---|
程序计数器 | 程序计数器是CPU中的寄存器,它包含每一个线程下一条要执行的指令的地址 |
本地方法栈 | 当程序中调用了native的本地方法时,本地方法执行期间的内存区域 |
方法区 | 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。 |
堆内存 | 存储对象(包括数组对象),new来创建的,都存储在堆内存。 |
虚拟机栈 | 用于存储正在执行的每个Java方法的局部变量表等。局部变量表存放了编译期可知长度的各种基本数据类型、对象引用,方法执行完,自动释放。 |
方法调用的过程:
-
入栈:方法被调用的瞬间,JVM会给这个方法在栈中开辟一块独立的内存空间,用于存储这个方法的局部变量等信息
-
出栈:方法调用结束瞬间,JVM会自动释放这个方法占用的栈内存空间
3.8 答疑(必须弄清楚)
形参、实参、返回值、返回值类型、调用、声明等名词。
3.9 方法的参数传递机制(面试的难点,选择题)
参数:实参给形参传值,
讨论,形参接收完实参的值之后,会不会对实参造成影响?
3.9.1 参数是基本数据类型(8种)
-
形参是基本数据类型,实参给形参的是数据值的副本,此时对形参做任何修改,和实参都无关。
public class ParamPassValueDemo2 {
public static void main(String[] args) {
int a = 1;
System.out.println("a = " + a);//a=1
change(a);
System.out.println("a = " + a);//a=1
a = modify(a);//a重新接收新的结果
System.out.println("a = " + a);//a=2
}
public static void change(int a){//a=1
a++;
}
public static int modify(int a){
a++;
return a;//返回修改后的结果
}
}
3.9.2 参数是引用数据类型
引用数据类型:类(class)、数组等,今天主要讨论数组。
-
形参是引用数据类型,实参给形参的是地址值的副本。此时如果通过形参修改数组的元素,那么相当于实参自己在修改元素。因此此时形参和实参指向的是同一个数组。
-
但是,如果在方法中,形参指向了新的数组,接下来的操作和实参数组无关了。