14、Java中的方法

198 阅读12分钟

Java中的方法

作者:韩茹

公司:程序咖(北京)科技有限公司

程序咖:IT职业技能评测平台

网址:www.chengxuka.com

1_MJ6hW6W2OWM4GAKl97gk-A

任务

1.方法
2.方法的重载
3.递归

一、方法

1.1 什么是方法

Java的方法类似于其它语言的函数,是一段用来完成特定功能的代码片段。
  方法的本质,就是一段代码。实现某个独立的功能。可以被多次调用。

1.2 为什么要声明方法

DRY(Don't Repeat Yourself)原则,把能被复用的逻辑抽取出来
实现相对独立的逻辑
实现比较复杂的逻辑
可以对具体实现进行隐藏/封装

1.3 方法的作用

简化代码,提高代码的可读性,提高代码的可维护性【版本迭代】

1.4 方法的使用:

需要以下两个步骤,缺一不可:

  • 声明:仅仅是声明了 这个方法,方法中的代码不会被执行的
  • 调用:根据方法名将方法调用,才会执行方法中的代码。调用几次,代码就执行几次。

1.5 方法的声明格式

语法:
	访问权限修饰符  其他修饰符  返回值类型  函数名称(参数列表) {
		//函数体【方法体】
		return 返回值;
	}
示例:
  public static void getSum(){
        方法体;
    }

踩坑:方法声明的位置。

1方法声明的位置

示例代码:

/*
* 方法
*/
public class Demo36Method {	
	/**
	 * main函数,不同于其他方法,是一个程序的唯一的入口。JVM自动执行main()方法中的内容。
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		//1.此处求1-10的和
		//step2:调用方法:方法名()
		getSum();//方法的调用处
		System.out.println("其他的代码。。。。10行。。。");
		//2.此处求1-10的和
		getSum();
		
		System.out.println("Hello world。。。");
		//3.求1-10的和
		getSum();
	}

	//step1:定义一个方法,也叫方法的声明
	/*
	 * (),方法的标志
	 * [],数组
	 * <>,泛型
	 * {},一段代码,一个类,一个方法,一个代码块
	 * 
	 * 方法名:小驼峰命名方式
	 * 注意点:方法声明的时候,方法里的代码不会被执行的。
	 */
	public static void getSum(){
		int sum = 0;
		for(int i = 1;i<=10;i++){
			sum += i;
		}
		System.out.println("1-10的和:"+sum);
	}
}

运行结果:

fangfa1

课堂画图:

2方法的执行过程

示例代码:

public class Demo37Method 
{

	public static void getSum(){
		//求1-100的和
		int sum = 0;
		for(int i = 1;i <= 100;i++){
			sum += i;
		}
		System.out.println(sum);
	}
	
	public void printTriangle(){
		for(int i = 0;i<5;i++){
			for(int j = 0;j <= i;j++){
				System.out.print("*");
			}
			System.out.println();
		}
	}

	public static void main(String[] args) 
	{
		System.out.println("Hello World!");
		/*
练习1:声明一个方法:有static关键字。用于求1-100的和。将结果在方法中打印。主函数中调用该方法2次。

练习2:声明一个方法:没有static关键字。用于打印一个三角形。主函数中调用该方法3次。
*/
		getSum();
		getSum();
		
		Demo56 d = new Demo56();
		d.printTriangle();
		d.printTriangle();
		d.printTriangle();
	}
}


方法的调用过程:

方法调用

1.6 方法声明中需要注意

a.一个完整的函数包含声明部分和实现部分
b.访问权限修饰符:public,default【如果没有添加任何的访问权限修饰符,则默认为default,而default不需要显式的写出来】,目前使用的访问权限修饰符都和main函数保持一致,使用public
c.其他修饰符:static 【静态的】,要么不写【非静态函数】,要么写上【静态函数】
d.返回值类型:函数运行之后所得到的结果的数据类型,如果没有运行结果,则直接为void【空】
e.函数名称:标识符【遵循小驼峰】,尽量做到顾名思义
f.参数列表:如果函数所实现的功能中有未知项参与运算,就可以将未知项设置为参数
		实际参数:实参,在函数外面定义,表示实际参与运算的值或者变量,作用为了给形参进行赋值
		形式参数:形参,在函数中定义,用于接收实参的值,相当于是一个未被赋值的变量
		形参数据类型  形参变量名称
		形参 = 实参;	
g.函数体:抽取出来的具有特殊功能的代码段
h.return 返回值:将当前函数运行之后的结果进行返回,返回给当前函数的调用者
		return:结束整个方法

1.7 方法的调用格式

语法:函数名称(实参列表)
	注意:
	a.实参的数量和类型必须和形参保持完全的一致,实现书写的顺序也必须和形参中的顺序保持完全一致
	b.函数之间只能进行相互的调用,而不能在函数中声明函数,就目前而言声明的函数都和main函数时并列的
	c.定义函数的时候,运算的结果会返回给调用者【在哪个函数中调用,运算的结果返回给哪个函数】	

踩坑:方法中的注意点如下:

public class Demo38Method {
	

	public static void main(String[] args) {
		/*
		 * 方法的注意点:
		 * 1、方法只有声明,没有调用。那就白写了。
		 * 2、方法没有声明,直接调用。那么报错。该方法未定义。
		 * 3、方法的声明位置,类里,其他方法外。关键是在哪里调用。
		 * 4、同一个类中,方法名不能冲突。
		 * 
		 * 补充:局部变量,方法里声明的变量。在哪个方法中声明的变量,就只能在哪个方法中使用。作用域。
		 */
		
		test2();
	}
	
	
	public static void test1(){
		System.out.println("test1()方法。。");
		int num = 100;
		test2();
		
	}
	public static void test2(){
		System.out.println("test2()方法。。");
//		System.out.println(num);//报错
		test1();
	}
//	public static void test2(){
//		System.out.println("我是另一个方法。。。");
//	}

}


1.8 练习题

课堂练习1:声明方法

1. 最简单的方法
void sum(){
  System.out.println("加法操作");
}
2. 拥有修饰符的方法
public static void sum(){
  System.out.println("加法操作");
}
3. 拥有参数的方法
public static void sum(int a,int b){
   System.out.pritln("两数相加结果"+a+b);
}
4.拥有返回值的方法
public static int sum(int a,int b){
  return a+b;
}

课堂练习2:调用方法

public class  Test
{
	public static void main(String[] args) 
	{
		//需求:打印多遍九九乘法表
		/*
		for(int i = 1;i <= 9;i++) {
			for(int j= 1;j <= i;j++) {
				System.out.print(j + "x" + i + "=" + i * j + " ");
			}
			System.out.println();
		}
		for(int i = 1;i <= 9;i++) {
			for(int j= 1;j <= i;j++) {
				System.out.print(j + "x" + i + "=" + i * j + " ");
			}
			System.out.println();
		}
		*/

		System.out.println("start");

		print();
		print();
		print();
		print();	
		System.out.println("end");
	}

	//对于打印九九乘法表的功能提取出来一个函数
	/*
	访问权限修饰符  其他修饰符  返回值类型  函数名称(参数列表) {

		//函数体【方法体】

		return 返回值;
	}
	*/
	public static void print() {
		for(int i = 1;i <= 9;i++) {
			for(int j= 1;j <= i;j++) {
				System.out.print(j + "x" + i + "=" + i * j + " ");
			}

			System.out.println();
		}
	}
}

二、方法中的参数

方法中的参数

工作原理:调用方法的时候,用实参给形参进行赋值,这个过程被称为传参

​ 形参就是一个变量,实参就是一个常量或者携带着值的变量,传参就是把实参赋值给形参 ​ 传参时需要注意的事项:实参的数量和类型必须和形参的数量和类型保持一致【相兼容的数据类型】

示例代码:


//程序咖
public class Demo39Param {

	public static void main(String[] args) {
		/*
		 * 参数:
		 * 形式参数:简称形参。声明方法的时候,用于接收外部传入的数据。
		 * 实际参数:简称实参。调用方法的时候,传给形参的具体的赋值。
		 * 
		 * 方法调用:方法名,实参必须严格匹配形参。
		 * 	方法名(实参);
		 * 
		 * 将实参赋值给形参的过程:参数的传递。简称:传参。
		 */
		// 1.求1-10的和
		getSum(10);//实参

		// 2.求1-20的和
		getSum(20);
		
		//3.求1-100的和
		getSum(100);
	}
	/**
	 * 方法用于求1-n的和。
	 * 参数:声明方法的时候,如果有些变量的数值,无法确定。就可以定义为参数。写在()内。
	 * 	数值由调用处传入。
	 * 
	 * 参数的本质:就是一个局部变量:声明和赋值分开了
	 * 
	 * @param n
	 */
	public static void getSum(int n) {//形参:用于接收外部传入的数据
		int sum = 0;
		for (int i = 1; i <= n; i++) {
			sum += i;
		}
		System.out.println("1-"+n+"的和:" + sum);
	}
}


执行过程分析:

3参数的传递

课堂练习:

//演示参数的使用
class Demo40 
{
	public static void main(String[] args) 
	{
		//需求:交换两个变量的值

		//实参
		int a = 10;
		int b = 20;
		
		//调用函数
		swap(a,b);

		System.out.println("main函数中的a=" + a);//10
		System.out.println("main函数中的b=" + b);//20
	}

	//分析:需要参数(两个参数)
	//		不需要返回值
	//形参:没有携带值的变量,多个变量之间使用逗号分隔
	public static void swap(int a,int b) {
		//定义一个中间的临时变量
		int temp = 0;
		temp = a;
		a = b;
		b = temp;

		System.out.println("swap函数中的a=" + a);//20
		System.out.println("swap函数中的b=" + b);//10
	}
}

三、方法的返回值

方法的返回值

​ return关键字的使用

​ a.表示一个函数执行完成之后所得到的结果 ​ void:表示没有返回值

​ b.return的使用 ​ 1>在没有返回值的函数中使用return ​ return单独成立一条语句,类似于break或者continue,后面不能跟任何的数值 ​ 作用:结束整个方法

​ 2>在一个有返回值的函数中使用return ​ 这种情况下函数中必须出现return ​ return后面必须跟一个具体的数值,而且数值的类型和返回值类型必须保持一致 ​ 作用:结束整个方法,并且将返回值携带给调用者

​ 3>如果一个自定义的函数有返回值,并且在方法中遇到了分支结构,使用return ​ 在每一个分支后面都需要出现一个return

示例代码:


//程序咖
public class Demo41Return {

	public static void main(String[] args) {
		
		/*
		 * 一个方法的返回值:一个方法执行之后的结果,返回给调用处。
		 * 声明方法的时候:标注清楚该方法的返回值类型,如果没有返回值就写void。
		 */
		// 在main中获取1-10的和结果,放大10倍,打印
		int res = getSum();//相当于int res = sum
		System.out.println(res * 10);
	}

	/**
	 * 一个方法如果有返回值,那么声明的时候要写清楚返回值类型,只能写一个。
	 * 如果没有返回值,就写void
	 * 方法中必须使用return语句返回这个结果。
	 * @return
	 */
	public static int getSum() {//This method must return a result of type int
		int sum = 0;// 局部变量,只能在该方法中使用
		for (int i = 1; i <= 10; i++) {
			sum += i;
		}
//		System.out.println(sum);//55
		return sum;//将sum的值,传递给方法的调用处
	}

}

分析执行过程:

4返回值

踩坑:return的注意点:

return语句:
	用法:1、将结果返回给调用处。2、结束该方法的执行。

注意点:
	1、如果一个方法声明有返回值(不是void),那么方法中必须使用return语句,返回结果。
	2、方法声明的返回值类型,和return语句后的数据类型一致。但是包含那些能够自动转型的类型
				返回值类型intintbyteshortchar
				返回值类型doublebyteshortintlongfloatdouble
	3、如果一个方法声明有返回值,方法中有分支语句,循环语句。。无论执行哪个分支,最终有return语句可以执行。
	4return用于返回结果,并强制结束该方法的执行。习惯上return语句往往是方法中的最后一行代码。
	5、如果一个方法声明没有返回值类型,void,方法中

示例代码:

public class Demo42Return {

	public static void main(String[] args) {
		/*
		 * return语句:
		 * 	用法:1、将结果返回给调用处。2、结束该方法的执行。
		 * 
		 * 
		 * 注意点:
		 * 1、如果一个方法声明有返回值(不是void),那么方法中必须使用return语句,返回结果。
		 * 
		 * 2、方法声明的返回值类型,和return语句后的数据类型一致。但是包含那些能够自动转型的类型
		 * 返回值类型int:int,byte,short,char
		 * 返回值类型double:byte,short,int,long,float,double
		 * 
		 * 3、如果一个方法声明有返回值,方法中有分支语句,循环语句。。无论执行哪个分支,最终有return语句可以执行。
		 * 
		 * 4、return用于返回结果,并强制结束该方法的执行。习惯上return语句往往是方法中的最后一行代码。
		 * 
		 * 5、如果一个方法声明没有返回值类型,void,方法中
		 */
//		System.out.println(test1());
//		  System.out.println(test5());
//		  
//		  test6();
		test7();
	}
	
	public static int test1(){
		return 200;
	}
	
	public static int test2(){
		byte i = 100;
		return i;
	}
	
	public static int test3(){
		int age = 30;
		if(age < 0){//if,switch,for,while,do-while
			return 0;
		}else{
			return age;
		}
	}
	public static int test4(){
		return 0;//返回结果,并结束该方法的执行。
//		System.out.println("haha");
	}
	
	public static int test5(){
		int age = 10;
		if(age < 0){
			return 0;//返回结果,结束方法
		}
		System.out.println("...."+age);
		return age;
	}
	
	public static void test6(){
		int age = -30;
		if( age < 0){
			return ;//没有返回,只用于结束方法
		}
		System.out.println("你的年龄:"+age);
	}
	
	public static void test7(){
		for(int i=1;i<=10;i++){
			if (i==5){
//				break;//强制结束循环语句
				return;
			}
			System.out.println(i);
		}
		System.out.println("test7..over...");
	}

}


方法的返回值练习

class Demo43 
{
	public static void main(String[] args) 
	{
		show();
	}
	/*
	1>在没有返回值的函数中使用return
			return单独成立一条语句,类似于break或者continue,后面不能跟任何的数值
			作用:结束整个方法
	*/
	public static void show() {
		System.out.println("Hello World!");

		int x = 10;
		if(x > 5) {
			return;//在某些情况下,可以使用return替换break
		}

		// 错误: 无法访问的语句
		System.out.println("Hello World!========");
	}
}
class  Demo44
{
	public static void main(String[] args) 
	{
		int result =  add(10,20);
		System.out.println(result);

		System.out.println(add(11,22));

		//如果一个函数返回值类型为void,则不能再调用函数的同时直接打印
		// 错误: 此处不允许使用 '空' 类型
		//System.out.println(show(11,22));
		show(11,22);
	}

	/*
	2>在一个有返回值的函数中使用return
			这种情况下函数中必须出现return
			return后面必须跟一个具体的数值,而且数值的类型和返回值类型必须保持一致
			作用:结束整个方法,并且将返回值携带给调用者
	*/

	//需求:求两个变量的和
	public static int add(int a,int b) {
		int sum = a + b;
		//谁调用,返回给谁
		//return每次只能携带一个数据返回
		return sum;
	}

	public static void show(int a,int b) {

		int sum = a + b;
		System.out.println(sum);
	}
}
class  Demo45
{
	public static void main(String[] args) 
	{
		int result = compare(34,67);
		System.out.println(result);
	}
	/*
	3>如果一个自定义的函数有返回值,并且在方法中遇到了分支结构,使用return
			在每一个分支后面都需要出现一个return
	*/
	//需求:比较两个变量的大小,返回较大的一个
	public static int compare(int num1,int num2) {
		//多分支
		/*
		if(num1 > num2) {
			return num1;
		} else if(num1 < num2) {
			return num2;
		} else {
			return num1;
		}
		*/

		//出现的问题:在使用单分支的时候,分支内部有return,这时编译还是不通过
		//解决办法:在单分支的外面再添加一个返回值,返回值随意,只要类型和返回值类型匹配就ok
		//单分支
		if(num1 > num2) {
			return num1;
		}

		//没有实际意义,作用只是为了匹配语法
		return 0;	 
	}
}

四、方法的重载

方法重载的概念:

同一个类中,方法名字相同,参数列表不同。则是重载
注意:
	1. 参数列表的不同包括,参数个数不同,参数数据类型不同,参数顺序不同
	2. 方法的重载与方法的修饰符和返回值没有任何关系

方法的重载:

概念:一个类中的,一个功能方法的多种体现形式(有不同的方法体)。
举例:
	1、人类,有吃的功能:eat()
			eat(食物);
			eat(药);
			eat(口香糖);
		
	2、求和的功能:
			getSum(int i,int j);
			getSum(double d1, double d2);
	3、水:
		常温:液态
		0度以下:固态
		100度以上:气态
		
就是同一个功能的方法,因为参数的不同,调用的具体的方法也不同。
如何判定多个方法是否是重载的?衡量标准,要同时满足以下三条:
	A:必须同一个类中。
	B:方法名称必须一致。
	C:参数列表必须不同。(顺序,个数,类型)
	
        和static,public,返回值,void等等都没有关系。
优点:
	1、简化了开发的压力
	2、简化了记忆的压力
	3、调用方法更方便,更简洁,又满足了不同的情况
        
基本原理:
    当方法名称一致时,通过形式参数列表的不同来选择要执行的方法。

示例代码:

//演示方法的重载
//测试类
public class Demo46Overload 
{
	public static void main(String[] args) 
	{
		//对于重载函数而言,具体调用的是哪个函数,取决于所传的参数
		Check.show("10");
		Check.show("10",10);
	}
}
//实体类
/*
在同一个类中,如果满足以下的条件,则称为这几个方法之间彼此重载
		a.方法名相同
		b.参数不同【数量不同或者类型不同】
		c.访问权限修饰符和返回值类型没有影响
*/
class Check
{
	public static void show() {
		System.out.println("无参无返回值的show");
	}

	//1.改变参数
	public static void show(int a) {
		System.out.println("int的show");
	}

	public static void show(String a) {
		System.out.println("String的show");
	}

	public static void show(String a,int b) {
		System.out.println("String  int的show");
	}

	//2.改变返回值:返回值对方法的重载没有任何影响
	//只改变返回值类型,其他都不改变,则对于编译器而言,则认为是同一个方法
	/*
	public static String show() {
		System.out.println("String返回值的show");

		return "abc";
	}
	*/

	//3.访问权限修饰符
	//只改变访问权限修饰符,其他都不改变,则对于编译器而言,则认为是同一个方法
	/*
	static void show() {
		System.out.println("show");
	}
	*/
}

课堂画图:

1方法的重载

五、 递归算法

递归算法的概念:在一个方法的方法体内调用该函数本身,称为函数的递归。

方法递归包含了一种隐式的循环,会重复执行某段代码,但是这种重复不需要使用循环语句来进行控制

示例代码:求和

public class Demo47Recursion 
{
	public static int getSum(int n){
		if(n == 1){

			return 1;

		}

		return getSum(n-1)+n;

	}
	public static void main(String[] args) 
	{
		int sum = getSum(5);

		System.out.println(sum);
	}
}


运行结果:

fangfa4

分析过程

递归调用

示例代码:求斐波那契数列

class  Demo48Fibonacci
{
	public static void main(String[] args) 
	{
		/*
		斐波那契数列
		1,2,3,4,5,6, 7, 8, 9,10,11,.....
		1,1,2,3,5,8,13,21,34,55,89....

		分析:
		1.第一个位置和第二个位置上的数是固定的,都是1
		2.第n个位置上的数 = 第n - 1个位置上的数 + 第n - 2个位置上的数

		fun(1)  = 1
		fun(2) = 1
		fun(3) = fun(2) + fun(1) = 1  + 1
		fun(4) = fun(3) + fun(2) = fun(2) + fun(1) +fun(2)
		fun(5) = fun(4) + fun(3) = fun(3) + fun(2) + fun(2) + fun(1) = fun(2) + fun(1) + fun(2) + fun(2) + fun(1)
		....
		fun(n) = fun(n - 1) + fun(n -2)
		*/

		int result1  = fun(10);
		System.out.println(result1);
	}
	//需求:报个数,获取在斐波那契数列中对应的数
	public static int fun(int n) {
		if(n == 1 || n == 2) {
			return 1;
		} else {
			int num1 = fun(n - 1);
			int num2 = fun(n -2);
			int sum = num1  + num2;

			System.out.println("num1=" + num1 + ",num2=" + num2);
			return sum;
		}
	}
}

示例代码:求1~某个数之间所有整数的和

class Demo49 
{
	public static void main(String[] args) 
	{
		int result = total(100);
		System.out.println(result);
	}

	//需求:求1~某个数之间所有整数的和
	//普通方式
	public static int add(int n) {
		int sum = 0;
		for(int i = 1;i <= n;i++) {
			sum += i;
		}
		return sum;
	}

	//使用递归实现
	/*
	total(1) = 1
	total(2) = total(1) + 2
	total(3) = total(2) + 3 = total(1) + 2 + 3
	....
	total(n) = total(n - 1) + n
	*/
	public static int total(int n) {
		if(n == 1) {
			return 1;
		} else {
			return total(n - 1) + n;
		}
	}
}

课堂练习:

class Demo50 
{
	public static void main(String[] args) 
	{
		method1();
      	method2(10);
	}
  public static void method1() {
    //输出100~200之间能被3整除的数
	for(int i = 100;i <= 200;i++) {
		if(i % 3 != 0) {
			continue;
		}

		System.out.println(i);
	}
  }
  public static void method2(int num) {
    //判断一个数是否为质数
	//质数:除了1和本身能整除,如果出现一个数可以将这个数整除的话,那么这个数就不是质数
	//1.假设是质数
	boolean isPrime = true;
	//2.寻找能够整除num的数,只要出现一个,则原来的假设被推翻
	for(int i = 2;i < num;i++) {
		//3.大对小求余
		if(num % i == 0) {
			//4.修改原来假设的状态
			isPrime = false;
			break;
		}
	}
	return isPrime;
  }
}

课堂练习:

class Demo51 
{
	public static void main(String[] args) 
	{
		getNum(100);
		getNum1(10);
      	exchange();
	}

	//1.求1--某个数之间可以被7整除的数的个数
	public static int getNum(int n) {
		int count = 0;
		for(int i = 1;i <= n;i++) {
			if(i % 7 == 0) {
				count++;
			}
		}
		return count;
	}

	//2.计算1到某个数以内能被7或者3整除但不能同时被这两者整除的数的个数。
	public static int getNum1(int n) {
		//&&
		int count = 0;
		for(int i = 1;i <= n;i++) {
			if((i % 7 == 0 || i % 3 == 0) && i % 21 != 0) {
				count++;
			}
		}

		//嵌套if语句
		int count1 = 0;
		for(int i = 1;i <= n;i++) {
			if(i % 7 == 0 || i % 3 == 0) {
				if(i % 21 != 0) {
					count1++;
				}
			}
		}
		return count;
	}

	//3.从键盘输入两个数,赋值给两个变量,交换这两个变量的值【三种方法】
	public static void exchange() {
		int a = 10;
		int b = 20;

		//方式一:异或【面试题:不采用第三方变量,交换两个变量的值】
		a = a ^ b;   //10 ^ 20
		b = a ^ b;	 //10 ^ 20 ^ 20 = 10
		a = a ^ b;   //10 ^ 20 ^ 10 = 20

		//方式二:加法
		int c = a  + b;//30
		a = c - a;//30 - 10 =20
		b = c - a; //30 - 20 = 10

		a = a  + b;
		b = a - b;//10
		a = a - b;//20

		//方式三:
		int temp = a;
		a = b;
		b = temp;
	}
}