一、简介
描述:
- Java中方法是语句的集合,它们在一起执行一个功能。
- 方法是解决一类问题的步骤的有序组合,它在类中定义,属于类的成员,包含于类或对象中。
- 方法在程序中被创建后,在其他使用了该方法的地方被引用。
优点:
- 使程序代码变得更简短而清晰。
- 有利于程序维护。
- 可以提高程序开发的效率。
- 提高了代码的重用性。
设计原则:
- 方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期的扩展。
命名规范:
- 小驼峰法
二、定义方法
语法:
/* 修饰符 */ /* 返回值类型 */ 方法名 (/* 参数列表 */) /* 异常抛出类型 */{
/* 方法体 */
/* return语句 */
}
描述:
- 修饰符:修饰符是可选项,可有多个不同修饰符,例如public、static、abstract、final等,多个修饰符之间是没有先后顺序的 。修饰符告诉编译器如何调用该方法,定义了该方法的访问类型。
- 返回值类型 :方法可能会返回值,Java是强类型语言,需要显式指定返回值的数据类型。若没有返回值,返回值类型使用关键字'void'。只有构造方法(构造器)才不写任何返回类型,也不写'void'。
- 方法名:Java标识符之一,是方法的实际名称。定义方法名时要遵守Java标识符的命名规则与规范。方法名和参数列表共同构成方法签名。
- 参数列表:
- 参数列表是表是指方法的形式参数类型、顺序和个数。
- 参数列表可以为空,也可以由多个形式参数的声明组成,互相之间用逗号分隔。
- 形参和实参:
- 形式参数:在方法被调用时用于接收外界输入的数据。
- 实际参数:调用方法时实际传给方法的数据。
- 形式参数的声明方式为:形式参数类型 + 空格 + 形式参数名称。
- 形式参数像是一个占位符,当方法被调用时,会传递实际参数的值给形式参数。形参的名字和实参的名字都只是一个变量的名字,是可以随便写的,我们并不关心这个名字,而是关心变量的类型以及变量接收的值。
- 异常抛出类型:异常抛出类型是可选项。如果方法中的代码在执行过程中,可能会出现一些异常情况,那么就可以在方法上把这些异常声明并抛出。使用'throws'关键字加异常类型来声明异常抛出类型,'throws'关键字与异常类型之间用空格隔开。可以同时声明抛出多个异常类型,使用逗号隔开不同异常类型即可。
- 方法体:方法体指方法定义时大括号里包含的所有语句,定义该方法的功能。
- 'return'语句:
- 'return'语句位于方法体中。
- 'return'语句有两个作用:
- 'return'语句会从当前的方法中立即退出,返回到调用该方法的语句处,继续向下执行。
- 'return'语句可以返回一个值给调用该方法的语句,返回值的数据类型必须与该方法的声明中的返回值类型一致。
- 'return'语句也可以不带返回值,其实主要目的就是用于中断该方法的执行,返回到调用该方法的语句处。
- 若方法声明里有返回值类型,则方法体最终必须使用'return'语句返回对应类型的返回值;若方法声明的返回值类型为'void',则定义方法体时可以没有'return'语句。
示例:
/* 比较两个数的大小,获取更大的值 */
public static int max(int num1, int num2) throws Exception {
if (num1 == num2) {
throw new Exception("比较两个数的大小时,不可以传入同样的值!");
}
if (num1 > num2) {
return num1;
} else {
return num2;
}
}
三、调用方法
描述:
- 在类中定义了方法,这个方法中的代码并不会执行,当这个方法被调用的时候,方法中的代码才会被一行行执行。
- Java语言中通常使用这样的形式调用方法:类或对象名.方法名(实参列表)
- 当程序调用一个方法时,程序的控制权就交给了被调用的方法。
- 当被调用方法的'return'语句执行,或者到达方法体闭括号的时候,交还控制权给程序。
- 当调用的方法有返回值的时候,该方法的调用通常被当做一个值来使用,例如可以用来将该方法的返回值赋值给一个变量。
- 如果方法返回值类型是'void',方法的调用一定是一条语句,不能被当做一个值来使用。
注意:
- 'static'修饰符:
- 使用'static'修饰符修饰的方法,就是静态方法。调用这种方法的时候,可以使用对象调用,也可以使用类来调用,但是推荐使用类进行调用,因为静态方法是属于类的。静态属性也是一样的。
- 若方法的修饰符没有'static',为非静态方法,调用这种方法一定要使用对象来调用。因为非静态方法是属于对象的。非静态属性也是一样的。
- 同一个类中的静态方法可以直接相互调用;同一个类中的非静态方法也可以直接相互调用;同一个类中的静态方法不能直接调用非静态方法;同一个类中的非静态方法可以直接调用静态方法。同一个类中,静态方法内不能直接访问到该类的非静态属性。
- 值传递和引用传递:
- 调用方法进行传参时,分为值传递和引用传递两种。
- 如果参数的类型是基本数据类型,那么就是值传递。值传递是实参把自己变量本身存的简单数值赋值给形参。
- 如果参数的类型是引用数据类型,那么就是引用传递。引用传递是实参把自己变量本身存的对象内存地址值赋值给形参。
- 所以Java中值传递和引用传递本质上都是值传递,只不过传递的东西的意义不同而已。
- 'main'方法:
- Java的'main'方法的头部写法是固定的,如下所示:
public static void main(String[] args/* 该形参名可随意定义 */) {
/* 方法体可随意定义 */
}
- Java的'main'方法是被JVM调用的,除此之外,'main'方法和普通方法没什么区别。
示例:
/* 运行main方法,结果为在控制台依次输出:2 5 */
public class TestMax {
/* main方法里调用max方法 */
public static void main(String[] args) {
int num1 = 2;
int num2 = 5;
int maxNum = new TestMax().max(num1, num2);
System.out.println(num1);
System.out.println(maxNum);
}
/* 比较两个数的大小,获取更大的值 */
public int max(int num1, int num2) {
if (num1 >= num2) {
return num1;
}
num1 = num2;
return num1;
}
}
四、方法重载
描述:
- 一个类的两个方法拥有相同的方法名,但是有不同的参数列表,就是方法重载。
- Java编译器根据方法签名的不同,判断哪个重载方法应该被调用。
- 方法重载可以提供方法调用的灵活性,可以让程序更清晰易读。
- 判断一个类中的两个方法是否相同,主要参考两个方面:方法名字和参数列表。
注意:
- 执行密切相关任务的方法应该使用相同的方法名,使用方法重载。
- 重载的方法必须拥有不同的参数列表,你不能仅仅依据修饰符或者返回类型的不同来重载方法。
示例:
/* 运行main方法,结果为在控制台依次输出:5 5.5 */
public class TestSum {
/* main方法里调用两个sum重载方法 */
public static void main(String[] args) {
double sum = new TestSum().sum(2, 3);
System.out.println(sum);
sum = new TestSum().sum(2.2, 3.3);
System.out.println(sum);
}
/* 得到两个浮点数的和 */
public double sum(double num1, double num2) {
return num1 + num2;
}
/* 得到两个整数的和 */
public double sum(int num1, int num2) {
return num1 + num2;
}
}
五、方法递归
描述:
- 递归的基本思想就是'自己调用自己',一个使用递归技术的方法将会直接或者间接的调用自己。
- 利用递归可以用简单的程序来解决一些复杂的问题,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。
- 递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。
- 递归的能力在于用有限的语句来定义对象的无限集合。
- 递归结构一般包括两个部分:
- 递归头:要有边界条件,满足边界条件时不再调用自身方法。如果没有递归头,方法调用将陷入死循环。
- 递归体:什么时候需要调用自身方法。
注意:
- 方法递归调用时,会一层层增加调用方法的层次,直到满足边界条件后,再原路返回,一层层结束方法的调用。
- 递归易理解,容易编程,但是递归用栈机制实现的,每深入一层,都要占去一块栈数据区域,对嵌套层数深的一些算法,递归会力不从心,空间上会以内存崩溃而告终,而且递归也带来了大量的函数调用,这也有许多额外的时间开销。所以在深度大时,它的时空性就不好了(会占用大量的内存空间)。
- 能不用递归就不用递归,递归都可以用循环结构来代替。循环结构效率高,运行时间只因循环次数增加而增加,没什么额外开销,空间上也没有什么增加,缺点是不容易理解,编写复杂问题时困难。
示例:
/* 运行main方法,结果为在控制台输出:120 */
public class TestFactorial {
/* main方法里调用阶乘方法 */
public static void main(String[] args) {
System.out.println(factorial(5));
}
/* 利用递归进行阶乘的计算 */
public static int factorial(int n) {
if (n == 1) {
return 1;
} else {
return n * factorial(n - 1);
}
}
}
六、可变参数
语法:
typeName... parameterName
描述:
- 从Java5开始支持传递同类型的可变参数给一个方法。
- 使用方式为在方法声明的时候,在参数列表中,在指定的形式参数类型后加一个三点省略号。
注意:
- 一个方法声明的时候只能指定一个可变参数,它必须是方法的最后一个形式参数。
- 方法声明的时候,任何普通的形式参数必须在可变参数之前声明。
示例:
/* 运行main方法,结果为在控制台依次输出:1 2 3 4 5 */
public class TestVariable {
/* main方法里调用可变参数方法 */
public static void main(String[] args) {
variable(1, 2, 3, 4, 5);
}
/* 遍历打印可变参数 */
public static void variable(int... nums) {
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}
}
}
七、'main'方法命令行传参
描述:
- 有时候希望一个程序运行的时候再传递给它信息,这要靠传递命令行参数给'main'方法实现。
- 命令行参数是在用命令行执行程序时候紧跟在程序名字后面的信息。
示例:
- Java代码
/* 在mian方法中遍历打印args参数 */
public class CommandLine {
public static void main(String[] args){
for(int i=0; i<args.length; i++){
System.out.println("args[" + i + "]: " + args[i]);
}
}
}
- CMD命令
D:\studyworkspace\springboot-demo\src\main\java\com\conyoo\springbootdemo\test> javac CommandLine.java
D:\studyworkspace\springboot-demo\src\main\java\com\conyoo\springbootdemo\test>cd D:\studyworkspace\springboot-demo\src\main\java
D:\studyworkspace\springboot-demo\src\main\java>java com.conyoo.springbootdemo.test.CommandLine command line 1 2 3
args[0]: command
args[1]: line
args[2]: 1
args[3]: 2
args[4]: 3