文章目录
- 1.概念
- 2.静态方法和非静态方法
- 2.1静态方法
- 2.2非静态方法
- 3 参数传递方式
- 4.方法的重载
- 5.命令行传参
- 6.可变参数
- 7.递归
- 作业
1.概念
在面向对象编程中,方法(Method)是类或对象中用于执行特定任务的一段代码。方法可以访问和操作对象的属性,并提供了一种封装行为的方式。
方法通常用于描述对象的行为或操作,它们定义了对象可以执行的操作,并在需要时接受输入参数并返回结果。方法可以被其他代码调用,并且可以在需要时被重复使用,从而实现了代码的模块化和重用。
方法一般由以下几个组成部分:
- 方法名:方法的名称用于标识和区分不同的方法。
- 参数列表:方法可以接受零个或多个输入参数,这些参数用于传递数据给方法进行处理。
- 返回类型:方法可能会返回一个值作为结果,返回类型指定了返回值的数据类型。
- 方法体:方法体是包含实际代码的部分,它描述了方法的具体实现。
package com.determination;public class Day11601 {//main方法public static void main(String[] args) {sayHello();System.out.println("两个数中最大的是:"+max(4,5));}/*修饰符 返回值类型 方法名(。。。){方法体返回值}*/public static void sayHello(){System.out.println("Hello world!");return;}public static int max(int a,int b){return a>b?a:b;}
}
当我们调用一个方法时,程序会跳转到该方法的代码块中执行相应的操作。在方法内部,我们可以通过参数来访问传递进来的数据,并通过方法体中的代码来处理这些数据。最后,方法可以根据需要返回一个结果给调用方。
2.静态方法和非静态方法
2.1静态方法
在面向对象编程中,静态方法(Static Method)是一种特殊的方法,不需要创建对象实例即可调用。静态方法是直接与类相关联的,而不是与类的对象相关联的。
使用static关键字来定义静态方法。在静态方法内部,不能直接访问非静态成员变量或方法,因为非静态成员变量和方法需要依赖于对象的实例才能被访问。但是,静态方法可以访问静态成员变量或静态方法。
静态方法在设计模式中有广泛应用,例如工厂模式。在工厂模式中,我们使用静态方法来创建对象,而不是通过new操作符来创建对象。这种方式可以将对象的创建逻辑封装在方法中,并提供更加灵活的对象创建方式。
静态方法还可以用于工具类或辅助类中,这些类通常只提供一些公用方法,而不需要维护任何状态或对象实例。使用静态方法可以避免创建多余的对象实例,从而提高程序的性能和效率。
Day11602.java
package com.determination;public class Day11602 {public static void main(String[] args) {Student.say();}
}
Student.java
package com.determination;public class Student {//静态方法·public static void say(){System.out.println("学生说话了!!");}
}
输出
学生说话了!!
2.2非静态方法
在面向对象编程中,非静态方法(Non-static Method)是与类的对象相关联的方法。也就是说,只有当类的一个实例化对象被创建后,才能调用非静态方法。
非静态方法是通过对象来调用的,因此它们可以直接访问和操作对象的非静态成员变量或方法。在非静态方法内部,可以使用this关键字来引用当前对象,从而获取或修改对象的状态。
使用非静态方法可以实现面向对象编程中的封装和抽象特性。非静态方法通常用于描述对象的行为或操作,例如读取或修改对象的状态、执行某些动作、计算属性等等。
当我们调用一个非静态方法时,程序首先需要创建一个对象实例,然后通过该对象来调用方法。由于每个对象都有一份独立的状态,因此同一个类的不同对象可能会产生不同的结果。
11602.java
package com.determination;public class Day11602 {public static void main(String[] args) {//Student.say();Student student=new Student();student.say();}
}
Student.java
package com.determination;public class Student {//静态方法·
// public static void say()
// {
// System.out.println("学生说话了!!");
// }//非静态方法public void say(){System.out.println("学生说话了!");}
}
static 关键字修饰的成员(包括静态方法和静态变量)是与类一起加载的。
在 Java 中,当类被加载到内存中时,静态成员会随着类的加载而加载,并且在类加载过程中只会加载一次。静态成员的加载顺序是按照定义的顺序进行的。
当类被加载时,Java 虚拟机会为该类分配内存,并且静态成员会被初始化。静态变量会被赋予默认值(如果有的话),或者通过显式赋值来初始化。静态方法也会被加载到内存中,供类直接调用。
由于静态成员是和类相关联的,它们可以在没有创建对象实例的情况下被访问和使用。我们可以通过类名直接调用静态方法或访问静态变量,无需创建对象。
需要注意的是,静态成员在内存中存在于整个程序执行期间,直到程序结束或类被卸载。因此,静态成员应谨慎使用,避免滥用静态变量,特别是在多线程环境下,需要考虑线程安全性。
需要注意的是:
实参与形参的参数类型要对应,不能出现定义的形参是int型,结果传递过来的是字符型char
3 参数传递方式
- 值传递
值传递是指将实参的值复制一份传递给形参,在方法内部对形参进行修改不会影响到实参本身。简单来说,值传递就是把数据的副本传递给方法。
public void swap(int x, int y) {int temp = x;x = y;y = temp; //没有返回值,仅仅是对a,b的副本x,y进行了交换数值
}
int a = 1, b = 2;
swap(a, b);
System.out.println("a=" + a + ", b=" + b); // 输出 a=1, b=2
在上面的例子中,swap 方法接收两个 int 类型的参数 x 和 y,通过将 x 和 y 的值进行交换来实现交换两个变量的值。但是,当我们调用 swap 方法时,并没有改变 a 和 b 的值,因为 swap 方法接收的是 a 和 b 的副本,交换操作只是在副本中进行的。
- 引用传递
引用传递是指将实参的引用传递给形参,在方法内部对形参进行修改会影响到实参本身。简单来说,引用传递就是把数据的地址传递给方法。
public void changeName(Student s, String name) {s.setName(name);
}
Student stu = new Student("Tom", 18);
changeName(stu, "Jerry");
System.out.println(stu.getName()); // 输出 Jerry
changeName 方法接收一个 Student 类型的对象 s 和一个 String 类型的参数 name,通过修改 s 对象的姓名来实现修改学生的姓名。当我们调用 changeName 方法时,传递的是 stu 对象的引用,因此在方法内部对 s 对象的修改会影响到 stu 对象本身。
4.方法的重载
方法的重载(Method Overloading)是指在一个类中可以定义多个方法,它们具有相同的名称但参数列表不同(参数个数、参数类型或参数顺序)。通过方法的重载,可以方便地使用相同的方法名进行不同的操作。
方法的重载有以下特点:
- 方法名相同:重载的方法必须具有相同的名称。
- 参数列表不同:重载的方法必须在参数列表上有所区别,包括参数个数、参数类型或参数顺序。
- 返回类型可以相同也可以不同:重载的方法可以具有相同的返回类型,也可以有不同的返回类型。返回类型不是重载方法的区分标准。
例如,下面是一个计算两个整数之和的方法的重载示例:
public class Calculator {public int add(int a, int b) {return a + b;}public double add(double a, double b) {return a + b;}
}
Calculator 类定义了两个名为 add 的方法,一个接收两个 int 类型的参数,另一个接收两个 double 类型的参数。这样,当我们调用 add 方法时,可以根据传入的参数类型自动选择匹配的方法进行计算。
使用方法重载的好处包括:
- 提高代码的可读性和可维护性:通过使用相同的方法名进行不同的操作,可以降低方法命名的复杂性,使代码更加清晰易懂。
- 简化代码逻辑:当我们需要进行类似但略有差异的操作时,可以直接调用重载的方法,避免编写多个类似的方法。
- 方便使用:通过方法重载,可以根据传入参数的不同灵活地选择合适的方法,方便使用者。
需要注意的是,在进行方法重载时,应该确保方法的功能是相似的,即具有相同的语义。否则,如果方法的功能不同,容易引起混淆和错误的调用。
5.命令行传参
在 Java 中,命令行参数以字符串数组的形式传递给 main 方法。main 方法的声明如下:
public static void main(String[] args)
其中,args 是一个字符串数组,包含了传递给程序的所有命令行参数。args 数组的长度即为传递参数的个数。
package com.determination;public class Day11603 {public static void main(String[] args) {//args.length 数组长度for(int i=0;i<args.length;i++){System.out.println("args["+i+"]:"+args[i]);}}
}
然后如下图所示操作
显示结果:
需要注意的是,命令行参数总是以字符串的形式传递给程序。如果需要将其转换为其他类型,需要进行相应的类型转换操作。
6.可变参数
可变参数(Varargs)是 Java 5 中引入的一个特性,它允许我们在方法中接受不定数量的参数。可变参数使得方法在调用时更加灵活,可以传递任意数量的参数。
在 Java 中,可变参数通过使用省略号 (…) 来声明。可变参数必须是方法的最后一个参数,且只能有一个可变参数。
下面是一个使用可变参数的示例:
public class VarargsExample {public static void main(String[] args) {printNumbers(1, 2, 3);printNumbers(4, 5, 6, 7, 8);printNumbers(9);}public static void printNumbers(int... numbers) {System.out.println("Numbers:");for (int number : numbers) {System.out.println(number);}}
}
在上述示例中,printNumbers 方法使用了可变参数 numbers。我们可以向该方法传递任意数量的整数参数。在方法内部,我们可以像操作普通数组一样来处理可变参数。在printNumbers 方法中,我们遍历可变参数数组,并打印每个数字。
Numbers:
1
2
3
Numbers:
4
5
6
7
8
Numbers:
9
需要注意以下几点:
- 可变参数可以接受零个或多个参数,也可以传递一个数组作为参数。
- 如果方法有多个参数,可变参数必须放在最后一个参数的位置。
- 如果方法除了可变参数外还有其他参数,那么传递给可变参数的值将作为数组存储在参数中。
- 可变参数在编译时被转换为数组。因此,我们可以像处理数组一样来处理可变参数。
- 如果方法同时存在其他重载方法,编译器会优先选择非可变参数的方法。
7.递归
递归(Recursion)是一种常见的算法设计技巧,它是通过函数自身调用来解决问题的方法。在递归过程中,函数会不断调用自身,直到达到某个终止条件为止。递归通常可以让代码更加简洁而优雅,但同时也需要注意可能带来的性能问题和栈溢出等问题。
public class RecursionExample {public static void main(String[] args) {int result = factorial(5);System.out.println("Factorial of 5 is " + result);}public static int factorial(int n) {if (n == 0) {return 1;} else {return n * factorial(n - 1);}}
}
上述代码使用递归的方式计算阶乘。在 factorial 方法内部,我们首先判断传入的参数是否为 0,如果是,则返回 1。否则,我们将 n 乘以 (n-1) 的阶乘结果,实现递归调用。
Factorial of 5 is 120
递归虽然在某些情况下可以使代码更加简洁而优雅,但有时也可能会带来一些问题。递归调用需要占用栈空间,如果递归层数过多,可能会导致栈溢出。另外,递归的效率可能不如迭代法,因为在递归调用过程中需要不断地压栈和出栈,增加了额外的开销。
递归详细讲解
作业
写一个计算器要求实现加减乘除功能,并且能够循环接收新的数据
package com.determination;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;public class Day11604 {public static void main(String[] args) {System.out.println("请输入数字,输入'exit'结束:");Scanner scanner=new Scanner(System.in);// 创建一个动态大小的数组列表List<Integer> numbers = new ArrayList<>();while (scanner.hasNext()) {String input = scanner.next();// 判断是否输入 'exit',如果是则退出循环if (input.equals("exit")) {break;}try {// 将用户输入的字符串解析为整数,并添加到数组列表中int number = Integer.parseInt(input);numbers.add(number);} catch (NumberFormatException e) {System.out.println("无效的输入,请重新输入数字或 'exit' 来结束。");}}// 将数组列表转换为数组double[] array = new double[numbers.size()];for (int i = 0; i < numbers.size(); i++) {array[i] = numbers.get(i);}System.out.println("相加的结果为:"+add(array));System.out.println("相减的结果为:"+decrease(array));System.out.println("相乘的结果为:"+multiple(array));System.out.println("相除的结果为:"+divde(array));}public static double add(double ... number){double sum=0;for(int i=0;i<number.length;i++){sum+=number[i];}return sum;}public static double decrease(double ... number){double res=number[0];
// System.out.println(res);for(int i=1;i<number.length;i++){res-=number[i];}return res;}public static double multiple(double ... number){double res=number[0];for(int i=1;i<number.length;i++){res*=number[i];}return res;}public static double divde(double ... number){double res=number[0];for(int i=1;i<number.length;i++){res/=number[i];}return res;}
}
运行:
请输入数字,输入'exit'结束:
10 5 exit
相加的结果为:15.0
相减的结果为:5.0
相乘的结果为:50.0
相除的结果为:2.0