从零开始学Java-方法

114 阅读14分钟

前言

前一篇文章中,我们讲解了Java数组中的访问,遍历,以及静态和动态数组的一些常见操作等。下面我们来学一下Java的方法吧!

目录

  • 什么是方法
  • 方法的三种格式
  • 方法的重载
  • 方法的内存

下面就让我们一起来学习一下什么是方法吧

什么是方法

  • 什么是方法

    其实呀方法就是程序中最小的执行单元。

  • 方法的使用场景

    有重复的代码,有独立的功能,都可以定义一个方法。

  • 方法的好处

    可以提高代码的重复性。

    可以提高代码的维护。

方法的格式

  • 方法的定义格式分3种:

    1.最简单的方法定义和调用

    2.带参数的方法定义和调用

    3.带返回值的方法定义和调用

下面我们就来学习第一种:最简单的定义和调用吧。我们先来看一下格式:

最简单的方法定义和调用

格式:

 public static void 方法名(){
     方法体;
 }

调用:

在主函数中调用。
方法名();

下面我们来简单的定义一个方法:

// 自定义playGame方法功能
public static void playGame(){
    System.out.println("选英雄");
    System.out.println("换技能");
    System.out.println("开始对局");
    System.out.println("崩盘");
    System.out.println("骂队友");
    System.out.println("送人头");
    System.out.println("凉凉");
}

这是自定义一个名为playGame方法的功能,那么定义完了怎么去调用呢?这个时候我们就要回到主函数去调用了。

public static void main(String[] args) {
    // 调用playGame方法
    playGame();
}

我们如果没有在主函数调用,来运行看一下: image.png 可以看到并没有打印出来我们自定义的方法里面的功能,因为程序都是从主函数开始执行的,主函数没有调用方法的话是不会执行其他方法里面的代码的,所以这点需要注意了。我们来调用看一下: image.png 下面我们来看一个案例:

需求:定义一个方法,在方法中定义两个变量求和并输出打印,我们一起来实现一下: 第一步:首先定义一个方法求和

// 定义一个sum方法用来求两个数的和
public static void sum(){
    // 定义变量a和变量b,并给他们赋值
    int a=10,b=20;
    // 定义变量c求a+b的和
    int c = a + b;
    System.out.println(c);
}

第二步:在主函数调用方法

public static void main(String[] args) {
    // 调用sum方法
    sum();
}

我们来运行看一下: image.png 以上就是最简单的方法定义和调用了,下面我们来学一下带参数的方法定义和调用。

带参数的方法定义和调用

带参数的方法定义和调用呢分两种:

1.单个参数:

定义:
public static void 方法名(参数){...} 
调用:
方法名(参数); 
例如:sum(10)

2.多个参数:

定义
public static void 方法名(参数1,参数2){...} 
调用:
方法名(参数1,参数2); 
例如:sum(1020)

这边有个注意点:方法调用时,参数的数量和数据类型必须与方法定义中小括号里面的变量一一对应,不然程序会报错。

我们还是使用上面那个例子吧:

// 定义一个sum方法用来求两个数的和,定义一个变量a和变量b用来接收
public static void sum(int a,int b){
    // 定义变量c求a+b的和
    int sum = a + b;
    System.out.println(sum);
}

然后在主函数中调用一下:

System.out.println("请输入第一个整数:");
int num1 = sc.nextInt();
System.out.println("请输入第二个整数:");
int num2 = sc.nextInt();
// 定义变量num1和num2用来传值;
sum(num1,num2);

这个时候有人就会问了,这两个是什么意思呢? image.png 其实这两个是行参和实参。我们来说一下吧:

行参:全称形式参数,是指方法定义中的参数
实参:全称实际参数,是指方法调用中的参数

好啦,带参数的方法定义和调用我们就讲到这里,下面我们来看一个例子实现一下吧:

需求:定义一个方法,求长方形的周长,将结果在方法中进行打印 第一步:定义求周长的方法

// 定义一个rlong方法用来求两个数的和,定义一个变量a和变量b用来接收
public static void rlong(double a,double b){
    // 定义变量girth用来求长方形的周长
    double girth = (a + b) * 2;
    System.out.println("长方形的周长=" + girth);
}

第二步:在主函数传值调用

System.out.println("请输入长方形的长:");
double num1 = sc.nextInt();
System.out.println("请输入长方形的宽:");
double num2 = sc.nextInt();
rlong(num1,num2);

下面我们来运行看一下吧: image.png 怎么样,是不是很简单呢?那你们可以自己编写一个方法求长方形的面积哟。好啦我们接下来就来学习最后一个带返回值的方法定义和调用吧!

带返回值的方法定义和调用

什么叫返回值的方法:

如果在调用处要用到方法的结果去编写另外一段代码的时候,这个时候就要定义带有返回值的方法了。带返回值的方法和前面两个方法的定义有点不一样,我们来看一下:

格式:

 public static 返回值类型 方法名(参数){
     方法体;
     return 返回值;
 }
 例:
 public static int sum(int a,int b){
     int c = a + b;
     return c;
 }

调用的三种方法:

1.直接调用
方法名(实参);
2.赋值调用
整数类型 变量名 = 方法名(实参);
3.输出调用
System.out.println(方法名(实参));

下面我们来看几个案例吧:

  • 求当前季度的营业额

第一步:由键盘输入三个月的营业额

System.out.println("请输入第一个月的营业额:");
double num1 = sc.nextInt();
System.out.println("请输入第二个月的营业额:");
double num2 = sc.nextInt();
System.out.println("请输入第三个月的营业额:");
double num3 = sc.nextInt();

第二步:定义一个带有返回值的方法求季度营业额

public static double sum(double num1,double num2,double num3){
    double sum = num1 + num2 + num3;
    // 返回给方法的调用者
    return sum;
}

第三步:赋值调用

// 赋值调用
double sum1 = sum(num1,num2,num3);
System.out.println(sum1);

这个时候我们来运行看一下效果吧: image.png

下面我们来说一下方法的注意事项:

1.方法不调用就不执行。

2.方法与方法之间是平级关系,不能互相嵌套。

3.方法的编写顺序和执行顺序无关。

4.方法的返回值为void,表示该方法没有返回值。

5.return语句下面,不能编写代码,因为永远执行不到。

下面我们重点来说一下return关键字吧:

1.方法没有返回值,可以不写,如果要写,表示结束方法。

2.方法有返回值,必须要写,表示结束方法和返回结果。

方法的重载

什么是方法重载呢?我们来看个直观的例子:

需求:求两个数的和,三个数的和,四个数的和。 image.png 是不是要定义多个方法名呢?有没有感觉很重复呢?那么有没有方法更简单呀?有的,这个就叫做方法重载。

我们来看一下方法的概念吧:

  • 在同一个类中,定义了多个同名的方法,这些同名的方法具有同种的功能。
  • 每个方法具有不同的参数类型或者参数个数,这些同名的方法就构成了重载关系。

是不是很麻烦?没关系,我们来看一下技巧:

  • 简单记: 同一个类中,方法名相同,参数不同的方法。与返回值无关。

    参数不同:个数不同、类型不同、顺序不同。

我们来看个构成重载关系的例子吧: image.png

image.png 我们再来看个不构成重载关系的例子: image.png 为什么呢?

我们来回忆一下:是不是在同一个类当中,方法名要一样,参数是不是要不同呢?这里两个方法都是同一个参数,所以就不构成重载关系啦。

Java虚拟机会通过参数的不同来区分同名的方法

下面我们自己来练习一下定义重载的方法吧! 需求:使用方法重载的思想,设计比较两个整数是否相同的方法。兼容全整数类型(byte ,short,int,long,double)。

// 定义重载方法
public static void sum(byte a,byte b){
    System.out.println("我是byte重载方法");
    System.out.println(a == b);
}

public static void sum(short a,short b){
    System.out.println("我是short重载方法");
    System.out.println(a == b);
}

public static void sum(int a,int b){
    System.out.println("我是int重载方法");
    System.out.println(a == b);
}

public static void sum(long a,long b){
    System.out.println("我是long重载方法");
    System.out.println(a == b);
}

public static void sum(double a,double b){
    System.out.println("我是long重载方法");
    System.out.println(a == b);
}

下面我们怎么样在主函数调用呢?

// byte调用重载方法
byte a = 10;
byte b = 10;
sum(a,b);

// short调用重载方法
short a = 10;
short b = 10;
sum(a,b);

// int调用重载方法
int a = 10;
int b = 10;
sum(a,b);

// long调用重载方法
long a = 10;
long b = 10;
sum(a,b);

// double调用重载方法
double a = 10;
double b = 10;
sum(a,b);

好啦,方法重载就讲到这里,你理解了吗?

方法的内存

到目前方法已经学习完毕啦,下面我们来做个额外的小扩展吧:

  • 方法调用的基本内存原理:和栈一样,先进后出(后进先出).

  • 基本数据类型和引用数据类型:

    • 基本数据类型:整数类型、浮点数类型、布尔类型、字符类型.

      基本数据类型的数据值是存储在自己的空间中.

    image.png

    特点:赋值给其他变量,赋的是真实的值.

    • 引用数据类型:除了基本数据类型外其他的都是引用数据类型.

      引用数据类型的数据值是存储在其他空间中,自己空间中存储的是地址值

    image.png

    特点:赋值给其他变量,赋的是地址值.

    我们来看一段代码:

      ```引用数据类型
      int[] arr1 = {1,2,3};
      int[] arr2 = arr1; // arr2此时获取到的是arr1的地址值.
      无论arr1还是arr2操作值的时候数组里面的元素都会发生改变.
      ```
    

    image.png

    引用数据类型只需要记住一句话:只要是new出来的都是引用数据类型,此时变量后面的不是真实数据,而是地址值,要通过索引去获取相对应的真实数据.

  • 基本数据类型和引用数据类型方法传递的结论:

    • 存储空间不同:
      • 基本数据类型的数据值是存储在自己的空间中
      • 引用数据类型的数据值是存储在其他空间中,自己空间中存储的是地址值
    • 赋值不同:
      • 基本数据类型赋值给其他变量,传递的是真实的数据
      • 引用数据类型赋值给其他变量,传递的是地址值

方法的常见习题

好啦,关于数组的知识点我们就学完啦,下面我们来做几个小练习巩固一下吧!

    1. 遍历数组,设计一个方法,要求遍历的结果是在同一行,例如[1,2,3,4,5]。

    第一步:定义一个数组:

    // 1.定义数组
    int[] arr1 = {1,2,3,4,5};
    

    第二部:编写遍历数组的方法

    // 设计一个方法用来遍历数组
    public static void printarr(int[] arr){
        // 遍历数组前加个[括号。
        System.out.print("[");
        for (int i = 0; i < arr.length; i++) {
            // 如果i是最后一个元素的话就直接打印他的值
            if(i == arr.length - 1){
                System.out.print(arr[i]);
            }else{
                // 打印出i下标的每个元素加,号。
                System.out.print(arr[i] + ",");
            }
        }
        // 遍历数组结束后加个]括号。
        System.out.println("]");
    }
    

    第三步:调用方法

    // 调用printarr方法
    printarr(arr1);
    

    下面我们来运行看下效果吧: image.png

    怎么样,是不是和题目需求一样了呢。我们再来看第二道!

    1. 取数组的最大值。设计一个方法求数组的最大值,并将最大值返回。

    第一步:定义一个数组

    // 1.定义数组
    int[] arr2 = {10,20,50,80,30};
    

    第二部:编写取最大值方法

    // 初始化数组的第一个元素为最大值。
    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        // 判断数组下标的元素如果大于max就把他存放进max里面
        if(arr[i] > max){
            max = arr[i];
        }
    }
    // 遍历完后返回max最大值给主函数使用
    return max;
    

    第三步:调用方法

    // 2.将最大的值赋值给max
    int max = maxarr(arr2);
    System.out.println("最大的值:" + max);
    

    我们运行看一下效果: image.png

    我们再来看下一道:

    1. 定义一个方法判断数组中的某个数是否存在,将结果返回给调用处。

    第一步:定义数组

    int[] arr3 = {10,20,30,40,50};
    

    第二步:编写判断数组元素的方法

    // 设计一个方法用来判断某个数在不在
    public static boolean compare(int arr[],int number){
        // 遍历数组里面的每一个元素
        for (int i = 0; i < arr.length; i++) {
            // 从0下标开始判断,判断里面的元素有没有等于number的,有的就执行返回true。
            if(arr[i] == number){
                return true;
            }
        }
        // 如果遍历完了全部数组里面的元素都没有等于传过来的值的话就会执行这行返回false。
        // 如果上面的元素有等于number的话就会在上面执行返回true,不会执行到这行了。
        return false;
    }
    

    第三步:调用方法

    // 判断这个数组中10存不存在。
    boolean flag = compare(arr3,10);
    System.out.println(flag);
    

    我们运行看一下10在不在数组中: image.png可以看到返回一个true,那就证明10存在数组中,下面我们来扩展一个小知识,return和break有什么区别.

return和break关键字的区别:

return:其实跟循环没有关系,跟方法有关,表示1结束方法,2返回结果,如果方法执行到了return,那么整个方法全部结束,里面的循环也会随之结束。

break:其实跟方法没有关系,跟结束循环或者switch的。

    1. 定义一个方法copyOfRange(int[] arr,int from,int to)

    需求:将数组arr中从索引from(包含from)开始,到索引to结束(不包含to)的元素复制到新数组中。将新数组返回。

    第一步:定义初始数组

    // 定义一个原始数组
    int[] arr4 = {10,20,30,40,50,60,70,80,90,100};
    

    第二步:定义新的数组

     // 定义一个新数组,由于不知道长度,可以使用动态数组,长度=结束位置-开始位置
     int[] newarr = new int[to - form];
    

    第三步:遍历原数组

    // 把原数组的元素拷贝到新数组,开始位置为from,结束位置为to
    for (int i = form; i < to; i++) {
    }
    

    第四步:拷贝原数组数据

    // 伪造索引
    int index = 0;
    // 格式:数组名[索引] = 数据值
    newarr[index] = arr[i];
    index++;
    

    第五步:调用方法

    // 定义新数组接受传过来的新数组
    int[] copyarr = copy(arr4,1,7);
    

    第六步:遍历传过来的新数组

    for (int i = 0; i < copyarr.length; i++) {
        System.out.print(copyarr[i] + " ");
    }
    

    我们来运行看一下吧: image.png 是不是成功把下标为1开始的20到下标为7的元素拷贝到新数组了呢.为什么没把下标为7的80拷贝进来呢?这个时候我们就要记住了,包头不包尾.所以没有把80给拷贝到新的数组里.

    我们来看下完整代码吧:

      public static void main(String[] args) {
          // 练习四:定义一个方法copyOfRange(int[] arr,int from,int to)
          /* 需求:将数组arr中从索引from(包含from)开始,到索引to结束(不包含to)的元素复制到新数组中。
          将新数组返回。*/
          // 定义一个原始数组
          int[] arr4 = {10,20,30,40,50,60,70,80,90,100};
          // 定义新数组接受传过来的新数组
          int[] copyarr = copy(arr4,1,7);
          System.out.print("截取的新数组为:" + " ");
          for (int i = 0; i < copyarr.length; i++) {
              System.out.print(copyarr[i] + " ");
          }
      }
    
      // 将数组arr中从索引from(包含from)开始,到索引to结束(不包含to)的元素复制到新数组中。
      public static int[] copy(int[] arr,int form,int to){
          System.out.print("原始数组为:");
          for (int i = 0; i < arr.length; i++) {
              System.out.print(arr[i] + " ");
          }
          System.out.println();
          // 定义一个新数组,由于不知道长度,可以使用动态数组,长度=结束位置-开始位置
          int[] newarr = new int[to - form];
          // 伪造索引
          int index = 0;
          // 把原数组的元素拷贝到新数组,开始位置为from,结束位置为to
          for (int i = form; i < to; i++) {
              // 格式:数组名[索引] = 数据值
              newarr[index] = arr[i];
              index++;
          }
          return newarr;
      }
    

这个练习比较难一点,需要理解的是索引开始位置和结束位置,以及伪造索引的原因.相信经过多加练习的你一定不难!!!

好啦,以上就是Java的方法一些定义以及使用,如果有什么不懂的可以在评论区评论哟,我们下期再见!

==最后非常感谢您的阅读,也希望能得到您的反馈  ==