Java初识方法

初识方法

释义

  • 方法是组合在一起来执行操作语句的集合。

方法作用

  1. 使程序变得更简短更清晰
  2. 有利于程序维护
  3. 提高程序开发效率
  4. 提高代码重用性

方法创建与使用

【语法格式】

[修饰符列表] 返回值类型 方法名 (参数列表){ 方法体; }

[] : 加中括号的意思是,可以有,可以没有,可以有多个
修饰符列表 :
权限修饰符 : public private

【方法分类】
根据方法是否带参、是否带返回值,可将方法分为四类

  1. 静态方法
    使用static修饰的方法
  2. 成员方法
    没有static修饰的方法
  3. 构造方法
    先不管,用于创建对象

其他 : static 修饰成员或静态 , 不加static就是成员

返回值类型 : 运行完方法之后,是否需要响应数据
如果不需要,就写void
如果有,就需要写 返回数据对应的类型(11种数据类型)

所以返回值类型的值为
void+11种数据类型
8种基本
3种引用

如果方法有返回值类型,那么方法体内 必须有return语句,并且 return语句后面 需要加上和返回值类型对应的值

比如 返回值为int 那么 必须要有 return 1; 只要是int值就行,不一定非得是1
注意 return 有终止函数运行的作用(return以后的代码不执行,不能出现任何代码)

如果没有返回值类型,方法体内,就可以没有return,当然也可以有,并且return语句后面 不能添加任何数据,只能起到结束函数运行的作用
函数就是方法

Return语句并不是必须要在程序的最后,

方法名
望文知意
命名规范
符合标识符要求 :
大小写字母,美元符号,下划线,数字,数字不能打头,不能单独使用关键字和保留字

参数列表 :
就是使用这个方法,需要传递的数据

形参 :
是指在方法定义处,需要传入的参数类型的定义
实参 :
调用方法的时候,实际传入的值

方法参数列表中的变量,是局部变量
并且参数列表中可以定义多个变量,多个之间用 逗号 , 隔开
也可以没有,即使没有参数列表, () 小括号还是要有的,这是语法问题

方法体 :
代码段,保存代码

public class Method_02 {

	public static void main(String[] args) {
		// 重复功能的代码只写一遍,想要多次完成某个功能,就多次使用这个方法即可
		// 传入的参数不同,函数的返回值也会不同
		int a = 1;
		sumInt(a, 2);// 1+2=3
		sumInt(10, 11);// 10+11=21
		sumInt(100, 200);// 100+200=300
		sumDouble(0.1, 0.2);// 0.1+0.2=0.3
		m1(1);
		// 方法返回值是1
		System.out.println(m1(1));
	}

	// a和b是传递过来的
	public static int sumInt(int a, int b) {
		// 形参不能在方法中重复定义
		// long a = 2L ;
		int c = a + b;
		System.out.println(a + "+" + b + "=" + c);
		return c;
	}

	public static void sumDouble(double a, double b) {
		double c = a + b;
		System.out.println(a + "+" + b + "=" + c);
	}

	// 可以使用多的修饰符修饰方法
	// 静态 最终 同步锁
	public static final synchronized void sss() {

	}

	/**
	 * 方法名命名规则: 1.首字母:英文或者$ 2.由英文,$,和数字构成 3.不能使用关键字和保留字 4.首字母小写,驼峰命名法
	 */

	public static void class1() {

	}

	/**
	 * 如果参数大于0 返回1
	 * 
	 * 否则返回-1
	 */
	public static int m1(int i) {
		// if单分支,有不执行的情况
		// 改进方法是用if-else结构,或在结尾加return
		if (true) {
			return 1;
		}
		return -1;
	}
}

方法调用

  • 静态方法
    类名.静态方法名(参数);
    当前类中类名可以省略
  • 成员方法
    对象.成员方法名(参数);
    为什么静态方法调用需要加类名呢?
    如果想要使用一个数据,必须先找到这个数据
    如果你想打我, 必须先找到我

方法不调用不执行,调用才执行,并把结果返回到方法调用处

程序是从上往下,从左到右执行,函数的出现,就可以任意顺序的编写,因为编写的时候不执行,调用才执行,所以 就不需要考虑方法的编写位置,但是在方法的内部,依然是 从上往下从左到右执行

方法,定义的时候不执行

特殊的方法 : main
所有方法的调用起点和终点 都是在main中
Main方法由JVM自动调用

public class Method_05 {

	public static void main(String[] args) {
		m1();
		Method_05.m1();
		// 调用别的类的静态方法的时候,必须加类名
		// m2();应该是A.m2();
		A.m2();

		// 只要是调用其他类中的静态数据,必须加对应类的类名
		A.m1();

		// 接收方法的返回值,因为返回值类型的int,所以用int声明的变量就可以接收返回的值
		int i = m4(false);
		System.out.println(i);
	}

	// 不调用不执行
	public static void m1() {
		System.out.println("Method_05 m1  execute");
		// 方法m1调用方法m3
		m3();
	}

	public static void m3() {
		System.out.println("Method_05 m3  execute");
	}

	public static int m4(boolean flag) {
		if (flag) {
			return 1;
		} else {
			return 0;
		}
	}
}

class A {
	public static void m2() {
		System.out.println("m2 execute");
	}

	public static void m1() {
		System.out.println("A m1 execute");
	}
}

重载 Overload

唯一性
方法名相同,参数列表不同,叫方法重载
参数列表不同 :

  1. 个数不同
  2. 类型不同

一定要注意,重载和返回值 以及修饰符列表 都没有关系


/**
 * 重载 Overload 唯一性 方法名相同,参数列表不同,叫方法重载 参数列表不同: 1.个数不同 2.类型不同
 * 
 * 一定要注意,重载和返回值 以及修饰符列表 都没有关系
 * 
 * @author lenovo
 * @Date 2020年6月28日
 * @Time 下午6:23:02
 */
public class Method_08 {
	public static void main(String[] args) {
		System.out.println(Colculate.sumInt(1, 2));
		System.out.println(Colculate.sumDouble(1.2, 2.3));
		System.out.println(Colculate.sumLong(1274684l, 22354641l));
		// 上面的这种情况,功能相同,名字不同,代码太多,不好记,太难看

		int i = 2;
		System.out.println(Colculate.sum(1, 2));
		System.out.println(Colculate.sum(1, 52.32));
		System.out.println(Colculate.sum(1165l, 2315));

		// 分析一下方法是否是重载
		System.out.println(1);
		System.out.println(1.2);
		System.out.println(true);
		System.out.println("------");
		System.out.println('a');
	}

	public static void m1() {

	}

	int m1(int i) {
		return 1;

	}

	int m1(double i) {
		return 1;
	}

	int m1(int i, int a) {
		return 1;
	}

	int m1(long i, int a) {
		return 1;
	}

	int m1(int i, long a) {
		return 1;
	}

	int m1(int i, double a) {
		return 1;
	}
}

class Colculate {
	public void m1() {
		System.out.println("---==============---");
	}

	public static int sumInt(int a, int b) {
		return a + b;
	}

	public static double sumDouble(double a, double b) {
		return a + b;
	}

	public static long sumLong(long a, long b) {
		return a + b;
	}

	public static int sum(int a, int b) {
		return a + b;
	}

	public static long sum(long a, long b) {
		return a + b;
	}

	public static double sum(double a, double b) {
		return a + b;
	}
}

内存分析

程序 : 可以执行文件就叫程序,是静态概念,保存在硬盘中
进程 : 就是正在执行的文件,是个动态概念
运行起来的程序,就是指载入到内存的可执行文件,这个时候,操作系统会开启一个进程来执行内存中的这个文件对象,如果要关闭某个程序,可以直接杀死某个进程

  • Java中的内存划分和管理 :
    Java Runtime Data Area : java运行时数据区 我们也可以叫做 JVM内存

内存被划分了5个区域 : 程序计数器,方法区/静态区/静态代码段 , VM栈(统称栈内存) , 本地方法栈 , 堆内存

程序计数器 :

是比较小的一块区域,可以看做是当前线程执行的字节码的位置指示器

方法区 :

是用来存放我们的程序文件,载入内存后的哪个程序文件对象
Java中指的是class文件
包含方法没有被调用之前,还有代码段,都会保存在方法区
方法区内还有运行时常量池

栈内存 :

虚拟机栈/VM栈 也可以叫做栈内存
方法是放到栈内存的,包括局部变量,也是在栈内存
栈内存 : 是一个以栈数据结构为模型的一段内存空间
栈 : 是一种数据结构,像弹夹,薯片盒子一样,先进后出
栈的构成因素 :

栈空间 : 就是指以栈数据结构为模型开辟的一段内存空间
栈帧 : 栈内存中,每一个栈元素都叫栈帧
栈底元素 : 最先方进入的元素
栈顶元素 : 最后方进入的元素

栈操作 :
压栈 : 就是把元素放入栈空间的过程
弹栈 : 就是把元素从栈内存中弹出的过程

栈内存 用来执行方法
方法调用 就是压栈
方法执行结束 就是弹栈

本地栈

和虚拟机栈一样,只不过虚拟机栈用来执行java方法服务,而本地栈是为JVM提供使用native方法的服务
两者结构一致

堆内存

保存对象
每个对象空间分为3大块

数据部分 : 成员变量
头部 : hashCode值
类型 : 是哪个类创建来的,引用对应的类

生命周期

1 java程序的编写
文本编辑器,按照java规定编写代码
2 编译
Javac 原文件名.java
Javac Method_10.java 就能生成对应的Method_10.class
3 运行

Java 程序名
Java Method_10
3.1 开启java虚拟机,然后把程序名对应的 Method_10.class文件载入到jvm划分的空间中,保存在静态区
3.2 jvm自动调用main方法
3.3 main方法被调用,会在栈内存开辟栈帧
3.4 jvm静态方法调用流程 在main方法中没有调用其他方法的时候,就直接执行,完事之后弹栈,程序销毁

如果main方法中有其他方法调用

1 本类方法
如果在main方法中,调用了本类的方法,就会在main方法栈帧的上面,再开辟一个栈帧,用来保存调用 的方法(m1)
如果被调用的方法中还有其他方法调用,同上,再开辟栈帧
一直到被调用的这个方法执行完成,然后弹栈,再接着main方法中的调用处接着向后执行,一直到main执行结束,main栈帧弹栈,程序销毁
如果调用的方法有返回值,会把对应的值放入临时空间中,携带返回调用处
2 其他类方法
先把对应的类,载入静态区
其他流程同上

怎么算方法执行完成呢?
1 最后一条语句执行结束,碰到方法体的大括号
2 碰到return语句

程序的静态加载和动态加载

静态加载 : 是指程序开始执行,就把相关所有的文件一次性载入内存
动态加载 : 程序开始执行,只载入相关的文件,当用到其他文件的时候,再去动态的加载

方法执行原理

方法在调用的时候,才会在内存中开辟空间
不调用的时候,不会再内存中开辟空间

方法在调用的时候,也就是在栈内存开辟栈帧分配空间
方法调用 就是压栈
方法执行结束 就是弹栈

public class Method_10 {
	public static void main(String[] args) {
		m1(1);
		System.out.println("main方法执行");
		/**
		 * m1传参数1调用方法m2()
		 * m2传参数1调用方法m3()
		 * m3输出  i=1
		 * m3输出  m3执行了
		 * 返回方法m2()  输出  m2执行了
		 * 返回方法m1()  输出  m1执行了
		 * 返回主方法    输出  main方法执行了
		 */
	}

	public static void m1(int i) {
		m2(i);
		System.out.println("m1执行了");
	}

	public static void m2(int i) {
		m3(i);
		System.out.println("m2执行了");
	}

	public static void m3(int i) {
		System.out.println("i=" + i);
		System.out.println("m3执行了");
	}
}

递归

释义

  • 程序自身调用自身的编程技巧称为递归
    递归四个特性
  1. 必须有可最终达到的终止条件,否则程序将陷入无穷循环;
  2. 子问题在规模上比原问题小,或更接近终止条件;
  3. 子问题可通过再次递归调用求解或因满足终止条件而直接求解;
  4. 子问题的解应能组合为整个问题的解。

基本思想 :
以此类推是基本思想
循环也是,递归和迭代是等价的(迭代就是循环)
步长、终止条件、初始值

// 因为没有终止条件,所以栈内存溢出
	// Exception in thread "main" java.lang.Error: Unresolved compilation problem:
	public static void m1() {
		m1();
	}

应用场景 :

  • 一般树状结构的都可以使用递归查询

递归比普通的算法耗内存,运行效率低,谨慎使用
能用循环搞定,尽量不用递归

常见问题 :

  • 需要删除一个目录下所有的文件以及子文件,类似的树状结构需求
  • 斐波那契数列这种有规律的也可以
  • 累加加和
  • 阶乘
  • 汉诺塔 等

难点 :
不容易理解,可以画栈帧调用链

演示实例 :
使用for完成1-100的累加加和

public static int sum(int a) {
		// 使用for完成1-100的累加加和
		int sum = 0;
		for (int i = 1; i <= a; i++) {
			sum += i;
		}
		return sum;
	}

使用递归完成1-100的累加加和

public static int m1(int a) {
	if (a == 1) {
		return 1;
	} else {
		// 5 = 5 + 4 + 3 + 2 + 1
		// 5 + m1(4)
		// 4 + m1(3)
		// 3 + m1(2)
		// 2 + m1(1)
		// 1
		return a + m1(--a);
	}
}

使用for完成斐波那契数列

	/**
	 * for循环完成斐波那契数列,并打印前n位的值
	 */
	public static void m1(int i) {
		if (i < 1) {
			System.out.println("位数不正确!");
			return;
		}
		// 说明i一定不小于1
		if (i == 1 || i == 2) {
			System.out.println("第" + i + "位的值是 : 1");
			return;
		}

		// 到这里说明一定是大于第二位的
		// 先把第一位和第二位打印
		System.out.println("第一位的值是 : 1");
		System.out.println("第二位的值是 : 1");

		// 当前位的前两位的值,默认是第一位
		long l1 = 1;
		// 当前位的前一位的值,默认是第二位
		long l2 = 1;
		// 当前默认是第三位
		long l3 = l1 + l2;
		for (int j = 3; j <= i; j++) {
			l3 = l1 + l2;
			System.out.println("第" + j + "位的值是:" + l3);
			// 把l2赋值给l1这时候l1就表示当前j位的前1位
			l1 = l2;
			// 把l3赋值给l2这时候l2就表示当前j位的值
			l2 = l3;
		}
	}

使用递归完成斐波那契数列

	// 计数,记录递归执行的压栈个数
	static int count = 0;

	/**
	 * 使用递归完成
	 */

	public static int fibonacci(int n) {
		// 每次执行方法对计数+1
		count++;
		// 因为斐波那契数列,最少要1位,所以判断,小于1,返回-1
		if (n < 1) {
			return -1;
		}
		// 因为斐波那契数列的前两位都是1,所以判断,n如果是1或者是2,就直接返回1
		if (n == 1 || n == 2) {
			return 1;
		}
		// 除了前两位,每一位的值都等于前两位的和,所以第n位=(n-1)位+(n-2)位
		return fibonacci(n - 1) + fibonacci(n - 2);
		// return fibonacci(4) + fibonacci(3);n=5
		// return fibonacci(3) + fibonacci(2);n=4
		// return fibonacci(2) + fibonacci(1);n=2
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值