什么是方法
方法(method)是java中程序执行的最小单元。
将重复的代码写在方法里,提高代码的复用性和可维护性。
- 什么时候会用到方法:重复的代码、具有独立功能的代码可以抽取到方法中。
- 方法的好处:提高代码的复用性和可维护性。
方法与类
一个类中可以定义的方法数量没有明确的硬性限制,但存在一些实际限制:
- 方法数量限制:Java 类文件格式允许最多 65535 个方法(包括构造方法、静态方法等)
- 这包括类中定义的所有方法,以及从父类继承的方法
方法的修饰符
修饰符
访问修饰符(Access Modifiers)
public:公共的,任何类都可以访问。protected:受保护的,同包或者子类可以访问。- 默认(什么都不写):包级私有,同包的类可以访问。
private:私有,仅限本类可以访问。
| 访问范围 | private |
default | protected |
public |
|---|---|---|---|---|
| 同一个类中 | ✅Yes | ✅Yes | ✅Yes | ✅Yes |
| 同一个包中的类 | ❌No | ✅Yes | ✅Yes | ✅Yes |
| 不同包的子类 | ❌No | ❌No | ✅Yes | ✅Yes |
| 全局范围 | ❌No | ❌No | ❌No | ✅Yes |
非访问修饰符 (Non-Access Modifiers)
static:静态方法,属于类。final:不能被子类重写。abstract:抽象方法,没有实现。synchronized:同步方法,线程安全native:本地方法,用其他语言实现strictfp:严格浮点计算
修饰符的作用
修饰符的主要作用是控制代码的访问权限、行为特性和约束条件。
说明
- 类(class):创建对象的模板或蓝图,它定义了对象的属性和行为。
- 包 (Package):组织相关类的文件夹结构,类似于电脑中的文件夹。
- 子类(Subclass):通过继承从父类派生出来的新类。
方法的格式
方法就是把一些代码打包在一起,用到的时候就调用。
方法的定义
把一些代码打包在一起的过程,称之为方法定义。
方法的定义应该定义在类中,而不是在main方法中。

最简单的方法
<访问修饰符> <非访问修饰符> <返回值类型> <方法名> () {
<方法体(就是打包的代码)>;
return <需要返回的内容>;
}
举例:
public static void sayHelloWorld () {
System.out.println("hello,world.");
return;
}
带参数的方法
在定义方法时,可以声明参数来接收外部传入的数据。参数在方法名后的括号内定义。
方法参数和局部变量
- 方法中定义的变量(包括参数)都是局部变量
- 局部变量的作用域仅限于方法内部,离开方法后无效
举例
public static void method (int a, int b) {
int result = a + b;
System.out.println(result);
}
形参和实参
- 形参:全称形式参数,指方法定义的参数。
- 实参:全称实际参数,指方法调用的参数。
带返回值的方法
<访问修饰符> <非访问修饰符> <返回值的类型> <方法名> (<形参>) {
<方法体(就是打包的代码)>;
return <返回值>;
}
举例
public static int getSum (int a, int b) {
int sum = a + b;
return sum;
}
说明:void类型也可以写return语句,但是不可以返回任何数据。在void中编写return,当代码执行到retuen后就回退出这个方法。当然void也可以不编写return语句。
要点总结
| 特性 | 说明 | 示例 |
|---|---|---|
| 形参 | 方法定义时的参数 | (int a, int b) |
| 实参 | 方法调用时传入的值 | getSum(5, 3) |
| void返回 | 不返回任何值 | return;或省略 |
| 非void返回 | 必须返回对应类型的值 | return 100; |
| 局部变量 | 方法内定义的变量,方法外不可访问 | int result = a + b; |
方法的调用
方法定义后并不是直接运行的,需要手动调用才能执行,这个过程称之为方法调用。
方法需要先定义再调用,否则程序会报错。
执行逻辑是:看到方法就进入到对于的方法中,执行完成后才继续原代码逻辑的顺序。
public static void main(String[] args) {
System.out.println("1");
demo();
System.out.println("2");
}
public static void demo () {
System.out.println("3");
System.out.println("4");
}

当一个方法调用另一个方法时,程序会转移到被调用的方法。待其内部所有代码执行完毕后,控制权将返回到调用处,并继续执行后续代码。
public static void main(String[] args) {
System.out.println("1");
demo();
System.out.println("2");
}
public static void demo () {
System.out.println("3");
demo2();
System.out.println("4");
}
public static void demo2 () {
System.out.println("5");
System.out.println("6");
}

调用栈机制:
- 方法调用时,当前方法状态被压入调用栈
- 执行被调方法,完成后从栈顶弹出,恢复原方法执行
最简单的方法
调用格式:<方法名>();
public static void main(String[] args) {
sayHelloWorld();
}
public static void sayHelloWorld () {
System.out.println("hello,world.");
}
带参数的方法
调用带参数的方法时,需要传入与形参相匹配的实参。数量,类型必须完全相同,否则会报错。
public static void main(String[] args) {
method(10, 20);
}
public static void method (int a, int b) {
int result = a + b;
System.out.println(result);
}

带返回值的方法
public static int getSum (int a, int b) {
int sum = a + b;
return sum;
}
调用
- 直接调用:
<方法名>(<实参>); - 赋值调用:
<变量名> = <方法名>(<实参>); - 输出调用:
System.out.println(<方法名>(<实参>));
public static void main(String[] args) {
getSum(10, 20);
int sum = getSum(10, 20);
System.out.println(getSum(10, 20));
}
public static int getSum (int a, int b) {
int sum = a + b;
return sum;
}
方法的小结
方法的注意事项
- 方法不调用就不执行
- 方法与方法之间是平级关系,不能互相嵌套定义
- 方法的编写顺序和执行顺序无关,以调用顺序为准
- 方法的返回值类型为
void,则表示该方法无返回值,此时可以省略return语句。 return后面可以跟变量、字面量、表达式等任何与返回值类型兼容的内容。return为方法的结束语句,当方法运行到return就截止,所以return语句之后不可以再写新的逻辑语句。
方法的重载
重载的含义:在同一个类中使用同一个方法名,但是形式参数数量或者形式参数类型不同。需要说明的是,与返回值无关。
方法签名:方法名 + 参数列表(参数类型、数量、顺序)
- 重载要求:方法名相同,但方法签名不同
- 注意:返回值类型不属于方法签名,不能作为重载依据
方法的重载可以是普通方法,也可以是构造方法。
public static int getSum (int a, int b) {
int sum = a + b;
return sum;
}
public static int getSum (int a, int b, int c) {
int sum = a + b + c;
return sum;
}
public static int getSum (double a, double b) {
int sum = ((int)(a + b));
return sum;
}

方法的内存
基础数据类型和引用数据类型
- 基础数据类型:变量里存储的是真实的数据,存储在栈内存中。
- 基础数据类型包含整数类型(
byte、short、int、long)、小数类型(float、double)、字符类型(char)、布尔类型(boolean)。 - 存取速度快,内存占用固定。
- 比较时,比较的是它们的值是否相等(使用
==)
- 基础数据类型包含整数类型(
- 引用数据类型:变量存储的是其他内存空间的地址,使用其他内存空间的数据,存储在堆内存中。
- 引用数据类型所有不属于基本类型的都是引用类型,例如:类(
Class),如String、Object,以及所有自定义的类;接口(Interface);数组(Array);枚举(Enum)。 - 对象占用的堆内存由垃圾回收器自动管理。
- 比较时,使用
==比较的是两个引用是否指向同一个对象(即内存地址是否相同)。要比较对象的内容是否相等,需要使用.equals()方法。
- 引用数据类型所有不属于基本类型的都是引用类型,例如:类(
方法传递数据
方法传递基本数据类型(值传递)
方法在传递基本数据类型时,传递的是真实的数据,形参的改变不会影响实际参数的值。
public static void main(String[] args) {
int number = 100;
System.out.println(number);
myMethod(number);
System.out.println(number);
}
public void myMethod(int number) {
number = 200;
}

方法传递引用数据类型(引用值传递)
方法在传递引用数据类型时,传递的是内存地址,形参的改变会影响实际参数的值。
public static void main(String[] args) {
int[] arr = new int[1];
arr[0] = 100;
System.out.println(arr[0]);
myMethod(arr);
System.out.println(arr[0]);
}
public void myMethod(int[] arr) {
arr[0] = 200;
}

当方法传递引用数据类型的时候,实际上存在两个变量指向同一块内存空间,导致无论通过哪个变量修改对应数据,都是修改同一块内存里的数据,所以形式参数的需修改会影响实际参数的值。
特别说明:String类的不可变性
public static void main(String[] args) {
String str = "hello";
System.out.println(str);
myMethod(str);
System.out.println(str);
}
public void myMethod(String s) {
s = "world";
}

String 虽然也是一个应用数据类型,但是 String 是不可变类。当String传递的时候,新的String局部变量指向了一个全新的String对象,这个新对象与原始String对象在内存中是完全独立的。