背景:假如我们需要削皮的苹果a1,现在定义一个完整带皮的苹果A1,通过定义“削”的动作X1,让A1—X1—>a1。
假如我们需要削皮的苹果a2,现在定义一个完整带皮的苹果A2,通过定义“削”的动作X2,让A2—X2—
[修饰符列表] 返回值类型 方法名(形式参数列表){
方法体;
}
- 合法的标识符 - 最好见名知意 - 方法名最好是动词 - 方法名首字母小写,后面每个单词首字母大写 - 形式参数列表:形参 - 形参是局部变量 - 形参的个数可以是0-N个 - 多个形参之间使用逗号分隔 - 形参中起决定作用的是形参的数据类型,形参的名字就是局部变量的名字 - 方法在调用的时候,实际给该方法传递的真实数据被称为:实际参数:实参 - 实参和形参必须满足:数量相同、类型对应相同(可以存在类型转换)
方法仅定义,不去调用是不会被执行的,只要在调用的时候才会执行。
语法规则:
当方法的修饰符有static时:类名.方法名(实参列表);
public class Test{ //表示定义一个公开的类:该类名需要于java源文件名一致 //类体 //类体中不能直接编写java语句,除声明变量之外 //方法出现在类体当中 static int m; //声明成员变量 public static void main(String[] args){ //public公开的 static静态的 void执行完不返回任何数据 main主方法 (String[] args) 形式参数列表 String[]是一个引用数据类型 args是一个局部变量的变量名 //方法 Test.sum(20,30); //完整调用 sum(20,30); //省略调用 A.doTest(); //编译成功 doTest(); //编译报错 } public static void sum(int x,int y){ int c = x+y; System.out.println(x+"+"+y+"="+c); } } class A{ public static void doTest(){ System.out.println("doTest方法执行!"); } }
//方法的返回值类型不是void的时候 //方法:实现两个int类型数据的和 public class Method01{ public static void main(String[] args){ sum(6,2); //接收方法的返回值,当一个方法有返回值的时候,可以不接收。 //采用变量接收 //变量的数据类型需要和返回值的数据类型相同,或者自动转换 int i = sum(6,2); System.out.println(i); //测试 } public static int sum(int x, int y){ return x+y; } }
public class Method01{ public static void main(String[] args){ m(); } public static int m(){ int a = 10; if(a>5){ return 1; //编译错误 ,编译器仅判断if判断语句可能是true可能是false,即return可能执行可能不执//行 } } }
“return”语句的出现在返回值为void的方法中,目的是为了结束当前方法—弹栈。仅仅是“return;”,不能返回值“return 100;”
public class Method01{ public static void main(String[] args){ m(); } public static int m(){ for(int i=0;i<10;i++){ if(i==5){ return; //终止的m方法 不是for循环 } System.out.println("i——"+i); } System.out.println("m方法"); } }
方法在执行过程中在JVM的内存中分配情况
方法只定义不调用,是不会被执行的,并且JVM中不会给该方法分配内存空间。只有在调用该方法时,才会动态的给该方法分配内存空间。编译生成的.class文件,java类加载器找到该字节码class文件,将其放入JVM中。
JVM内存划分有三块主要的内存空间
1. 方法区内存 :方法的代码片段 (属于.class文件的一部分)字节码文件在类加载的时候,将其放入方法区当中,所以方法区是最先有数据的。代码片段虽然只有一份,但是可以被重复调用,每一次调用中国方法的时候都需要给该方法分配独立的活动内存——栈内存
2. 堆内存
3. 栈内存 :栈中分配该方法的独立内存空间,压栈;方法结束,该方法分配的内存空间全部释放,弹栈。 局部变量在“方法体”中声明,局部变量运行阶段在栈中分配。
public class Method01{ 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 x,int y ){ int result=(x+y); int num = 3; int retValue = divde(result ,num ); return retValue ; } public static int divde(int x,int y ){ int z=x/y; return z; } }
对于功能类似的方法,我们进行构造时,每一个方法都定义方法名。增加了代码编写时的记忆负担,多个功能类似的方法调用时仅使用一个方法名,并准确的运行出结果,达到节省的目的。即调用方法时就感觉在使用一个方法一样,依据实参的数据类型不同,对于调用的方法不同。
//重载前 public class Overload{ public static void main (String[] args){ System.out.println(sumInt(1,2)); System.out.println(sumLong(1L,2L)); System.out.println(sumDouble(1.0,2.0)); } public static int sumInt(int x,int y){ return x+y; } public static long sumLong(long x,long y){ return x+y; } public static double sumDouble(double x,double y){ return x+y; } }
//重载后 public class Overload{ public static void main (String[] args){ System.out.println(sum(1,2)); System.out.println(sum(1L,2L)); System.out.println(sum(1.0,2.0)); } public static int sum(int x,int y){ return x+y; } public static long sum(long x,long y){ return x+y; } public static double sum(double x,double y){ return x+y; } }
递归:方法自身调用自身,相当于一直压栈,如果没有终止条件,程序会一直递归,直到栈溢出发生错误。
public class Recursion{ public static void main(String[] args){ //1-4求和 递归 int retValue = sum(4); System.out.println(retValue); } public static int sum(int n){ if(n==1){ return 1; } return n+sum(n-1); // n+(n-1)+(n-2)...... } }