导学
什么是方法,其实我们从一开始就接触到了方法。这个方法就是我们的主方法。主方法是一个比较特殊的方法,它是程序执行的入口。之前我们还提到可以使用.
去调用方法,像System.out.println();
中,println()
就是一个方法。
所谓方法(函数),就是就是用来解决一类问题的代码的有序组合,是一个功能模块。
文档注释一般放在方法上,构造器上和 类上 , 表明这三者的作用
方法声明
语法:
访问修饰符 返回类型 方法名(参数列表) {
方法体
}
示例:
/**
*访问修饰符(public static)
public表示公共的,即该方法可以在Java程序的任意位置被访问。static表示静态的,表示谁都可以使用该方法
static-类和类的对象都可以使用该方法
*返回值类型(void)
void表示空,即该方法没有返回值
如果一个方法存在返回值,则方法定义上返回值类型就是返回值的类型(可以是任意类型,包括我们自己创建的数据类型)
*方法名(main)满足标识符的规则,还需要满足驼峰原则
*参数列表(String[] args)
*/
public static void main(String[] args) {
System.out.println("Hello,World!");
}
访问修饰符就是方法允许被访问的范围;返回类型可以是void和其他任何类型的数据(包括自己创造的数据类型);方法名需要满足标识符的全部规则外还需要满足驼峰原则;参数列表可以省略,既没有参数,同样参数可以有多个,每个参数之间使用逗号间隔,参数由数据类型和参数名构造,类似变量的定义;
根据参数和返回值,方法可以分为四类:
- 无参无返回值
- 无参有返回值
- 带参无返回值
带参有返回值。
本节课我们就根据这四个分类来给大家介绍方法的具体信息。方法类型
无参无返回值方法
首先我们来看一道例题,打印如下所示的图形
这样的图形只需要使用System.out.println()
就可以打印输出出来,但是我们发现该例题会要求我们进行重复的打印输出该图形。对于这样一种重复的行为,我们希望将这条打印语句放置在一个方法里面,然后每次遇到同样的要求,只需要调用方法就可以了。
那么,方法的使用意义就出来了,我们希望使用方法来减少代码的量!就如同我们之前给大家讲过冒泡排序的问题,如果我们每次遇到要冒泡排序的问题,只需要调用一个方法,是不是就方便很多。public class One {
// 打印输出星号的方法定义
// public static void printStar()
public void printStar() {
//在方法内部所写的内容称之为方法体
System.out.println("********************************");
}
// 一行打印输出一串星号
public static void main(String[] args) {
//对于使用static修饰的方法,可以直接被类(或者类的对象)调用
//One.printStar();
//对于没有使用static修饰的方法,我们需要使用类的对象来调用
//构建一个当前One类的对象MyOne
One MyOne = new One();
//使用当前类的对象名.方法名()去调用方法
MyOne.printStar();
System.out.println("欢迎来到Java的世界!");
MyOne.printStar();
}
}
在本章节中,我们会碰到很多的概念和语法,这些概念和语法需要我们同学反复记忆。其实关于这些概念和语法的问题没有为什么,Java的语法规则就是这么规定的,编译器就只认这些语法。
无参有返回值的方法
我们依旧通过一个例题完成:
求一个长宽都是整数的长方形面积?public class Rectangle {
public int area() {
int length=10;
int width=5;
int area=length*width;
return area;//返回语句,将方法得到的结果传递给方法外部
//变量名和方法名可以一致
//注意:方法返回值需要和规定的返回值一致。
// -- 最终的返回语句中的返回值类型必须要和方法定义上的返回值类型一致
}
public static void main(String[] args) {
Rectangle rc = new Rectangle();
int x = rc.area();
//只要方法返回值不是void,可以调用该方法时,设置变量承接该方法的返回值
System.out.println("长方形的面积为:" + x);
}
}
什么是返回值,返回值其实是本方法求得的结果,这个结果最终可能为其他方法或代码块所需要,那么为了将该结果传递出去,就需要使用返回值将得出的结果传递出去。
带参无返回值方法
例题:
定义一个求两个float类型的数据最大值的方法,在方法中将最大值打印输出public class MaxDemo {
public void max(float a, float b) {//形式参数(形参)
float max;
if(a > b) {
max = a;
} else {
max = b;
}
System.out.println("最大值为:" + max);
}
public static void main(String[] args) {
MaxDemo md = new MaxDemo();
md.max(1.1f, 1.3f);//实际参数(实参)
//Java中,当定义方法时规定参数的参数类型和参数个数时,必须在调用该方法时完全满足
//在调用该方法时,对于基本数据类型,方法的参数类型一般不会兼容(向上兼容)
}
}
局部变量的范围只限于定义它的大括号中,传递数值时主方法中可以是变量,也可以是一个字面值,不同类型传递会出现类型转换。
带参有返回值的方法
例题:
定义一个求n!的方法,然后再求1!+ 2!+3!+4!+5!
n!是指阶乘,5的阶乘就是1*2*3*4*5
public class Four {
//方法不能嵌套定义
//求阶乘的方法
public int fac(int n) {
int s=1;
for(int i=1;i<=n;i++) {
s*=i;//s=s*i;
}
return s;
}
public static void main(String[] args) {
Four four=new Four();
int fac=four.fac(3);
System.out.println("3!="+fac);
int sum=0;
//求1!+2!+3!+4!+5!
for(int i=1;i<=5;i++){
fac=four.fac(i);
sum+=fac;
}
System.out.println("1!+2!+3!+4!+5!="+sum);
}
}
方法的定义必须定义在类的里面,但是不能定义在另外一个方法的里面。
方法不能嵌套,带有返回值的方法是为了参与进一步的运算
可以在无static修饰的方法中直接调用另一个无static修饰的方法
可以在static修饰的方法中直接调用另一个static修饰的方法
**数组作为方法参数
示例一
例题:
定义方法,打印输出数组元素的值。public class Five {
//打印输出数组元素的值
public void printArry(int[] arr) {
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
}
public static void main(String[] args) {
int[] arr= {10,20,30,40,50,};
Five am=new Five();
am.printArry(arr);
}
}
示例二
例题:
查找数组元素的值:public class ArraySearch {
//方法参数:数组、要查找的元素
//返回值:Boolean类型
public boolean search(int n,int[] arr) {
boolean flag = false;
for (int i = 0; i < arr.length; i++) {
if(arr[i]==n) {
flag=true;
}
}
return flag;
}
public static void main(String[] args) {
int[] a= {10,20,30,40,50,60};
int b = 30;
ArraySearch as = new ArraySearch();
boolean flag = as.search(b, a);//flag=true
if(flag) {
System.out.println("存在数据");
} else {
System.out.println("不存在数据");
}
}
}
方法重载
参数列表
参数列表和参数个数、参数类型、参数排序有关,跟参数名无关。
方法重载简单概括就是方法名相同,参数列表不同。
方法之间存在重载关系,即方法名相同,方法参数列表不同
如果方法名相同,参数列表也相同 属于方法的重复定义,会产生编译时错误
通过重载可以定义很多相似的方法,这些方法公用一个方法名,根据参数的不同决定调用哪个方法
(第一行和第二行不属于重载,属于重复定义)
(第一行和最后一行,既不属于重载,也不属于重复定义)
例题:
定义三个方法,实现int、double和数组类型求和的问题
public class MathDemo {
//求两个int类型数的和
public int plus(int m,int n){
return m+n;
}
//求两个double类型数的和
public double plus(double m,double n){
return m+n;
}
//求数组元素的累加和
public int plus(int[] arr){
int sum=0;
//for(int i=0;i<arr.length;i++){
//sum=sum+arr[i];
//}
for (int i : arr) {
sum += i;
}
return sum;
}
public static void main(String[] args) {
int m=5,n=10;
int[] arr={1,2,3,4,5,6};
MathDemo mathDemo=new MathDemo();
System.out.println("int类型的和:"+mathDemo.plus(m,n));
System.out.println("double类型的和:"+mathDemo.plus(5.6,7.8));
System.out.println("数组元素的和:"+mathDemo.plus(arr));
}
}
方法的传值
基本数据类型的传值
例题:
对两个变量的值进行交换并打印输出(传值问题)
public class ExchangeDemo {
//交换方法
public void swap(int a,int b){
int temp;
System.out.println("交换前:a="+a+","+"b="+b);
temp=a;
a=b;
b=temp;
System.out.println("交换后:a="+a+","+"b="+b);
}
public void swapTest(){
//ExchangeDemo ex=new ExchangeDemo();
//普通方法调用方法不需要定义对象,直接调用即可 方法名(实参);
int m=4,n=5;
System.out.println("交换前:m="+m+","+"n="+n);
swap(m,n);
System.out.println("交换后:m="+m+","+"n="+n);
}
public static void main(String[] args) {
ExchangeDemo ex=new ExchangeDemo();
ex.swapTest();
/*int m=4,n=5;
System.out.println("交换前:m="+m+","+"n="+n);
ex.swap(m,n);
System.out.println("交换后:m="+m+","+"n="+n);*/
}
}
输出: 交换前:m=4,n=5
交换前:a=4,b=5
交换后:a=5,b=4
交换后:m=4,n=5
在方法运行之后,我们会发现,m与n的值并没有发生改变。
这是因为首先创建m,n变量,会在内存中开辟空间存储对应的值,然后在方法调用的时候把m和n的值(复制)传给变量a,b,这时候只是把4和5这两个值传过去了。并不是把m和n的内存地址传递过去了。
实际上,这道题目告诉我们,如果方法的参数是基本数据类型,那么在方法内对参数进行修改,不会影响到传递的实际参数。
对于基本数据类型,不会改变方法外的数据值。
数组的传值
例题:
定义一个用于修改某个数组元素的方法
public class Ten {
//定义一个用于修改某个数组元素值的方法
public void updateArry(int[] a) {
a[3]=15;
System.out.println("数组a的元素为:");
for(int n:a) {
System.out.print(n+" ");
}
System.out.println();
}
public static void main(String[] args) {
Ten b=new Ten();
int[] a1= {1,2,3,4,5};
System.out.println("方法调用前数组a1元素为:");
for(int n:a1) {
System.out.print(n+" ");
}
System.out.println();
b.updateArry(a1);
System.out.println("方法调用后数组a1元素为:");
for(int n:a1) {
System.out.print(n+" ");
}
}
}
输出 :方法调用前数组a1元素为:
1 2 3 4 5
数组a的元素为:
1 2 3 15 5
方法调用后数组a1元素为:
1 2 3 15 5
在方法运行之后,我们会发现,数组a1的值发生了改变。
总结:
当方法的参数为引用数据类型时,在方法中对参数进行修改,会影响到方法外的参数。
主方法中声明变量并传值到方法中,基本数据类型传值是把值传过去,没有传变量的地址,所以如果在普通方法中修改了变量的值,对主方法中的普通变量没有影响。但是如果主方法中声明的是数组(引用数据类型),则传值是把变量地址传过去了(传过去的是数组的第一个元素的地址),在普通方法中修改变量会影响主方法的变量。传值都是传的的变量里的值,基本数据类型的是值本身,引用类型的是对象的地址。但是数组可以修改对象里的东西,字符串不可以。
可变参数列表
什么是可变参数列表
示例:
public void sum(int...n) {
}
可变参数列表指的是参数的数量不固定,但是参数的类型是固定的,参数列表规定了是哪一种类型,随后的参数就只能是哪一种类型。
示例一:
public class Demo {
//求和
public void sum(int...n) {
int sum = 0;
for(int i:n) {//其实我们可以将可变参数列表看作为一个数组int[] n
sum = sum + i;
}
System.out.println("sum="+sum);
}
public static void main(String[] args) {
Demo de = new Demo();
de.sum(1);
de.sum(1,2);
de.sum(1,2,3);
//de.sum(1,1.2);传入的必须是int类型
de.sum(new int[]{1,2,3});//可以使用数组代替可变参数列表
}
}
sum=1
sum=3
sum=6
示例二:
public class ArgsDemo1 {
//查找
public void search(int n,int...a){//参数列表中如果有两个或两个以上的参数,可变参数一定是在最后的。
boolean flag=false;
for(int a1:a){
if(a1==n){
flag=true;
break;
}
}
if(flag){
System.out.println("找到了"+n);
} else{
System.out.println("没找到"+n);
}
}
/*public void search(int n, int[] a) {
//可变参数方法换成数组是不算重载的,算重复定义
}*/
/*public void search(int n, int... a, int...b) {
//一个方法中只能有一个可变参数。
}*/
public static void main(String[] args) {
ArgsDemo1 ad1=new ArgsDemo1();
//可变参数两种传入实参的方法
ad1.search(3,1,2,3,4,5);
int[] a={1,2,3,4,5};
ad1.search(3,a);//可变参数列表可以和数组进行兼容,可以将数组传递给可变参数列表
}
}
找到了3
找到了3
总结:
- 可变参数列表指的是参数数量是不确定的,可以随时变化。有时候也称可变原参数。
- 参数列表中如果有两个或两个以上的参数,可变参数一定是在最后的。例如:
public void a(int a,int... b){ }
是正确的,但是如果把int... b
写前面则是错误的。 - 可以将数组传递给可变参数。(数组作为参数,不能传入可变原参数)
- 一个方法中只能有一个可变参数。
-
可变参数列表作为方法参数的重载问题
本节课,我们来看一下当进行方法重载时,可变参数列表方法,调用顺序的问题。 ```java public class Demo { public int sum(int a, int b) {
System.out.println("不带可变参数列表的方法被调用");
return a + b;
}
//求和 public int sum(int…n) {
int sum = 0;
for(int i:n) {//其实我们可以将可变参数列表看作为一个数组
sum = sum + i;
}
System.out.println("带可变参数列表的方法被调用");
return sum;
}
public static void main(String[] args) {
Demo de = new Demo();
System.out.println("和为:" + de.sum(1,2));
System.out.println("和为:" + de.sum(3,4));
System.out.println("和为:" + de.sum(new int[]{3,4});
System.out.println("和为:" + de.sum(3,4,5));
} }
不带可变参数列表的方法被调用
和为:3
不带可变参数列表的方法被调用
和为:7
带可变参数列表的方法被调用
和为:7
带可变参数列表的方法被调用
和为:12
总结:<br />若有多个重载方法,则可变参数列表所在的方法是最后被访问的(如果主方法所传参数其他重载方法可以满足,则调用其他方法,只有其他方法都不满足,才会调用可变参数列表所在的方法)
<a name="vLNS3"></a>
## 再议文档注释
至此,对于方法的学习,我们已经完成的差不多了,接下来,我们再来看一看文档注释对于整个类使用的帮助<br />在 javadoc 中也提供了丰富的标记
- @author:指定程序的作者
- @version:指定源代码的版本
- @param:在方法中指定参数
- @return:在方法中指定返回值
/**
可变参数列表方法重载的应用
- @author 作者
- @version 版本号
/
public class Demo {
/*
求和
- @param a 参数
- @param b
- @return 返回值
*/
public int sum(int a, int b) {
System.out.println(“不带可变参数列表的方法被调用”);
return a + b;
}
}
cmd中执行命令: javadoc -encoding utf-8 -d apidoc -version -author Demo.java ``` 在eclipse中执行生成doc文档在文档注释中可以使用html标签,但是不能用自封闭的标签。<br />使用javadoc命令生成**API文档**,-d指定生成的目录地址。
- 在工具栏project选项中右键选择Generate Javadoc选项
- 可以选择生成整个项目的帮助文档和单独一个类的帮助文档,以及选择输出地址
- 生成标题
- 输出文档
各位同学可以尝试学习Java jdk的帮助文档:https://tool.oschina.net/apidocs/apidoc?api=jdk-zh方法的调试
在方法调用处打上断点。F5进入方法内部执行
F6单步执行
F7由方法内部跳回调用处