本篇笔记主要是方法传递机制、可变参数方法、递归方法、方法重载
1.在Java语言里,方法不能独立存在,必须属于类或对象。一旦将一个方法定义在某个类中,如果这个方法有static修饰,则这个方法属于这个类,否则这个方法属于这个类的实例。
2.在同一个类中,一个方法调用另外一个方法,如果被调用的是普通方法,则默认使用this作为调用者。如果被调用的方法是静态方法,则默认使用类作为调用者。
3.方法的传递机制
在方法调用时,如果声明的时包含了形参,那么调用方法是必须给这些形参指定参数值。
在Java里方法的参数传递方式只能是值传递。即,就是将实际参数值得副本传入方法内,参数本身不会受到任何影响。
eg:
package cn.it.lsl; public class SwapDemo { public static void main(String[] args){ int a = 5; int b = 7; swap(a,b); System.out.println("交换后,a的值为:"+a+",b的值:"+b); } private static void swap(int a, int b) { int temp = a; a = b; b = temp; System.out.println("swap里面,a的值为:"+a+",b的值:"+b); } }
输出:
swap里面,a的值为:7,b的值:5
交换后,a的值为:5,b的值:7
交换结束后,变量a,b的值不变,所以swap方法的a和b只是main方法里变量a和b的复制品。
eg:
package cn.it.lsl; class DateWrap{ public int a; public int b; } public class SwapTest { public static void main(String[] args){ DateWrap dw = new DateWrap(); dw.a = 6; dw.b = 8; swap(dw); System.out.println("交换后,a的值为:"+dw.a+",b的值:"+dw.b); } private static void swap(DateWrap dw) { int temp = dw.a; dw.a = dw.b; dw.b = temp; System.out.println("swap里面,a的值为:"+dw.a+",b的值:"+dw.b); } }
输出:
swap里面,a的值为:8,b的值:6
交换后,a的值为:8,b的值:6
Java引用类型的参数传递也是,也是值传递的方式
在main()方法调用swap()方法时,mian()方法并未结束,系统会分别开辟出mian和swap两个栈区。
mian()方法中的dw是一个引用(也就是一个指针),它保存的DataWrap对象的地址,当把dw的值赋值给swap方法的dw形参后,即让swap方法的dw形参也保存这个地址值,
即也会引用到堆内存中的DataWrap对象。
这种参数传递也是一种值传递方式,关键是dw是一个引用变量,所以系统复制了dw的变量,并未复制DataWrap对象。故还是操作堆内存中DataWrap对象。
4.可变参数的方法
可以为方法定义形参个数可变的参数,从而允许为方法指定数量不确定的形参。
在最后一个形参的类型后增加三点(...),则表明该形参可以接受多个参数值,多个参数值被当成数组传入。
eg:
package cn.it.lsl; public class Varargs { public static void main(String[] args) { test(3,"JavaSe","JavaEE"); } private static void test(int i, String...books) { for(String book : books){ System.out.println(book); } System.out.println(i); } }
个数可变的参数只能处于参数列表的最后。也就是说,一个方法中最多只能有一个长度可变的形参。
5.递归方法
一个方法体调用它自身,被称为方法递归。
例如有一道数学题
已知f(0)=1,f(1)=4,f(n+2)=2*f(n+1)+f(n),求f(10)
package cn.it.lsl; public class Recursive { public static int fn(int n){ if(n==0){ return 1; }else if(n==1){ return 4; }else{ return 2*fn(n-1)+fn(n-2); } } public static void main(String[] args) { System.out.println(fn(10)); } }
在递归调用的时候,必须在某个时刻方法的返回值是确定的,即不再调用它本身。递归一定要向已知方向递归。
上面的数学题,如果改成已知f(20)=1,f(21)=4,f(n+2)=2*f(n+1)+f(n),求f(10)
package cn.it.lsl; public class Recursive { public static int fn(int n){ if(n==20){ return 1; }else if(n==21){ return 4; }else{ return fn(n+2)-2*fn(n+1); } } public static void main(String[] args) { System.out.println(fn(10)); } }
对于求fn(10),如果fn(0)和fn(1)是已知的,应该采用f(n)=2*f(n-1)+f(n-2)的形式,因为小的一端已知。如果fn(20)和fn(21)是已知的,应该采用f(n)=fn(n+2)-2*fn(n+1);的形式,因为大的一端已知。
6.方法重载
在一个类中,两个或两个以上的方法名相同,但形参列表,则就被称为方法重载。(同一个类中方法名相同,参数列表不同,方法的其他部分,与方法重载没有任何关系)
package cn.it.lsl; public class Overload { // public void test(){ // System.out.println("没有参数"); // } public void test(String name){ System.out.println("一个参数:"+name); } //因为前面定义了有一个字符串参数的方法,所以此处长度可变形参里不包含一个字符串参数的形式 public void test(String...books){ System.out.println("可变参数"); } public static void main(String[] args) { // TODO Auto-generated method stub Overload ol = new Overload(); ol.test(); //下面这个调用的是public void test(String name) ol.test("张三"); ol.test("aa","bb"); } }