2.3 方法



一、概述

1.1 以前的方法:主方法

主方法是一种特殊的方法,是程序执行的入口。

class HelloImoc{
    public static void main(String[] args){
        System.out.pringln("Hello,imooc!");
    }
}

1.2 以前的方法:从键盘输入数据的方法

Scanner sc=new Scanner(System.in);
sc.nextInt();                // nextInt()是从键盘获取整型数据的方法
sc.next();                    // next()是从键盘获取字符串数据的方法

在方法部分,只介绍使用对象名来调用方法。后续学习面向对象时,对于静态方法其实是使用类名来调用的。

1.3 以前的方法:输出打印的方法

System.out.println();            // println():输出打印的方法

1.4 定义

由上可知,方法,就是用来解决一类问题的代码有序组合,是一个功能模块。

由于上述的三个方法,代表的是JDK提供的系统定义的方法,可以直接拿来使用。但是,此类方法并不能满足所有日常开发需求,因此,应该自定义方法。

二、方法的声明和调用

2.1 方法声明的语法格式和分类

1.以主方法为例:

(1)访问修饰符:

方法允许被访问的权限范围。有几种:

  • public
  • protected
  • private
  • 什么都不写

(2)返回类型:

可以是void以及任何的数据类型。

(3)方法名:

跟变量名命名规则一样。

(3)参数列表:

可以省略无参,即小括号里面可以为空。

参数列表是由参数类型、参数名组成。like变量的定义

2.方法的调用

Demo d=new Demo();
d.show();                // 通过对象名.函数名()来调用

以上的调用仅限主方法中,同类下的其他方法调用,只需要函数名()即可,不需要对象。

3.方法的分类、使用场景

根据方法是否带参数、是否有返回值,可以分为以下四类:

  • 无参、无返回值的方法
  • 无参、有返回值的方法
  • 带参、无返回值的方法
  • 带参、有返回值的方法

无参的使用场景:方法操作固定,没有变化。比如:

  • 输出一串星号
  • 后面面向对象中,输出成员变量的方法,因为成员变量在类中已经定义好了

除此之外,就需要使用参数。

4.方法的作用

减少代码量.比如:

  • 以前的冒泡排序写法如下:
int[] a= {34,53,12,32,56,17};
int temp;
for(int i=0;i<a.length;i++) {                    
    for(int j=0;j<a.length-1-i;j++) {            
        if(a[j]>a[j+1]) {                        
            temp=a[j];
            a[j]=a[j+1];
            a[j+1]=temp;
        }
    }
}

上述只是一个数组a,如果还有数组b、数组c等100个数组呢,上面13行的业务逻辑你要写100次吗?

单独写到一个方法中,用方法调用:

public void sort(){                            // 新定义一个方法
    int temp;
    for(int i=0;i<a.length;i++) {                    
        for(int j=0;j<a.length-1-i;j++) {            
            if(a[j]>a[j+1]) {                        
                temp=a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
            }
        }
    }   
}

SortDemo ad=new SortDemo();
int[] a= {34,53,12,32,56,17};
int[] b= {85,73,25,56,34,48};
ad.sort(a);                                // 对数组a进行排序
ad.sort(b);                                // 对方法进行调用

2.2 无参、无返回值的方法

例题:一行打印输出一串星号?

方法定义的形式:

public void printStar() {}

业务代码如下:

package com.imooc.method;

public class MethodDemo {
    // 新的打印输出星号的方法
    public void printStar() {      // 方法的定义,是在类MethodDemo的内部        // 无参,且void表示无返回值
        System.out.println("***************************");
        }
    
    // 主方法,习惯放最后
    public static void main(String[] args) {
        MethodDemo myMethodDemo=new MethodDemo();     // 创建一个类MethodDemo的对象myMethodDemo     
        myMethodDemo.printStar();                       // 使用对象名.方法名()去调用方法                
        System.out.println("欢迎来到java的世界!");
        myMethodDemo.printStar();
    }
}

--->
***************************
欢迎来到java的世界!
***************************

2.3 无参、有返回值的方法

之前的方法:Scanner类下的next()方法,返回值是String类型,就是无参、有返回值的方法。

Scanner sc=new Scanner();
sc.next();                        // 该方法返回值是String类型
sc.nextInt();                    // 该方法有返回值,是int类型

例题:求长方形的面积?

定义的形式:

public int area(){}              // 有返回值,且是整型int。根据需求可以变为double类型等

业务代码如下:

package com.imooc.method;

public class Rectangle {
    public int area() {                                    // 无参
        int length=10;
        int width=5;
        int getArea=length*width;
        return getArea;                                    // 有返回语句
    }
    

    public static void main(String[] args) {
        Rectangle rc=new Rectangle();
        System.out.println("长方形的面积为:"+rc.area());
    }
}

--->
长方形的面积为:50

2.4 有参、无返回值的方法

例题:定义一个方法,求两个float类型数据的最大值,并在方法中打印输出?

定义的形式:

public void max(float a,float b){}

业务代码如下:

package com.imooc.method;

public class MaxDemo {
    // 求最大值的方法
    public void max(float a,float b) {                // 有参     // void表示无返回值
        float max;
        if(a>b) {
            max=a;
        }else {
            max=b;
        }
        System.out.println("两个数"+a+"和"+b+"的最大值为:"+max);
    }
    
    
    public static void main(String[] args) {
        MaxDemo maxDemo=new MaxDemo();
        
        int a=5,b=3;                            // 因为int可自动转换为float    
        maxDemo.max(a, b);
        
        float m=5.6f,n=8.9f;                    // 调用时,定义变量     // 这里不一定非得是a、b,上面只是个形式参数
        maxDemo.max(m, n);
        
        maxDemo.max(9.8f, 12.8f);                // 调用时,也可不定义变量,直接传字面值
    }
}

--->
两个数5.0和3.0的最大值为:5.0
两个数5.6和8.9的最大值为:8.9
两个数9.8和12.8的最大值为:12.8

2.5 有参、有返回值的方法

例题:定义一个方法,求n!,然后再求1!+2!+3!+4!+5!?

以前使用的双重循环求阶乘。

定义的形式:

public int fac(int n){}

业务代码如下:

package com.imooc.method;

public class FacDemo {
    
    public int fac(int n) {                        // 有参数
        int s=1;
        for(int i=1;i<=n;i++) {
            s=s*i;
        }
        return s;                                // 有返回值        // 目的是为了下一步的运算
    }

    public static void main(String[] args) {
        FacDemo facDemo=new FacDemo();
        int fac=facDemo.fac(3);                    
        System.out.println("3!="+fac);             // 检验下求阶乘的方法是否生效
        // 求1!+2!+3!+4!+5!
        int sum=0;
        for(int i=1;i<=5;i++) {
            fac=facDemo.fac(i);
            sum=sum+fac;
        }
        System.out.println("1!+2!+3!+4!+5!="+sum);
    }
}

--->
3!=6
1!+2!+3!+4!+5!=153

方法不能定义在方法内,即不能嵌套定义。

2.6 练习题的教训:

错误演示;

public class DisCountDemo {
    //根据商品总价输出折后总价
    public void discount(float price){            // 有参        // void:无返回值
        float dscPrice;
        if(price<100){
            dscPrice=price;
        }
        else if(price>=100&price<=199){
            dscPrice=price*0.95;
        }
        else{
            dscPrice=price*0.85;
        }
        System.out.println("折后商品的总价为:"+dscPrice);
    }
    

    public static void main(String[] args) {
        DisCountDemo myDisCount=new DisCountDemo();            // 定义对象
        float price=150;                                    // 定义商品总价,存放到变量中
        myDisCount.discount(price);                            //调用方法,输出折后商品总价
    }
    
}

--->                        // 因为0.85在默认情况下,是double类型,转float类型会精度丢失
DisCountDemo.java:9: error: incompatible types: possible lossy conversion from double to float
            dscPrice=price*0.95;
                          ^
DisCountDemo.java:12: error: incompatible types: possible lossy conversion from double to float
            dscPrice=price*0.85;
                          ^
2 errors

改为:

将上述的float类型,全部换为double.

public class DisCountDemo {
    //根据商品总价输出折后总价
    public void discount(double price){                    // 有参,无返回值
        double dscPrice;
        if(price<100){
            dscPrice=price;
        }
        else if(price>=100&price<=199){
            dscPrice=price*0.95;
        }
        else{
            dscPrice=price*0.85;
        }
        System.out.println("折后商品的总价为:"+dscPrice);
    }
    

    public static void main(String[] args) {
        
        DisCountDemo myDisCount=new DisCountDemo();            // 定义对象
        double price=150;                                    // 定义商品总价,存放到变量中
        myDisCount.discount(price);                            //调用方法,输出折后商品总价
    }
}

--->
折后商品的总价为:142.5

三、数组作为方法参数

3.1 例题1:输出数组元素

定义一个方法,打印输出数组元素的值?

定义的形式:

public void printArray(int[] arr){}        

业务代码如下:

package com.imooc.method;

public class ArrayMethod {
    public void printArray(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};
        ArrayMethod am=new ArrayMethod();
        am.printArray(arr);
    }
    
}

--->
10  20  30  40  50  

2.习题:

3.2 例题2:查找数组元素

定义一个方法,查找数组元素的值?

定义的形式:

  • 方法的参数:数组、要查找的元素
  • 方法的返回值:boolean类型
public Boolean search(int n,int[] arr){}    

业务代码如下:

package com.imooc.method;

import java.util.Scanner;

public class ArraySearch {
    public boolean seach(int n,int[] arr) {            // 有参数
        boolean flag=false;                            // 默认是flase,即没找到
        for(int i=0;i<arr.length;i++) {
            if(arr[i]==n) {
                flag=true;                            // 表示找到了
                break;                    // 如果找到了,就立马跳出本循环,不执行后续循环
            }
        }
        return flag;                                // 有返回值
    }

    public static void main(String[] args) {
        int[] arr1= {10,20,30,40,50,60};
        System.out.println("请输入要查找的数据:");
        
        Scanner sc=new Scanner(System.in);
        int n1=sc.nextInt();
        
        ArraySearch as=new ArraySearch();
        boolean flag1=as.seach(n1, arr1);
        if(flag1) {
            System.out.println("找到了!");
        }else {
            System.out.println("没找到!");
        }
    }

}

--->
请输入要查找的数据:
30
找到了!
 
请输入要查找的数据:
32
没找到!

四、方法的重载

3.1 概念

1.方法重载:就是方法名相同,但是参数不同。

参数不同指的是参数的数据类型不同,也可以指参数数量不同。

以下三个方法是重载方法:

public void dispaly(){};
public void dispaly(){int n};
public void dispaly(){float n};

以下两个方法不是重载方法:因为参数的数量、参数的数据类型都相同。

public void dispaly(){int n};
public void dispaly(){int d};            // 只是参数名不同,没用

2.应用场景:

因为实现某一相同功能,针对不同的参数,如int、long,float、double等,针对多个方法只起一个方法名即可。

平时常用的println()其实就是多个重载的方法,用于输出不同类型的数据。

3.2 案例应用

例题:定义三个方法,实现int、double和数组类型和?

package com.imooc.method;

public class MathDemo {
    // 求两个int类型数的和
    public int plus(int m,int n) {                    // 方法名叫plus
        return m+n;
    }
    // 求两个double类型数的和
    public double plus(double m,double n) {            // 方法名叫plus
        return m+n;
    }
    // 求数组元素的累加和
    public int plus(int[] arr) {                    // 方法名叫plus
        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));
    }

}

--->
int类型的和:15
double类型的和:13.399999999999999
数组元素的和:21

四、方法传值

4.1 基本数据类型的传值

例题1:

对两个变量的值进行交换,并打印输出?

package com.imooc.method;

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 static void main(String[] args) {
        int m=4,n=5;
        ExchangeDemo ed=new ExchangeDemo();
        System.out.println("交换前:m="+m+",n="+n);
        ed.swap(m,n);                                    // 这里的m,n只是传值进入了上述的swap子方法
        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前后没有变化

真实的项目中,主方法的简化如下:

package com.imooc.method;

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() {                 // 再定义一个新方法,在方法体中调用上述方法
        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 ed=new ExchangeDemo();
        ed.swapTest();                        // 在主方法中调用,代码简洁
    }

}

--->
交换前:m=4,n=5
交换前:a=4,b=5
交换后:a=5,b=4
交换后:m=4,n=5                                // 跟上面的结果是一样的

例题2:

在主方法中调用了子方法,那么子方法影响主方法中变量的值吗?

package com.imooc.method;

public class ExchangeDemo2 {
    public void add(int n) {
        n++;
        System.out.println("方法中n="+n);
    }
    
    public static void main(String[] args) {
        int n=10;
        System.out.println("方法调用前n的值:"+n);
        
        ExchangeDemo2 ed=new ExchangeDemo2();
        ed.add(n);
        System.out.println("方法调用后n的值:"+n);
    }

}

--->
方法调用前n的值:10
方法中n=11
方法调用后n的值:10                        // 子方法调用,对主方法中的变量值没有影响

4.2 数组的传值

上面是基本数据类型的参数传值,接下来是数组作为方法参数的传值:

package com.imooc.method;

public class ArrayDemo {
    
    // 定义一个方法,用于修改某个数组元素值
    public void updateArray(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) {
        ArrayDemo ad=new ArrayDemo();
        int[] a1= {1,2,3,4,5};
        System.out.println("方法调用前数组a1的元素为:");
        for(int n:a1) {
            System.out.print(n+"  ");
        }
        System.out.println();
        
        ad.updateArray(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                      // 子方法调用,影响到了主方法中的数组元素

之所以是这样,是因为数组是引用数据类型,面向对象中的对象同理。

数组名a,指向了内存空间中数组的第一个元素a[0]。

上述不同,为何这样设计?

五、可变参数列表

5.1 概念

可变参数,是一种特别的参数:即参数的数量不确定、可以随时变化。或者叫可变原参数、可变参数类型。

形式:

public void sum(int... n) {};                // 视为有0~n个整型变量

5.2 案例应用

例题1:

定义一个方法,方法中的参数是可变参数列表形式?

package com.imooc.method;

public class Argsdemo {
    // 求和
    public void sum(int... n) {
        int sum=0;
        for(int i:n) {                // 用增强型for循环,取出可变参数列表中的每一个参数        // like数组
            sum=sum+i;            
        }
        System.out.println("sum="+sum);
        
    }
    
    
    public static void main(String[] args) {
        Argsdemo ad=new Argsdemo();
        ad.sum();
         ad.sum(1);
        ad.sum(1,2);
        ad.sum(1,2,3);                // 不管是几个参数,方法sum()都hold的住
    }

}

--->
sum=0
sum=1
sum=3
sum=6

例题2:

定义一个方法,在可变参数列表中进行查找?

package com.imooc.method;

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 static void main(String[] args) {
        ArgsDemo1 ad1=new ArgsDemo1();
        ad1.search(3, 1,2,3,4,5);                    // 1,2,3,4,5是传给可变参数的
        
        int[] arr= {1,2,3,4,5};
        ad1.search(3, arr);                            // 也可以将数组,传给可变参数列表
        
    }

}

--->
找到了!3
找到了!3

3.注意:

(1)一个方法中,只能有一个可变参数列表;

(2)以下说明,可变参数的底层实现其实是数组。可变参数功能更强大一些

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

方法重载时,两个方法的调用顺序:可变参数列表所在的方法,是最后被调用访问的

package com.imooc.method;

public class ArgsDemo3 {
    
    public int plus(int a,int b) {
        System.out.println("不带可变参数的方法被调用!");
        return a+b;
    }
    
    public int plus(int... a) {
        int sum=0;
        for(int n:a) {
            sum=sum+n;
        }
        System.out.println("带可变参数的方法被调用!");            // 可变参数列表所在的方法,是最后被访问的
        return sum;
    }

    public static void main(String[] args) {
        ArgsDemo3 ad3=new ArgsDemo3();
        System.out.println("和为:"+ad3.plus(1,2));
    }

}

--->
不带可变参数的方法被调用!
和为:3
感觉可变参数列表就像是兜底的

5.4 文档注释:

1.以下是以前的多行注释:

package com.imooc.method;

public class ArgsDemo3 {
    /*                                                        // 多行注释
    public int plus(int a,int b) {
        System.out.println("不带可变参数的方法被调用!");
        return a+b;
    }
    */
    public int plus(int... a) {
        int sum=0;
        for(int n:a) {
            sum=sum+n;
        }
        System.out.println("带可变参数的方法被调用!");            
        return sum;
    }

    public static void main(String[] args) {
        ArgsDemo3 ad3=new ArgsDemo3();
        System.out.println("和为:"+ad3.plus(1,2));            // 此时,只能调用可变参数了
    }
}

--->
带可变参数的方法被调用!
和为:3

2.以下是文档注释:

因为可以通过Javadoc命令,将代码中的注释提取出来,生成程序的帮助文档。

3.如何生成文档内容?

六、方法调试

跟其他的调试一模一样,唯一不同的是可以通过快捷键进入方法内部,查看方法内代码的执行细节。

演示如下:

七、总结

声明:Jerry's Blog|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - 2.3 方法


Follow excellence, and success will chase you.