学习目标
1、掌握方法的可变参数定义及使用
2、掌握递归算法以及其他优缺点
3、掌握构造方法的定义及使用
4、掌握this、static、package、import关键字
5、熟练实现一些常用算法
第1章 方法的可变参数
1.1 方法的可变参数引入
需求一:
现在假如有这样一个设计需求,一个工具类中,要实现一个求2个整数之和的方法;接着,还需要实现一个求2个小数求和的方法。
针对上面这个需求,最开始我们可以定义两个方法getSum1()和getSum2()分别求和。但是,如果类似需求增多了呢?这种定义方法的方式就显得不够文雅了,因此,这里就可以用上我们前一天学习的方法重载了。
需求二:
接着,又有这样的需求改进:不但要实现2个整数之和,还要实现三个、甚至是四个、五个……整数之和,怎么解决呢?难道,我们就定义n个这样的求和方法?
针对这种需求,即使用上方法重载也是不太好实现这个需求的,我们不知道到底有几个参数,也不知道到底要定义几个这样的方法。为此,Java设计出了方法的可变参数来实现这种需求。
1.2 方法的可变参数介绍
在实际开发过程中,有时方法中参数的个数是不确定,但是类型相同的。为了解决这个问题,在 J2SE 5.0 版本中引入了可变参数的概念。
语法
方法名([固定参数列表],可变参数类型… 可变参数形参名)
示例:
getSum(int... v);
getOrder(String a,int... ids);
说明:
- 当需求设计方法时,方法的部分参数类型一致且个数不定,就可以使用Java的可变参数定义方法;
- 定义可变参数方法时,允许加入其他类型的固定参数列表,且可变参数必须放在最后;
- 在方法中定义可变参数后,我们可以像操作数组一样操作该参数。
1.3 方法的可变参数使用
在方法中定义可变参数后,我们可以像操作数组一样操作该参数。
这里,我们就对前面小节的需求使用方法的可变参数进行实现。
public class VariableParamTest {
public static void main(String[] args) {
int rs1= getSum();
System.out.println(rs1);
int rs2= getSum(1,2);
System.out.println(rs2);
}
// 定义一个可变参数方法,求取n个整数之和
public static int getSum(int... numbers) {
int sum=0;
for (int i = 0; i < numbers.length; i++) {
sum+=numbers[i];
}
return sum;
}
}
第2章 递归方法
2.1 递归介绍
递归算法(英语:recursion algorithm)在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。
递归往往能给我们带来非常简洁非常直观的代码形势,从而使我们的编码大大简化,然而递归的思维确实很我们的常规思维相逆的,我们通常都是从上而下的思维问题, 而递归趋势从下往上的进行思维。这样我们就能看到我们会用很少的语句解决了非常大的问题,所以递归策略的最主要体现就是小的代码量解决了非常复杂的问题。
场景说明:
假设你在一个电影院,你想知道自己坐在哪一排,但是前面人很多,你懒得去数了,于是你问前一排的人「你坐在哪一排?」,这样前面的人 (代号 A) 回答你以后,你就知道自己在哪一排了——只要把 A 的答案加一,就是自己所在的排了,不料 A 比你还懒,他也不想数,于是他也问他前面的人 B「你坐在哪一排?」,这样 A 可以用和你一模一样的步骤知道自己所在的排。然后 B 也如法炮制,直到他们这一串人问到了最前面的一排(或者说问到了知道自己是哪一排的人,预示着调用结束),第一排的人告诉问问题的人「我在第一排」,最后大家就都知道自己在哪一排了。
定义: 一个方法在执行过程中调用自身, 就称为 “递归”。
递归,相当于数学上的 “数学归纳法”, 有一个起始条件, 然后有一个递推公式. 例如, 我们求 N! 起始条件: N = 1 的时候, N! 为 1. 这个起始条件相当于递归的结束条件。
2.2 递归使用
递归的思想就是,通过重复将问题分解为同类的子问题而解决问题的方法。也就是说,针对同样的工作,我们可以定义一个方法,然后重复调用即可。
这里,我们以一个求n的阶乘为例进行说明。
求 N! , 直接不好求, 可以把问题转换成 N! => N * (N-1)!,也就是可以用递归实现。(当前数*前一个数的阶乘)
示例:
public class RecursiveTest {
public static void main(String[] args) {
// 调用递归方法,求n的阶乘
int res=getRecursive(5);
System.out.println(res);
}
// 递归方法,求n的阶乘
public static int getRecursive(int n) {
if(n==1) {
// 如果为1的时候,就跳出,不再递归
return 1;
}else {
// n非1的情况下,继续调用本身,获取前一个数的递归结果
int res=n*getRecursive(n-1);
return res;
}
}
}
图解:
如上图所以,n!其实就是n*(n-1)!,依次类推,只要找到出口n=1即可算出n的阶乘结果。
2.3 递归方法说明
2.3.1 递归方法优缺点
关于Java递归方法需要注意以下几点:
- 递归方法可以使用重复方法、少量代码,即可实现复杂功能的实现;
- 递归方法一定要有出口,否则无限递归调用,直到出现StackOverflowError(栈内存溢出)错误;
- 递归方法的递归次数也不能过多,否则同样出现StackOverflowError(栈内存溢出)错误;
- 递归方法都可以使用非递归方法解决,比如循环。
2.3.2 递归方法优缺点说明
1、StackOverflowError
从上图示例可以看出,递归方法没有出口、递归次数过多,都会产生StackOverflowError(栈内存溢出)错误。这是因为,在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等,所以一般不提倡用递归算法设计程序。
2、使用循环替代递归方法
这里,我们对前面的求n的阶乘方法使用循环的方式实现。
示例:
public class RecursiveTest2 {
public static void main(String[] args) {
// 调用递归方法,求n的阶乘
int res=getRecursive(6);
System.out.println(res);
}
// 使用循环实现n!
public static int getRecursive(int n) {
int res=1;
for (int i = 1; i <=n; i++) {
res*=i;
}
return res;
}
}
第3章 构造方法
3.1 构造方法介绍
定义: 就是类构造对象时调用的方法,主要用来实例化对象。构造方法分为无参构造方法、有参构造方法。
说明:
- 构造方法是类的一个特殊成员方法;
- 构造方法作用:(1)构造出来一个类的实例 (2)对构造出来个一个类的实例(对象)初始化;
- 构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连void也没有;
- 类中必定有构造方法,若不写,系统自动提供一个无参构造方法;而一旦提供了有参构造方法,就不再提供默认的无参构造方法;
- 构造方法存在重载,比如无参构造方法和有参构造方法;
- 构造方法就是来创建对象的,使用new关键字,然后根据提供的构造方法进行选择构造即可。
示例:
public class Student {
// 成员变量
Str