什么是方法

Java 方法是语句的集合,他们在一起执行一个功能

  • 方法是解决一类问题的步骤的 有序组合

  • 方法包含于 对象

  • 方法在程序中被创建,在其他地方被引用

System.out.printLn()
  //System类 里的标准 对象out 中的 方法printLn()

设计方法的原则:方法的本意是功能块,就是实现某个功能的语句块的集合。我们设计方法的时候,最好保持方法的原子性,即一个方法只完成一个功能,这样利于我们后期的扩展

public class Demo {
    //main方法
    public static void main(String[] args) {
        int sum = add(1,2);
        System.out.println(sum);
        System.out.println("=====================");
        test();
    }
    //加法
    public static int add(int a,int b){
        return a + b;
    }
    public static void test(){
        int i = 0;
        while (i < 10) {
            i++;
            System.out.println(i);
            if (i == 3) {
                break;
            }
        }
    }
}

方法的定义及调用

Java 是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法:

  • 方法包含一个方法头和一个方法体。下面是一个方法的所有部分:

    • 修饰符:修饰符,这是可选的,告诉编译器如何调用该方法。定义了该方法的访问类型,例如有publicstatic等。

    • 返回值类型:方法可能会返回值。returnValueType 是方法返回值的数据类型。有些方法执行所需的操作,但没有返回值,这种情况下,returnValueType 是关键字 void

      public class Demo01{
      	public static int[] getNums() {
      
      		int[] nums = new int[100];
      		for(int i = 0;i < nums.length;i++) {
      			nums[i] = (int)(Math.random() * 100 + 1);
      		}
      		return nums;
      	}
      	public static void main(String[] args) {
      		int[] arr = Demo01.getNums();
      		System.out.println(Arrays.toString(arr));
      	}
      }
      
    • 方法名:是方法的实际名称。方法名和参数表共同构成方法签名。

    • 参数类型:参数像是一个占位符。当方法被调用时,传递值给参数。这个值称为实参或变量。参数列表是指方法的参数类型、顺序和参数的个数。参数是可选的,方法可以不包含任何参数。

      • 形参:形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。 形参只有在方法被调用的时候,虚拟机才会分配内存单元,在方法调用结束之后便会释放所分配的内存单元。 因此,形参只在方法内部有效,所以针对引用对象的改动也无法影响到方法外。
      • 实参:实际参数,用于调用时传递给方法的参数。实参在传递给别的方法之前是要被预先赋值的。
      //例,形参
      public static int add(int a,int b) {
        return a + b;
      }
      //例,实参
      public static void main(String[] args) {
        int sum = add(a:1,b:2)
      }
      
      public class Demo02{
      	public static int getSum(int[] arr) {
      		int sum = 0;
      		for (int i : arr) {
      			sum += i;
      		}
      		return sum;
      	}
      	public static void main(String[] args) {
      		int[] arr = {1,2,3,4};
      		System.out.println(Demo02.getSum(arr));
      		System.out.println(Demo02.getSum(new int[] {1,2,3,4})); // 直接输出时在参数位置直接new一个数组也可做到调用,不推荐
      	}
      }
      
    • 方法体:方法体包含具体的语句,定义该方法的功能。

      public class Demo03  {
          // 方法的命名:修饰符 + 返回值类型 + 方法名 + 形参列表 + 方法体
          public static void getSum() { // 声明方法为getSum,void是返回值类型  (是没有返回值的返回类型)
              int sum = 0;
              for (int i = 1; i < 11; i++) {
                  sum += i;
              }
              System.out.println(sum);
          }
      }
      
  • 方法的调用

    看调用方法**是否有static**修饰:

    1. static修饰,访问用:当前类名.方法名(实参(变量/值));

    2. 没有static修饰,访问 用:当前类的对象名.方法名(实参(变量/值));

    3. 如果调用方(目前是指main方法)和被调用方都在同一个类中,且都有或者都没有static修饰,可以简写为:方法名(实参(变量/值));

    注1:调用方法的时候,传入的参数数量、数据类型、顺序必须和 声明方法的一致

    注2:static修饰的方法不能直接调用static修饰的方法,但是static方法可以调用**static修饰的方法**

    public class Demo02 {
        // 方法的命名:修饰符 + 返回值类型 + 方法名 + 形参列表 + 方法体
        public static void getSum() { // 声明方法为getSum,void是返回值类型(是没有返回值的返回类型)
    
            int sum = 0;
            for (int i = 1; i < 11; i++) {
                sum += i;
            }
            System.out.println(sum);
        }
        public static void main(String[] args) {
           getSum(); // 在main函数内直接调用同static修饰符的方法getSum()
        }
    }
    

可变参数

可变参数是支持传递同类型的可变参数给一个方法,相当于数组类型。且一个方法中只能指定一个可变参数,它必须是方法的最后一个参数。任何普通的参数必须在它之前声明。在方法声明中,在指定参数类型后加一个省略号(…) 。

方法的可变参数的声明如下所示:

typeName... parameterName

public class Demo{
	public static int getSum(int... nums) {
		int sum = 0;
		for (int n : nums) {
			sum += n;
		}
		return sum;
	}
	public static void main(String[] args) {
		System.out.println(Demo.getSum(0,1,2,3));
	}
}

方法的执行流程

方法执行时遵循一定的规律,这个规律就是方法的执行流程,以如下代码实例:

public class Demo{
	public static void getSum(int a,int b) {
		System.out.println(a + b);
	}
	public static void main(String[] args) {
		Demo.getSum(10, 20 );
	}
}
  1. 首先进入main方法,在栈内存开辟栈帧;

  2. Demo.getSum(10, 20); 放入main方法的栈帧;

  3. 开辟getSum方法的栈帧;

  4. Demo类中找getSum(int a,int b)方法;

  5. 为形参赋值a = 10; b=20;

  6. 执行方法代码里的System.out.println(10 + 20); 输出结果30;

  7. getSum 方法执行完毕,出栈回到 main方法的栈帧;

  8. main方法结束, 出栈。

方法的执行流程

值传递与址传递

值传递概念:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。基础数据类型均为值传递。

在方法的调用过程中,实参把它的实际值传递给形参,此传递过程就是将实参的值复制一份传递到函数中,这样如果在函数中对该值(形参的值)进行了操作将不会影响实参的值。因为是直接复制,所以这种方式在传递大量数据时,运行效率会特别低下。

public class Demo {
    public static void main(String[] args) {
        int num = 10; // 实际参数
        test(num);
        System.out.println(num); // num的值没有被改变,任然为10;
    }
    // 测试值传递的方法
    public static void test(int num) {
        num = num + 19;
    }
}

引用传递:所谓引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。引用类型均为引用传递。

引用传递弥补了值传递的不足,如果传递的数据量很大,直接复过去的话,会占用大量的内存空间,而引用传递就是将对象的地址值传递过去,函数接收的是原始值的首地址值。在方法的执行过程中,形参和实参的内容 相同,指向同一块内存地址,也就是说操作的其实都是源数据,所以方法的执行将会影响到实际对象。

public class Demo {
    public static void main(String[] args) {
        int[] nums = {1, 1, 1}; // 实际参数
        System.out.println(nums[0] +  "\t" + nums[1] + "\t" + nums[2]); // 结果为 1 1	1
        test(nums);
        System.out.println(nums[0] +  "\t" + nums[1] + "\t" + nums[2]); // 结果为 2 2	2
    }
    // 测试引用传递的方法
    public static void test(int[] nums) {
        nums[0] = 2;
        nums[1] = 2;
        nums[2] = 2;
    }
}