Java基础05-方法、方法内存分配、方法重载、方法递归

方法

  • 简述
    • 方法的本质
      方法就是一段代码片段,并且这段代码片段可以完成某个特定的功能,并且可以被重复的使用。
    • 方法,对应的英语单词:Method,方法在c语言中叫做函数/Function
    • 方法定义在类体当中,在一个类当中可以定义多个方法,方法编写的位置没有先后顺序,可以随意。
    • 方法体当中不能再定义方法
    • 方法体当中由java语句构成,方法体中的代码遵守由上而下的顺序依次执行。
  • 1.方法定义,语法结构
    【修饰符列表】返回值类型 方法名【形式参数列表】{
    方法体;
    }
  • 2.对以上语法进行解释说明
    • 2.1关于修饰符列表
      • 是可选项,不是必须的
      • 目前统一写成:public static【以后讲】
      • 方法的修饰符列表当中“有static关键字”的话,怎么调用这个方法?
        类名.方法名(实际参数列表)
    • 2.2返回值类型
      • 什么是返回值?
        一个方法是可以完成某个特定功能的,这个功能结束之后大多数都是需要返回最终执行结果的,执行结果可能是一个具体存在的数据。而这个具体存在的数据就是返回值。
      • 返回值类型
        返回值是一个具体存在的数据,数据都是有类型的,此处需要指定的是返回值的具体类型。
      • 返回值都可以指定哪些类型呢?
        java任意一种类型都可以,包括基本数据类型和所有的引用数据类型。
      • 也可能这个方法执行结束之后不返回任何数据,java中规定,当一个方法执行结束之后不返回任何数据的话,返回值类型的位置需要写:void关键字
      • 返回值类型若不是void,表示这个方法执行结束返回一个具体的数值,当方法执行结束的时候没有返回任何数据的话编译器报错,怎么返回值呢,代码怎么写呢?“return 值;”,并且要求“值”的数据类型必须和"方法的返回值类型"一致。不然编译器报错。
      • 返回值类型是void的时候,在方法体当中不能编写"return 值;"这样的语句。但是注意可以编写"return;"这样的语句。
      • 只要带有return关键字的语句执行,return语句所在的方法结束。【不是JVM结束,是所在的方法结束】
    • 2.3方法名
      • 只要是合法的标识符就行
      • 方法名最好见名知意
      • 方法名最好是动词
      • 方法名首字母要求小写,后面每个单词首字母大写
    • 2.4形式参数列表:简称形参
      • 形参是局部变量
      • 形参的个数可以是:0-N个
      • 多个形参之间用“逗号”隔开
      • 形参中起决定性作用的是形参的数据类型,形参的名字就是局部变量的名字。
      • 方法在调用的时候,实际给这个方法传递的真实数据被称为:实际参数,简称实参。
    • 2.5 方法体必须由大括号括起来,方法体当中的代码有顺序,遵循自上而下的顺序依次执行。并且方法体由java语句构成,每一个java语句以";"结尾。
  • 3.方法怎么调用呢?
    方法只定义不调用时不会执行的,只有在调用的时候才会执行。
    语法规则:《方法的修饰符列表当中有static》
       类名.方法名(实参列表);<这是一条java语句,表示调用的某个类型的某个方法,传递这样的实参。>
/*
	方法的调用不一定在main方法当中,可以在其他方法当中
	只要是程序可以执行到的位置,都可以去调用其他方法
*/
pubilc class MethodTest04
{
	public static void sum(int a,int b){
		System.out.println(a + "+" + b + "=" + (a+b));
		//调用doSome方法
		MethodTest04.doSome();//允许
	}
	//主方法,程序入口
	public static void main(String[] args){
		MethodTest04.sum(1,2);
	}
	public static void doSome(){
		System.out.println("do some!");
	}
}
/*
实参和形参要求个数相同,数据类型对应相同
*/
public class MethodTest04
{
	public static void main(String[] args){
		//编译通过,存在自动类型转换
		MethodTest04.sum(10,20);
		//编译错误,double为大容量,需要强制类型转换符
		MethodTest04.sum(3.0,20);
		MethodTest04.sum((long)3.0,20);//编译通过
	}
	public static void sum(long a,long b){
		System.out.println(a + "+" + b + "=" + (a+b));
	}
}	
  • 方法调用省略"类名."
    方法的修饰符列表当中有static关键字,完整的调用方式是:类名.方法名(实参列表);
    但是,有的时候"类名."可以省略,什么情况下可以省略呢?
m1(){
	m2();
}
m1方法和m2方法在同一个类当中的时候,"类名."可以省略不写
**建议一个java文件中定义一个class,比较清晰**
public class MethodTest04
{
	public static void main(String[] args){
		MethodTest04.m();//可以
		m();//可以
		//调用其他类中的方法【不是本类中的】
		A.doOther();//可以
		//“类名.”省略后,默认从当前类中找到"doOther"方法,在当前类中该方法不存在
		doOther();//不可以
	}
	public static void m{
		System.out.println("m method execute!");
		MehtodTest04.m2();//完整的方式
		m2();//省略的方式,调用本类的m2()方法
		A.m2();//调用A类中的m2()方法
	}
	public static void m2{
		System.out.println("m2 method execute!");
	}
}
class A
{
	public static void doOther{
		System.out.println("A's doOther method invoke!");
	}
	public static void m2{
		System.out.println("A'm2 method execute!");
	}
}
``
```java
/*
返回值:
	采用变量接收,变量的数据类型和返回值的数据类型相同,或者可以自动类型转换
*/			
public class MethodTest05
{
	public static void main(String[] args){
		//boolean b = divide(10,3);//编译报错,类型不兼容
		long m = divide(10,3);//编译通过,自动类型转换
		int i = divide(10,3);//编译通过
		System.out.println(divide(10,3));
	}
	public static int divide(int a,int b){
		return a / b; 
	}
}
```java
/*
深入return语句
	*带有return关键字的java语句只要执行,所在的方法执行结束
	*在“同一个作用域”当中,return语句下面不能编写任何代码,因为这些代码永远都执行不到,所以编译报错。
*/
public class MethodTest09
{
	public static void main(String[] args){
		
	]

	//编译报错,缺少返回语句,以下程序编译器认为无法百分百保证"return 1"会执行
	/*
	public static int m(){
	int a = 10;
	if(a > 3){//编译器只会识别到"a > 3"是boolean类型,但不会得到true或者false
		return 1;
	}
	*/
	//以下程序可以保证"return 1;"或者"return 0;"执行,编译通过。
	/*public static int m(){
	int a = 10;
	if(a > 3){
		return 1;
	}else{//也可以将else{}去掉
		return 0;
	}*/
	
	/*public static int m(){
	int a = 10;
	if(a > 3){
		return 1;
		//这里不能编写代码,编译错误,因为无法访问的语句
		//System.out.println("Hello!");
	}
	//这里的代码可以执行到
	System.out.println("Hello!");
	return 0;
	//编译错误,无法访问的语句
	//System.out.println("Hello!");
	}*/

	public static int m(){
		return 10 > 3 ? 1 : 0;
	}
}
/*
	返回值类型是void的方法当中使用"return;"语句.
	"return;"语句出现在返回值为void方法当中主要是为了结束当前方法
*/
public class MethodTest09
{
	public static void main(String[] args){
		m();
		for(int i = 10;i > 0;i --){
			if(i == 2){
				return;//结束的是main方法
			}
			System.out.println("data:-->" + i);
		}
		System.out.println("Hello World!");
	}
	public static void m(){
	for(int i = 0;i < 10;i ++){
		if(i == 5){
			return;//不是终止for循环,而是终止main方法
			//break;//终止的for循环
		}
		System.out.pritnln("i -->" + i);
	}
		System.out.println("Hello World!");
	}
}

方法内存分配

  • 方法在执行过程当中,在JVM中的内存是如何分配的呢,内存是如何变化的?
    • 方法如果只定义,不去调用,是不会执行的,并且在JVM 当中也不会给该方法分配"运行所属"的内存空间。只有调用该方法时,才会动态的给这个方法分配所属的内存空间。
    • 在JVM内存分配划分上有这样三块主要的内存空间:
      • 方法区内存
      • 堆内存
      • 栈内存
    • 关于栈数据结构
      • 栈:stack,是一种数据结构
      • 数据结构反映的是数据存储形态
      • 数据结构是独立的学科,不属于任何编程语言的范畴,只不过在大多数编程语言当中要使用数据结构。
      • 作为程序员需要提前精通,数据结构 + 算法
      • java程序员在不精通数据结构和算法的前提下,也能进行java开发,因为java有一套庞大的类库支持,别人写好了,直接用。【JavaSE当中的集合章节使用了大量的数据结构】
      • 常见的数据结构:
        • 数组
        • 队列
        • 链表
        • 二叉树
        • 哈希表/散列表
      • 栈的示意图
        在这里插入图片描述
    • 方法代码片段存在哪里?方法执行的时候执行过程的内存在哪里分配?
      • 方法代码片段属于.class文件的一部分,字节码文件在类加载的时候,将其放到了方法区当中,所以JVM中的三块主要的内存空间中方法区内存最先有数据,存放了代码片段。
      • 代码片段虽然在方法区内存当中只有一份,但是可以被重复调用。每一次调用这个方法的时候,需要给该方法分配独立的活动场所,在栈内存中分配。【栈内存中分配方法运行的所属内存空间】
    • 方法在调用的瞬间,会给该方法分配内存空间,会在栈中发生压栈动作,方法执行结束之后,给该方法分配的内存空间会全部释放,此时发生弹栈动作。
      • 压栈:给方法分配内存
      • 弹栈:释放该方法的内存空间
    • 局部变量在“方法体”中声明。局部变量在运行阶段内存在栈中分配。

在这里插入图片描述

//**重点:方法调用的时候,在参数传递的时候,实际上传递的是变量中保存的那个“值”。**
// 注意:在EditPlus当中,字体颜色为红色的表示一个类的名字,并且这个类是JavaSE类库中自带的。
public clsss MethodTest01
{
	public static void main(String[] args){
		int a = 10;
		int b = 20;
		int retValue = sumInt(a,b);
		System.out.println("retValue = " + retValue);
	}
	public static int sumInt(int i,int j){
		int result = i + j;
		int num = 3;
		int retValue = divide(result,sum);
		return retValue;
	}
	public static int divide(int x,int y){
		int z = x / y;
		return z;
	}

}

上述代码的运行内存分配图如下:
在这里插入图片描述

  • 画图原则:
    1.只要涉及到参数传递的问题,传递的是变量中保存的值
    2.画图的时候,必须遵循的方法自上而下的顺序依次执行

方法重载

  • 引用,以下代码如果不引入“方法重载机制”,不适用overload,分析程序存在哪些缺陷?
public class MethodTest03
{
	public static void main(String[] args){
	//调用方法
		int result1 = sumInt(1,2);
		System.out.println("result1 -->" + result1);
		double result2 = sumDouble(1.0,2.0);
		System.out.println("result2 -->" + result2);
		long result3 = sumLong(1L,2L);
		System.out.println("result3 -->" + result3);
		
	}
	//定义一个方法,可以计算两个int类型数据的和
	public static int sumInt(int a,int b){
		return a + b;
	}
	//定义一个方法,可以计算两个double类型数据的和
	public static double sumDouble(double a,double b){
		return a + b;
	}
	//定义一个方法,可以计算两个long类型数据的和
	public static long sumLong(long a,long b){
		return a + b;
	}
}
  • 分析:
    • 分析1:sumInt、sumLong、sumDouble方法虽然功能不同,但是功能是有限的,都是求和。在以下程序当中功能相似的方法,分别起了三个不同的名字,这对于程序员来说,调用方法的时候不方便,程序员需要记忆更多的方法,才能完成调用。【不方便】
    • 分析2:代码不美观
  • 有没有这样的一种机制:
    • 功能虽然不同,但是功能相似的时候,有没有这样的一种机制,可以让程序员使用这些方法的时候就像在使用同一个方法一样,这样程序员以后编写代码比较方便,也不需要记忆更多的方法名,代码也会很美观。
    • 有这种机制,方法重载机制/Overload
  • 最终希望达到的效果是,程序员在使用上面的三个相似的方法的时候,就像在用一个方法一样。
  • Java支持这种机制【有些语言不支持,例如以后要学习的:javascript】
/*
	该方法还是一个体验程序,体验一下方法重载的优点:
		*程序员调用方法的时候,比较方便,虽然调用的是不同的方法,但是就感觉在使用同一个方法一样,不需要
		记忆更多的方法名。
		*代码美观
	前提:
		功能相似的时候,方法名可以相同。
		但是,功能不同的时候,尽可能让这两个方法的名字不同。
*/
public class OverlaodTest01
{
	public static void main(Stirng[] args){
	//调用方法的时候就像在使用一个方法一样;
	//参数的类型不同,对应调用的方法不同;
	//此时区分方法不再依赖方法名了,依靠的是参数的数据类型
		System.out.println(sum(1,2));
		System.out.println(sum(1.0,2.0));
		System.out.println(sum(1L,2L));
	}
	//以下三个方法构成了方法重载机制
	public static int sum(int a,int b){
		System.out.println("sum(int,int)");
		return a + b;
	}
	public static long sum(long a,long b){
		System.out.println("sum(long,long)");
		return a + b;
	}
	public static double sum(double a,double b){
		System.out.println("sum(double,double)");
		return a + b;
	}
}
  • 正式讲述方法重载
/*
	方法重载:
	    1.方法重载又被称为:overload
	    2.什么时候考虑使用方法重载?
	    	*功能相似的时候,尽可能让方法名相同
	    	【但是:功能不同/不相似的时候,尽可能让方法名不同】 
	    3.什么条件满足之后构成了方法重载?
	    	*在同一个类当中
	    	*方法名相同
	    	*参数列表不同:
	    	 	-数量不同
	    	 	-顺序不同
	    	 	-类型不同
	    4.方法重载和什么有关系,和什么没关系?
	    	*方法重载和方法名+参数列表有关系
	    	*方法重载和返回值类型无关
	    	*方法重载和修饰符列表无关
*/
public class OverloadTest03
{
	public static void main(String[] args){
		m1();
		m1(10);
	
		m2(1,2.0);
		m2(2.0,1);

		m3(10);
		m3(3.0);
	}
	//以下方法构成方法重载
	public static void m1(){}
	public static void m1(int a){}
	//以下方法构成方法重载
	public static void m2(int a,double b){}
	public static void m2(double a,int b){}
	//以下方法构成方法重载
	public static void m3(int x){}
	public static void m3(double x){}
    //以下方法不能构成方法重载,为方法重复
	/*
		public static void m4(int a,int b){}
		public static void m4(int b,int a){}
	*/
	
	/*返回值类型
		public static void x(){
		}
		public static int x(){
			return 1;
		}//注意可以不接收返回值
	*/
	
	/*修饰符列表
		void y(){}
		public static void y(){}
	*/
}
  • 方法重载的应用
public class OverloadTest04
{
	public static void main(String[] args){
		/*
		System.out.println("Hello World!");
		System.out.println(10);
		System.out.println(true);
		*/
		U.p(10);
		U.p(fasle);
		U.p("Hello World!");
		U.p(3.0);
	}
}
class U
{
	public static void p(byte b){
		System.out.println(b);
	}
	public static void p(short b){
		System.out.println(b);
	}
	public static void p(int b){
		System.out.println(b);
	}
	public static void p(long b){
		System.out.println(b);
	}
	public static void p(float b){
		System.out.println(b);
	}
	public static void p(double b){
		System.out.println(b);
	}
	public static void p(boolean b){
		System.out.println(b);
	}
	public static void p(char b){
		System.out.println(b);
	}
	public static void p(String b){
		System.out.println(b);
	}
}

方法递归

初认识
  • 1.什么是递归?
    方法自身调用自身
    a(){
    a();
    }
  • 2.递归是很耗费栈内存的,递归算法可以不用的时候尽量不用
  • 3.如果递归没有设置结束条件,程序就会报如下错误:【不是异常,是错误error】
    java.lang.StackOverflowError
    栈内存溢出错误
    错误无法发生挽回,只有一个结果,就是JVM停止工作
  • 4.递归必须有结束条件,没有结束条件一定会发生栈内存出错误。
  • 5.递归即使有了结束条件,即使结束条件是正确的,也可能会发生栈内存出错误,因为递归的太深了。
/*
	使用递归计算1-N的求和
		--> 1 + 2 + 3 + 4
		--> 4 + 3 + 2 + 1 : n的最初值是4,建议采用这种方式
*/
public class RecursionTest03
{
	public static void main(String[] args){
		//1-4的和
		int n = 4;
		int RetValue = sum(n);
		System.out.println(RetValue);
	}
	public static int sum(int n){
		//4 + 3 + 2 + 1
		if(n == 1){
			return 1;
		}
		return n + sum(n-1);
	}
}
  • 上述递归代码运行内存示意图
    在这里插入图片描述
  • 递归原理图
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值