目录
Java 中的方法(method)是一种用于封装可重复执行的代码块的机制。方法可以接受参数并返回一个值(或者是 void,表示没有返回值)。在 Java 中,方法是类(class)或对象(object)的行为和功能的基本构建块之一。
以下是关于 Java 方法的一些重要概念和特性:
1. 方法声明:方法声明包括方法的名称、返回类型、参数列表以及方法体。方法声明的一般形式如下:
<访问修饰符> <返回类型> <方法名>(<参数列表>) {
// 方法体
}
2. 访问修饰符:访问修饰符决定了其他类是否可以调用这个方法。常见的访问修饰符包括 `public`、`private`、`protected` 和默认(不使用任何修饰符)。
3. 返回类型:返回类型是方法执行后返回的数据类型。如果方法不返回任何内容,可以使用 `void` 关键字作为返回类型。
4. 方法名:方法的名称应该是有意义的,用于描述方法执行的操作。方法名遵循标识符命名规则。
5. 参数列表:参数列表包含方法接受的输入参数。参数由参数类型和参数名称组成,多个参数之间用逗号分隔。如果方法不接受任何参数,则参数列表为空。
6. 方法体:方法体包含了方法的实际执行代码。
7. 方法调用:方法通过在程序中使用方法名和传递参数来调用。调用方法时,传递的参数类型和数量必须与方法声明中的参数列表相匹配。
8. 方法重载:Java 支持方法重载,即在同一个类中可以有多个方法,它们具有相同的名称但参数列表不同的特性。方法重载使得可以根据参数的不同选择不同的方法。
9. 递归方法:方法可以调用自身,这被称为递归方法。递归方法常用于解决可以被分解为相似子问题的问题,如树遍历、阶乘计算等。
10. 静态方法:使用 `static` 关键字声明的方法称为静态方法。静态方法属于类而不是对象,可以直接通过类名调用。
11. 实例方法:实例方法不使用 `static` 关键字声明,它们属于类的实例,并且必须通过对象来调用。
12. 返回值:方法可以返回一个值,返回值的类型必须与方法声明中的返回类型相匹配。如果方法不返回任何值,则使用 `void` 关键字作为返回类型。
下面是一个简单的 Java 方法示例:
public class Example {
// 方法声明
public static int add(int a, int b) {
return a + b; // 返回 a 和 b 的和
}
public static void main(String[] args) {
int result = add(5, 3); // 调用 add 方法
System.out.println("Result: " + result); // 输出结果
}
}
在这个示例中,`add` 方法接受两个整数参数,并返回它们的和。在 `main` 方法中调用 `add` 方法,并打印出结果。
一、方法调用的基本内存原理
这里会对Java中的栈、堆等内存进行分析,如果对这方面不了解可以看下这篇文章:
其中,方法运行时使用的内存,方法进栈运行,运行完毕就出栈,所以方法是和栈有关的
我们通过代码加速理解:
代码1:
在main方法中定义了一个变量number,并对number进行了打印
程序刚开始运行的时候,main方法就要进栈,然后从上往下执行代码
内存图为:
当运行完代码之后,main方法就会出栈,其中的变量也会随之消失
代码2:
首先定义了一个main方法,在main方法中,调用了eat()方法,在eat()方法中,调用了study()、sleep()方法,并执行了对应方法的功能
在这个过程当中一共有四个方法在运行,在栈中的规则是,先进后出(就像子弹弹夹一样,先放进弹夹的子弹总是是后打出的)
首先程序启动,先执行main方法,所以main方法先进栈,然后再执行main方法里面的代码,在main方法中调用了eat()方法,此时eat()方法进栈,执行eat()方法中的代码,eat()方法中,首先调用了study()方法,所以study()方法进栈,此时实行study()方法中的代码,打印"学习"
此时study()方法中的代码执行完毕,study()方法就要出栈。
此时,程序就要返回到eat()方法中,继续执行代码,也就是sout("吃饭");
然后再调用sleep()方法,sleep()方法入栈,执行sleep()方法中的代码
此时sleep()执行完毕,出栈,然后回到调用处,eat()方法也执行完毕,eat()方法出栈,最后main方法出栈,程序执行完毕。
二、方法传递基本数据类型的内存原理
首先要知道:什么是基本数据类型?什么是引用数据类型?
除了四类八种基本数据类型,其他的都是引用数据类型,但是这强行记忆,没有抓住问题的本质
所以还是要通过内存图进行解析。
其中,当我们定义一个变量,它的值能够真实的存在栈内存中(变量中存储的是真实的数据,而不是内存地址),就是基本数据类型
数据类型存储在自己的空间中,特点:赋值给其他变量,也是赋的真实的值
三、方法传递引用数据类型的内存原理
然而通过new关键字new出来的就是引用数据类型(数组都是通过new出来的,这只是一个简写形式)
由于数组中的值有多个,在栈中不好存储,所以在堆中开辟一个内存空间进行存储,在堆中开辟的空间有一个内存地址,而在栈中数组变量所保存的就是内存地址(这就是为什么我们直接打印数组,打印的是内存地址的原因)我们要获取数组中的元素,只能通过arr保存的地址值去堆中通过索引获取,像这种在栈中存储的不是真实的数据,而是其它空间的地址值(堆...)的称为引用数据类型(引用就是使用其他空间中的数据的意思)
数据值是存储在其他空间中,自己空间中存储的是地址值
在赋值时,赋值给其他变量,赋的时地址值,也就是当其他变量修改其中的值时,原来变量的值也会改变
四、方法的值传递
我们通过案例来深入了解方法的值传递
案例一:
由上可知,两次打印的结果都是一样的,在上述代码中,没有new关键字,所以我们只需要关心栈内存
由于变量是有自己的所属范围的,所以两个方法中的变量值改变不会相互影响
内存图为:
所以说传递基本数据类型时,传递的时真实的数据,形参的改变,不会影响实际参数的值。
如果我们要改变实参的值就要就将代码修改为:
案例二:
本案例中相当于把arr记录的地址值,当作参数传递给了change()方法
运行结果:
由于使用了数组出现了new关键字,所以涉及到了堆内存
内存图为:
定义数组:
打印调用前代码:
调用change()方法
当执行change()方法中的arr[1]=200;就相当于,拿着地址值去堆中修改索引为1的元素。
当调用完方法后,change()出栈,打印arr[1],此时arr[1]修改为200
传递引用数据类型时,传递的是地址值,形参的改变,影响实际参数的值。