方法

什么是方法,其实我们从一开始就接触到了方法。这个方法就是我们的主方法。主方法是一个比较特殊的方法,它是程序执行的入口。之前我们还提到可以使用.去调用方法,像System.out.println();中,println()就是一个方法。
所谓方法(函数),就是就是用来解决一类问题的代码的有序组合,是一个功能模块**。**

方法声明

语法:访问修饰符 返回类型 方法名(参数列表) { 方法体 }
示例:

  1. public static void main(String[] args) {
  2. System.out.println("Hello,World!");
  3. }

访问修饰符就是方法允许被访问的范围;返回类型可以是void和其他任何类型的数据(包括自己创造的数据类型);方法名需要满足标识符的全部规则外还需要满足驼峰原则;参数列表可以省略,既没有参数,同样参数可以有多个,每个参数之间使用逗号间隔,参数由数据类型和参数名构造,类似变量的定义;

根据参数和返回值,方法可以分为四类:

  1. 无参无返回值
  2. 无参有返回值
  3. 带参无返回值
  4. 带参有返回值。

    方法类型

    无参无返回值方法

    首先我们来看一道例题,打印如下所示的图形
    Java方法 - 图1
    这样的图形只需要使用System.out.println()就可以打印输出出来,但是我们发现该例题会要求我们进行重复的打印输出该图形。对于这样一种重复的行为,我们希望将这条打印语句放置在一个方法里面,然后每次遇到同样的要求,只需要调用方法就可以了。
    那么,方法的使用意义就出来了,我们希望使用方法来减少代码的量!就如同我们之前给大家讲过冒泡排序的问题,如果我们每次遇到要冒泡排序的问题,只需要调用一个方法,是不是就方便很多。

    1. public class One {
    2. // 打印输出星号的方法
    3. public void printStar() {
    4. System.out.println("********************************");
    5. }
    6. // 一行打印输出一串星号
    7. public static void main(String[] args) {
    8. //创建一个One类的对象MyOne
    9. One MyOne=new One();
    10. //使用对象名.方法名()去调用方法
    11. MyOne.printStar();
    12. System.out.println("欢迎来到Java的世界!");
    13. MyOne.printStar();
    14. }
    15. }

    在本章节中,我们会碰到很多的概念和语法,这些概念和语法需要我们同学反复记忆。其实关于这些概念和语法的问题没有为什么,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();
         System.out.println("长方形的面积为:"+rc.area());
     }
    }
    

什么是返回值,返回值其实是本方法求得的结果,这个结果最终可能为其他方法或代码块所需要,那么为了将该结果传递出去,就需要使用返回值将得出的结果传递出去。

带参无返回值方法

例题:
定义一个求两个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.1, 1.3);//实际参数(实参)
    }
}

局部变量的范围只限于定义它的大括号中,传递数值时主方法中可以是变量,也可以是一个字面值,不同类型传递会出现类型转换。

带参有返回值的方法

例题:
定义一个求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);
    }
}

方法的定义必须定义在类的里面,但是不能定义在另外一个方法的里面。方法不能嵌套,带有返回值的方法是为了参与进一步的运算

数组作为方法参数

示例一

例题:
定义方法,打印输出数组元素的值。

public class Five {
    //打印输出数组元素的值
    public void printArry(int[] arr) {
        for(int i=0;i<arr.length;i++) {
            System.out.print(arr[i]+" ");
        }
        System.out.println();
    }
    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);
        if(flag) {
            System.out.println("存在数据");
        } else {
            System.out.println("存在数据");
        }
    }
}

方法重载

方法重载简单概括就是方法名相同,参数列表不同
Java方法 - 图2
例题:

定义三个方法,实现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];
        }
        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与n的值并没有发生改变。
Java方法 - 图3

这是因为首先创建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+" ");
        }
    }
}

总结:

主方法中声明变量并传值到方法中,基本数据类型传值是把值传过去,没有传变量的地址,所以如果在普通方法中修改了变量的值,对主方法中的普通变量没有影响。但是如果主方法中声明的是数组(引用数据类型),则传值是把变量地址传过去了(传过去的是数组的第一个元素的地址),在普通方法中修改变量会影响主方法的变量。传值都是传的的变量里的值,基本数据类型的是值本身,引用类型的是对象的地址。但是数组可以修改对象里的东西,字符串不可以。

可变参数列表

什么是可变参数列表

示例:

public void sum(int...n) {
}

可变参数列表指的是参数的数量不固定,但是参数的类型是固定的,参数列表规定了是哪一种类型,随后的参数就只能是哪一种类型。

示例一:

public class Demo {

    //求和
    public void sum(int...n) {
        int sum = 0;
        for(int i: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类型
    }
}

示例二:

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);//可变参数列表可以和数组进行兼容,可以将数组传递给可变参数列表
    }
}

总结:

  1. 可变参数列表指的是参数数量是不确定的,可以随时变化。有时候也称可变原参数。
  2. 参数列表中如果有两个或两个以上的参数,可变参数一定是在最后的。例如:public void a(int a,int... b){ }是正确的,但是如果把int... b写前面则是错误的。
  3. 可以将数组传递给可变参数。
  4. 一个方法中只能有一个可变参数
  5. 可变参数方法换成数组是不算重载的,算重复定义

可变参数列表作为方法参数的重载问题

当进行方法重载时,可变参数列表方法,调用顺序的问题。

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(3,4,5));
    }
}

总结:
若有多个重载方法,则可变参数列表所在的方法是最后被访问的(如果主方法所传参数其他重载方法可以满足,则调用其他方法,只有其他方法都不满足,才会调用可变参数列表所在的方法)

再议文档注释

至此,对于方法的学习,我们已经完成的差不多了,接下来,我们再来看一看文档注释对于整个类使用的帮助
在 javadoc 中也提供了丰富的标记

  • @author:指定程序的作者
  • @version:指定源代码的版本
  • @param:在方法中指定参数
  • @return:在方法中指定返回值
/**
 * <h2>可变参数列表方法重载的应用</h2>
 * @author 作者
 * @version 版本号
 */
public class Demo {
    /**
     * <p style="color:red">求和</p>
     * @param a 参数
     * @param b
     * @return 返回值
     */
    public int sum(int a, int b) {
        System.out.println("不带可变参数列表的方法被调用");
        return a + b;
    }
}

在文档注释中可以使用html标签,但是不能用自封闭的标签。
使用javadoc命令生成API文档,-d指定生成的目录地址。

cmd中执行命令:

javadoc -encoding utf-8 -d apidoc -version -author Demo.java

在eclipse中执行生成doc文档

  1. 在工具栏project选项中右键选择Generate Javadoc选项
    Java方法 - 图4

  2. 可以选择生成整个项目的帮助文档和单独一个类的帮助文档,以及选择输出地址
    Java方法 - 图5

  3. 生成标题
    Java方法 - 图6

  4. 输出文档
    可以尝试学习Java jdk的帮助文档:https://tool.oschina.net/apidocs/apidoc?api=jdk-zh

    方法的调试

    在方法调用处打上断点。

    F5进入方法内部执行
    F6单步执行
    F7由方法内部跳回调用处
    

知识点:

  1. main主方法 程序入口
  2. 键盘获取 Scanner sc = new Scanner(System.in); Scanner是类 sc是类的对象
  3. Sc.nextInt(); 从键盘获取一个整型值的方法
  4. Sc.next(); 从键盘获取一个字符串类型的方法
  5. 在方法部分只使用对象名调用方法
  6. 输出语句println( ) 或 print( );
  7. 所谓的方法,就是用来解决一类问题的代码和有序组合,是一个功能模块
  8. 方法在类的内部定义,方法不能嵌套定义
  9. 局部变量在未赋值(初始化)的情况下不可以直接使用
  10. 数组必须先被初始化,才能被使用
  11. String类型保存的数据没有地址 所以用null来代替
  12. 未初始化和定义为null不一样
  13. 初始化称之为创建的原因:因为真正的变量是初始化时赋予的数据
  14. 数组排序可以使用冒泡排序等算法,还可以借助工具类,类定义出来可以被其他地方所引用(例如:Arrays.sort();)sort默认升序排序