首先弄懂2个概念:形参和实参。 形参(形式参数):相当于函数(Java中也把函数称之为方法)中的局部变量,在函数被调用时创建,并以传入的实参作为起始值,函数调用结束时被释放。不会影响主程序中其他的变量(即使有变量跟他们同名),因为他们是不同作用域的变量,互不干扰。实参:调用函数时,实际传给函数形式参数的数据。
不管是基本类型的参数传递,还是引用类型的参数传递,统统采用的是值传递方式。有点区别的是引用类型的参数传递,实际上传递的是一个引用。记住下面一句话,就可以很好的理解值传递的实质:当系统开始执行方法时,系统为形参执行初始化,就是把实参变量的值赋值给方法的形参变量,方法里面操作的并不是实际的实参变量。
//java值传递测试 public class Test01 { //定义一个方法,里面交换2个变量的值 public static void test(int a,int b){ int temp = a; a = b; b = temp; System.out.println("a="+a+";b="+b); } public static void main(String[] args) { int a = 1; int b = 2; test(a, b); //这里的a还是实际存在的a,这里的b还是实际存在的b,所以值没有发生变化。 System.out.println("a="+a+";b="+b); } }
public class Test03 { public static void test(Test02 test02){ int temp = test02.a; test02.a = test02.b; test02.b = temp; System.out.println("a="+test02.a+";b="+test02.b); //这里来验证下是值传递还是引用传递:要是值传递的话,原来的引用还可以操作对象,要是传递的参数的话,原来的引用就不能操作对象了 test02 = null; } public static void main(String[] args) { Test02 test02 = new Test02(); test02.a = 1; test02.b = 2; test(test02); //test02 = null; 这里要是将引用赋值为null的话,就不能在操作对象了 //2个引用同时操作对象,实际在堆内存中的对象当然发生改变了 System.out.println("a="+test02.a+";b="+test02.b); } } class Test02 { public int a; public int b; }
,
这里情形经常遇到的,如果我们在使用hibernate的时候,给hql或者sql赋值的时候,要是有不确定的参数,就可以这样子写。
下面2个方法签名的效果完全一样:
public Static void test(int a,String... books);//以可变参数来定义方法
public Static void test(int a,String[] books);//以数组形参来定义方法
关于上面这2者的区别是:1,可变形参这种比较简洁。如果采用数组形参的方式,调用时必须传入数组。
2,数组形式的形参可以处于形参列表的任意位置,但是个数可变的形参只能处于形参列表的最后。
3,一个方法最多只能包含一个长度可变的形参,调用这个方法时,既可以传入多个参数,也可以传入一个数组
//形参个数可变的方法 public class Test04 { public void test(int a,String... names){ for (String name : names) { System.out.println(name); } } /** * @desc ^形参个数可变的参数其实就是一个数组参数 * @param a * @param names */ public void test1(int a,String[] names){ for (String name : names) { System.out.println(name); } } public static void main(String[] args) { Test04 test04 = new Test04(); test04.test(1, "赵云"); test04.test(0, "张飞","关羽","典韦"); // test04.test1(0, new String[]{"张飞","大乔"}); //和上面的test1test02有点区别的是 ...这种方式可以直接传入多个参数,也可以传入一个数组参数 test04.test(0, new String[]{"张飞","大乔"}); } }
递归很有用滴,举个例子:我们希望遍历某个路径下的所有文件。为了更好的记住递归的规定,下面是2个数学题:
1,已知有一个数列:f(0)=1,f(1)=2,f(n+2)=2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值;
2,已知有一个数列:f(20)=1,f(21)=2,f(n+2)=2*f(n+1)+f(n),其中n是大于0的整数,求f(10)的值;
/** *只要一个方法的方法体内再次调用了方法本身,这就是一个递归方法 * @version 1L * @author LinkinPark * @since 2014-10-22 * @motto 梦似烟花心似水,同学少年不言情 * @desc ^ */ public class Test05 { public static int test(int n) { if (n == 0) { return 1; } else if (n == 1) { return 2; } else { return 2 * test(n - 1) + test(n - 2); } } public static int test1(int n) { if (n == 20) { return 1; } else if (n == 21) { return 2; } else { //不可以和上面写成一样,递归一定要向已知的方法递归 return test(n + 2) - 2 * test(n + 1); } } public static void main(String[] args) { //循环的次数一样,初始值一样,所以最终2次输出结果相同 System.out.println(test(10)); System.out.println(test1(10)); } }
//方法的重载 public class Test06 { public void test(){ } public void test(String msg){ System.out.println(msg); } }
5,关于main方法说明的一点:启动java程序的main方法的参数是一个字符串数组,通过反射来调用这个方法时,如何为invoke方法传递参数呢?因为JDK1.5要兼容JDK1.4,所以当我把一个字符串数组作为参数传递给invoke方法时,它会把数组打散成若干个单独的参数。所以:
在给main方法传递参数时,不能使用代码:mainMethod.invoke(null,new String[]{"1","2"});javac只会把它当做JDK1.4的语法进行理解,不会把他当成1.5的,因此出现参数类型不对的报错。解决办法:
mainMethod.invoke(null,object[]{new String[]{"1","2"}});或者mainMethod.invoke(null,(object)new String[]{"1","2"})