方法的基础语法
方法就是一段代码片段,可以完成一个特定的功能,可以被多次使用,方法在C中成为函数
方法定义在类体,一个类体可以定义多个方法,方法的顺序可以任意,但是方法里不可以定义方法
方法的定义
[修饰符列表] 返回值类型 方法名 (形式参数列表) {
//方法体
}
修饰符列表 是可选项,不是必须的,现在可写成 public static 【以后涉及】
返回值类型
返回的值是具体存在的数据,数据都有类型;void返回的是空;若不是void必须返回一个具体的数据
方法名首字母小写,最好是动词,见名知意。
形参是局部变量,个数是0~N个,逗号隔开,形参和实参必须满足数量相同和数据类型相同。
方法的修饰符列表中有static 怎么调用这个方法? 类名.方法名(实际参数列表);
public class MethodTest {
//类体
//类体中不能直接编写JAVA语句,除了声明变量外
//方法出现在类体中
//方法
//public公开的,static静态的,void是方法执行结束不返回任何数据
//main是方法名:主方法
//(String[] args) 形式参数列表,String[]是参数的数据类型,args是局部变量的变量名
//所以只有args可以随意更改变量名
public static void main(String[] args){
//调用MethodTest的sum方法
MethodTest.sum(10,20);
int j = 11;
int k = 12;
MethodTest.sum(j,k);
}
//自定义方法
public static void sum(int i,int j){
System.out.println(i+"+"+j+"="+(i+j));
}
}
方法的调用不一定在main方法中
public class MethodTest02 {
//方法的调用不一定在main方法中
public static void main(String[] args){
MethodTest02.sum(10,20);//调用 sum() 函数
System.out.println("HELLO");
}
public static void sum(int i,int j){
System.out.println(i+"+"+j+"="+(i+j));
//调用dosome()方法
MethodTest02.dosome();
}
public static void dosome(){
System.out.println("do some !");
}
}
研究一下return语句:
public class Return {
//return一旦执行,所在方法就执行结束
//同一个方法中return下面不写代码,因为下面的代码执行不到,所以编译报错
//以下程序不能百分百的编译return 1; 编译报错
public static int m(){
int a = 10;
if (a > 3){
return 1;
}
}
}
public static int m(){
int a = 10;
if (a > 3){
return 1;
System.out.println("Hello"); //return后面不能写代码,因为执行不到,编译报错
}
return 0;
}
return是结束整个方法
break是结束整个循环,二者作用的范围都不一样
方法执行内存分析
方法在执行过程中,在JVM的内存是如何分配的,内存是如何变化的?
1、方法只是定义,不调用,是没有执行的,那么在JVM中也不会给该方法分配“运行所属”的内存空间,只有调用的时候才分配空间。
2、在JVM 的内存划分上有三块注意的内存空间
方法区内存
堆内存
栈内存
3、栈,stack,一种数据结构,数据结构是反映了数据的存储形态,常见的数据结构:数组、队列、栈、链表、二叉树、哈希表/散列表......
栈帧永远指向栈顶
栈顶元素处于活跃状态,其他元素静止
术语:压栈/入栈 push
弹栈/出栈 pop
4、方法代码片段在属于.class字节码文件的一部分,字节码在类加载的时候,将它放入了方法区当中,所以JVM中的三块主要的内存空间中方法区最先有数据,存放了代码片段; 代码片段虽然在方法区中只有一份,但是可以被重复调用,每次调用这个方法的时候,需要给该方法分配独立的活动场所,在栈内存中分配。【栈内存中分配方法运行的所属内存空间】
5、方法在调用的时候,会给该方法分配内存空间,此时会发生压栈动作,方法执行之后,给该方法分配的内存空间全部释放掉,此时发生弹栈
6、局部变量在方法体中声明,局部变量在运行阶段,内存在栈中存储。
参数传递的是变量的值。分析以下代码
public static void main(String[] args){
int i = 10;
method(i);
System.out.println("main------"+i);
}
private static void method(int i) {
i++;
System.out.println("method-----"+i);
}
结果是
原因是
方法的重载overload
public class Overload01 {
public static void main(String[] args){
//参数类型不同,对应调用的方法就不同,此时区分方法不再是依赖方法名而是依靠参数的类型
System.out.println(sum(1,1));
System.out.println(sum(1l,1l));
System.out.println(sum(1.0,1.0));
}
public static int sum(int i, int j) {
System.out.println("sum(int, int)");
return i+j;
}
public static long sum(long i, long j) {
System.out.println("sum(long, long)");
return i+j;
}
public static double sum(double i, double j) {
System.out.println("sum(double, double)");
return i+j;
}
}
程序员在调用方法的时候,比较方便,虽然调用的是不同的方法,但是感觉就像在调用同一个方法,不需要记忆更多的方法名。
代码美观
前提:功能相似的时候,方法名可以相同
但是,功能不同的时候,方法名尽量不同
什么时候考虑方法重载?
功能相似的时候,尽可能让方法名相同,但是不同或者不相似的时候,尽可能让方法名不同。
什么条件满足之后构成方法重载?
1 在同一个类中
2 方法名相同
3 参数列表不同:数量不同;顺序不同;类型不同
public static void m1(){}
public static void mi(int a){}
public static void m1(int a,double b){}
public static void m1(double a,int b){}
public static void m1(int a){}
public static void m1(double a){}
方法重载和什么有关?和什么无关?
方法重载和返回值类型、修饰符列表无关,方法重载和方法名、参数列表有关
方法递归
1 方法自身调用自身。
A(){
A(){}
}
2 方法递归是很耗栈内存的,尽量不用
3 以下程序运行时候发生的一个错误【不是异常,是错误Error】
java.lang.StackOverflowError 栈内存溢出错误
错误发生,无法挽回,只有一个结果就是JVM停止工作
4 递归必须有结束条件,否则一定会发生内存溢出错误
5 递归即使有了结束条件。即使结束条件是正确的,也可能会发生栈内存溢出错误,因为递归的太深了
public class Recursion {
//1~n的求和;递归
public static void main(String[] args){
int i = 4;
int result = sum(i);
System.out.println(result);
}
public static int sum(int n){
if (n == 0){
return 1;
}
return n + sum(n-1);
}
}