方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,就是一个方法只完成一个功能,这样利于我们后期扩展
我们的main方法要时刻保持简洁干净,尽量把一些公共模块都提取到外面,通过方法调用的形式来使用这些方法。之后学习jvm就会更清楚,因为这涉及到一些底层的东西,main方法是占的最底层
方法的定义修饰符 返回值类型 方法名(参数类型 参数名) { 方法体 return 返回值; }
Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:
方法包含一个方法头和一个方法体。下面是一个方法的虽有部分:
-
修饰符:这是可选的,告诉编辑器如何调用该方法。定义了该方法的访问类型。
-
返回值类型:方法可能会返回值。returnValueType是方法返回值的数据类型。有些方法执行所需的 *** 作,但没有返回值。在这种情况下,returnValueType的关键字是void。
-
方法名:是方法的实际名称。方法名和参数表共同构成方法签名。
-
参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值被称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。
形式参数:在方法被调用时用于接收外界输入的数据。
//加法,需要接受两个值,即a与b,才能进行计算。这就是形式参数,可以理解为定义作用 public static int add(int a,int b) { return a+b; }
实参:调用方法时实际传给方法的数据。
//这里,就是在调用上面的add方法,把3跟5传递到形参中,3赋值给了a,5赋值给了b。这就是实际调用给他传递的参数 int sum = add(3, 5); System.out.println(sum);
-
方法体:方法体包含具体的语句,定义该方法的功能。
练习:做一个比大小的方法
public static void main(String[] args) { int M=compare(13,9); //调用比大小方法,把返回值存到M中 System.out.println(M); } //定义一个比大小的方法 public static int compare (int a,int b) { if (a>b) { return a; //如果直接在这里返回a,没有后续else语句的话,是会报错的,因为此时如果areturn一般是要在方法体的最外层的,上例中return是在if...else语句中,如果不注意可能会造成没有返回值的后果导致报错。可以这样写:
public static void main(String[] args) { int M=compare(13,9); System.out.println(M); } public static int compare (int a,int b) { int result=0; //定义一个新变量来保存返回值 if (a==b) { System.out.println("a=b"); return 0; //终止方法 //程序要严谨,每种情况都要考虑到 } if (a>b) { result = a; }else { result = b; } return result; //此时return就在最外层,把result作为返回值即可 }return除了返回结果,同时还有终止方法的作用
方法调用
-
调用方法:对象名.方法名(实参列表)
-
Java支持两种调用方法的方式,根据方法是否返回值来选择
-
当方法返回一个值的时候,方法调用通常被当做一个值,例如:
int larger = compare(30,40); //上一个述例子的
-
如果方法返回值是void,方法调用一定是一条语句。
System.out.println("Chao")
值传递是对基本类型变量而言的,传递的是该变量的一个副本,改变副本不影响原变量
引用传递一般是对于对象型变量而言的,传递的是该对象地址的一个副本, 并不是原对象本身 。
int num = 10; String str = "hello";
num是基本类型,值就直接保存在变量中。而str是引用类型,变量中保存的只是实际对象的地址。一般称这种变量为"引用",引用指向实际对象,实际对象中保存着内容。
对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。 对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变。
方法的重载(重点)-
重载就是在一个类中,有相同的函数名称,但形参不同的函数
-
重载规则
-
方法名称必须相同
-
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
-
方法的返回值类型可以相同也可以不同
-
仅仅返回类型不同不足以成为方法重载
-
public static int compare (int a,int b) public static double compare (double a,double b) public static int compare (int a,int b,int c)
以上这三个方法就是方法的重载
-
方法名称相同时,编译器会根据调用方法的参数个数、参乎类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错。
package com.Chao.Method; public class Demo03 { public static void main(String[] args) { // args.length 表示数组长度 for (int i = 0; i < args.length; i++) { System.out.println("args["+i+"]:"+args[i]); } } }
-
有时候你希望运行一个程序的时候再传递给他消息。这要靠传递命令行参数给main()函数实现。
我们可以使用DOS命令符,在java文件路径下打开命令符
例如,输入javac Demo03.java,来生成一个class文件,我们再输入java Demo03来执行这个文件,发现d出了错误:错误: 找不到或无法加载主类 Demo03,因为这个文件在一个包下,我们需要在包的路径下来执行:java com.Chao.Method.Demo03 此时,就运行成功,但是当前并没有输出,我们需要给他加上参数:
D:codebasesrc>java com.Chao.Method.Demo03 this is Chao args[0]:this args[1]:is args[2]:Chao
这就是传递参数给了args
之前学方法重载的时候注意到了,如果有太多的不确定性,方法重载会要写好多遍,非常麻烦。
public static int compare (int a,int b) {} public static double compare (double a,double b) {} public static int compare (int a,int b,int c) {}
..............可能还要更多
此时就用到了可变参数
-
JDK 1.5 开始,Java支持传递同类型的可变参数给一个方法
-
在方法生命中,在指定参数类型后加一个省略号(...)
-
一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。
public static void main(String[] args) { //这里采用new一个类,返回一个当前对象demo04,这个方法不需要static Demo04 demo04 = new Demo04(); demo04.text(3,3,5,2,4); } //传递a,但是不知道传递多少,用...就可以传递无限个 public void text(double b,int... a) { System.out.println(b); //int... a就是可变参数,它就是这个方法的最后一个参数,double就在它之前 System.out.print(a[0]+"t"); System.out.print(a[1]+"t"); System.out.print(a[2]+"t"); System.out.print(a[3]+"t"); //输出的本质还是数组,这个方法来定义输出,main中引用就是数组。这里来确定输出数组的第几个数 } 输出结果: 3.0 3 5 2 4
排序例子:
public static void main(String[] args) { printMax(1,2,3,4,5); //调用printMax方法 printMax(new double[]{5,2,7,4}); //传递一个数组,也可以实现 } //定义可变参数 public static void printMax(double...numbers) { if (numbers.length==0) { //判断数组长度是否为0 System.out.println("No argument passed"); return; //数组长度为0,结束方法 } //数组长度不为0,进行排序 double result = numbers[0]; //将数组的第一个值给result for (int i = 1; i < numbers.length; i++) { if (numbers[i] > result) { //把最大值赋值给result result = numbers[i]; } } System.out.println("The max value is "+result); } 输出结果: The max value is 5.0 The max value is 7.0
A方法调用B方法,我们很容易理解! 递归就是:A方法调用A方法,就是调用自己!
错误示范:
//这是一个没有递归头的例子,就是说这个方法是死循环,没有被定义什么时候不调用,就会不停地调用 public static void main(String[] args) { recursion text = new recursion(); text.test(); } public static void test() { test(); //调用自己 } 这样输出会直接报错,自己调用自己电脑内存根本不够,并不是这样使用的
-
利用递归可以用简单地程序来解决一些复杂的问题。它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要的多次重复计算,大大的减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。
-
递归结构包括两个部分
-
递归头:什么时候不调用自身方法。如果没有头,将陷入死循环。
-
递归体:什么时候需要调用自身方法。
-
来看一个递归的例子:
public static void main(String[] args) { System.out.println(f(5)); } //定义一个阶乘的方法 public static int f(int m) { if (m==1) { return 1; }else{ return m*f(m-1); //这里方法体就是调用自己 //例如:m是5,到这里会调用f(4),一只调用到最后m==1,此时f(1)会返回一个具体的结果1 } }
边界条件:此例中,f(1)j就是一个尽头,一个边界,程序执行到这里就停止了 前阶段:当参数不等于1,就不停地调用自身 返回阶段:从最大数开始,n*(n-1)
递归我们人用起来很方便,但是难为了计算机,Java是使用栈机制的,就像一个罐子,main方法在最底层,每调用一个方法就压一层,main方法执行完了栈就空了。但是,如果往栈里面压入过多的东西,它的空间就会不够,对于嵌套层次比较深的算法,递归就会显得力不从心,物理上就可能造成内存崩溃。就像上述阶乘的例子:参数为5就调用了好几个f()。
能不用递归就不用递归!递归都能用一些方法来代替的,如果真的要用递归,前提是基数比较小。也就是说计算量小可以用递归,计算量太大还是免了
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)