1. Java 支持可变长度参数,可变长度参数的语法及格式
- 语法:在数据类型后面加三个点即:
…
- 格式:可变长度参数必须是参数列表中的最后一个;一个方法也只能有一个可变长度参数
2. 可变参数的作用
- 简化代码书写,因为可变长度参数实际上会转换为数组参数
3. “return
可以用于方法内的任意地方”,对吗
- 对
4. “方法返回值类型为 void
也可以使用 return
”,对吗
- 对,
return;
5. 请写出下面程序结果并分析
1 | char a = 'a'; |
- 结果是数字 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):是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数
10. 递归概述
递归的概念
- 递归:程序调用自身的编程技巧,递归方法是直接或间接(考虑到重载)调用自身的方法
递归的要点
- 定义递归方法时,需要定义递归的初始状态、初始状态的处理、递归调用
- 初始状态也称为终止条件,即最简单的情况,此时应该直接给出如何处理初始状态;对于非初始状态,则需要进行递归调用,对子问题进行求解,直到初始状态。然后将结果返回给调用者,直到传回原始的调用者
- 递归必须定义初始状态,且保证所有的递归调用都能到达初始状态。否则会发生无限递归,导致栈溢出
递归的优点
- 递归的优点是代码简洁且易于理解
- 如果问题满足递归的特点,即可以分解成子问题且子问题与原始问题相似,则可以使用递归给出自然、直接、简单的解法
递归的缺点
- 时间和空间的消耗比较大。每一次函数调用都需要在内存栈中分配空间,对栈的操作还需要时间,因此时间复杂度和空间复杂度都会比较高
- 如果子问题之间存在重叠,则在不加记忆化的情况下,递归会产生重复计算,导致时间复杂度过高
- 由于栈的空间有限,如果递归调用的次数太多,则可能导致调用栈溢出
尾递归
- 概念:当递归调用是方法中最后执行的语句且
return
语句不包含表达式 - 特点:在返回时直接传回原始的调用者,不用经过中间的调用者。这个特点很重要,因为大多数现代的编译器会利用该特点自动生成优化的代码
- 优点:使用尾递归代替普通的递归,可以在时间和空间方面都带来显著的提升
- 概念:当递归调用是方法中最后执行的语句且
Demo: 斐波那契数列
普通递归:包含大量重复子问题,时间复杂度高;递归调用栈太深时,空间复杂度高,容易导致栈溢出
1
2
3
4
5
6
7
8
9public 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
12public 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);
}
}
}