0%

Java 编程基础(六):方法及方法调用

1. Java 支持可变长度参数,可变长度参数的语法及格式

  • 语法:在数据类型后面加三个点即:
  • 格式:可变长度参数必须是参数列表中的最后一个;一个方法也只能有一个可变长度参数

2. 可变参数的作用

  • 简化代码书写,因为可变长度参数实际上会转换为数组参数

3. “return 可以用于方法内的任意地方”,对吗

4. “方法返回值类型为 void 也可以使用 return”,对吗

  • 对,return;

5. 请写出下面程序结果并分析

1
2
3
char a = 'a';
char b = 'b';
System.out.println(Math.max(a, b));
  • 结果是数字 98。参数是字符类型的,但 Math 并没有定义针对字符类型的 max() 方法,这是因为 char 本质上就是一个整数,Java 会自动将 char 转换为 int,然后调用 Math.max(int a, int b)
  • 如果 Math 中没有定义针对 int 类型的 max() 方法,会调用 long 类型的 max() 方法;如果 long 类型也没有会调用 float 类型的 max() 方法;如果 float 类型也没有,会调用 double 类型的。Java 编译器会自动进行类型转换,并寻找最匹配的方法
  • 在只有一个方法的情况下(即没有重载),只要可以进行类型转换,就会调用该方法;在有方法重载的情况下,会调用最匹配的方法

6. 简单介绍一下栈的概念

  • 数据结构中的栈,特点是先进后出;内存中的栈,一般是从高位地址向地位地址扩展
  • 栈用来存放方法调用过程中需要的数据,包括:参数(基本数据类型)返回地址局部变量(方法内部定义)
  • 这些栈内存变量的生命周期是:只有在方法被调用的时候才分配,而且在方法调用结束后就被释放了

7. 对象类型的内存分配是怎样的

  • 数组和对象类型,都有两块内存:一块存放实际的内容,一块存放实际内容的地址
  • 实际的内容空间分配在堆内存上,但存放地址的空间是分配在栈内存上。即:栈地址,堆内容

8. 方法签名的概念

  • 方法签名 = 方法名 + 参数列表(参数类型、参数顺序、参数数量)

9. 什么是值传递、引用传递,Java 是值传递还是引用传递

  • 结论:Java 中只有值传递。只不过对于对象参数,值的内容是对象的引用

  • 概念

    • 值传递(pass by value):是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数
    • 引用传递(pass by reference):是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数
  • 参考:Java 到底是值传递还是引用传递

10. 递归概述

  • 递归的概念

    • 递归:程序调用自身的编程技巧,递归方法是直接或间接(考虑到重载)调用自身的方法
  • 递归的要点

    • 定义递归方法时,需要定义递归的初始状态初始状态的处理递归调用
    • 初始状态也称为终止条件,即最简单的情况,此时应该直接给出如何处理初始状态;对于非初始状态,则需要进行递归调用,对子问题进行求解,直到初始状态。然后将结果返回给调用者,直到传回原始的调用者
    • 递归必须定义初始状态,且保证所有的递归调用都能到达初始状态。否则会发生无限递归,导致栈溢出
  • 递归的优点

    • 递归的优点是代码简洁且易于理解
    • 如果问题满足递归的特点,即可以分解成子问题且子问题与原始问题相似,则可以使用递归给出自然、直接、简单的解法
  • 递归的缺点

    • 时间和空间的消耗比较大。每一次函数调用都需要在内存栈中分配空间,对栈的操作还需要时间,因此时间复杂度和空间复杂度都会比较高
    • 如果子问题之间存在重叠,则在不加记忆化的情况下,递归会产生重复计算,导致时间复杂度过高
    • 由于栈的空间有限,如果递归调用的次数太多,则可能导致调用栈溢出
  • 尾递归

    • 概念:当递归调用是方法中最后执行的语句且 return 语句不包含表达式
    • 特点:在返回时直接传回原始的调用者,不用经过中间的调用者。这个特点很重要,因为大多数现代的编译器会利用该特点自动生成优化的代码
    • 优点:使用尾递归代替普通的递归,可以在时间空间方面都带来显著的提升
  • Demo: 斐波那契数列

    • 普通递归:包含大量重复子问题,时间复杂度高;递归调用栈太深时,空间复杂度高,容易导致栈溢出

      1
      2
      3
      4
      5
      6
      7
      8
      9
      public class Fibonacci {
      public static long fibonacci(int index) {
      if(index <= 1) {
      return index;
      } else {
      return fibonacci(index - 1) + fibonacci(index - 2);
      }
      }
      }
    • 尾递归优化:即 return 语句不包含表达式。不会有重复计算,具有线性迭代特性,栈不会增长、不会导致栈溢出

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      public class Fibonacci {
      public static long fibonacciTailRecursion(long index) {
      return fibonacciTailRecursion(index, 0, 1);
      }
      public static long fibonacciTailRecursion(long index, int curr, int next) {
      if(index == 0) {
      return curr;
      } else {
      return fibonacciTailRecursion(index - 1, next, curr + next);
      }
      }
      }
-------------------- 本文结束感谢您的阅读 --------------------