今日所学知识的具体实现及例题将整合至明日“动手动脑”。
1、软件工程模块化原则
模块:将一个复杂的系统划分为子模块,便于设计、实现和维护
Java种的程序模块:方法、类、包
Java在程序中最基本的构造单元是类,而类中最重要的成员就是方法
例:Java模块实例:JDK种的Math类
2、使用静态导入
从JDK5.0开始,支持一种称为 ”静态导入" 的方法:
import static java.lang.Math.*;
从而允许在Java代码中省略类名只写静态方法名;
System.out.println(abs(-100));
上述方法完全等价于:
System.out.println(Math.abs(-100));
3、类方法的编写
将方法放入类中,并将其定义为静态(static),是面向对象软件提供类似于C语言程序种“全局函数”的基本手段
开发自己的方法,只需创建一个类,然后为其编写声明为public的函数即可。
例1:定义一个求平方数的静方法 Square (SquareInt.java)
例2:随机数生成 (RandomInt.java)
4、使用Random类生成随机数
JDK提供了一个Random类,可以更加方便地生成随机数
例:TestRandom.java
相同“种子”的Random对象会生成相同的随机数
例:TestSeed.java
通常使用以下方法生成较好的随机数,它以当前的时间为“种子”
Random ran = new Random(System.currentTimeMillis());
例:模拟骰子滚动的统计结果(RollDie.java)
纯随机数发生器:
5、参数可变的方法
从JDK5.0起,Java支持可变参数的方法
例:VariableArgumentsTest.java
可变参数的特点:
- 只能出现在方法参数列表的最后
- “..."位于变量和变量名之间,前后有无空格均可
- 调用可变参数方法时,编译器为该可变参数隐含创建一个数组,在方法体中以数组的形式访问可变参数
6、方法重载的要点
满足以下条件的两个或多个方法构成“重载”关系:
(1)方法名相同
(2)参数类型不同,参数个数不同,或者是参数类型的顺序不同
注意:方法的返回值不作为方法重载的判断条件
7、递归
简言之:递归就是“自己调用自己"
例:编个程序求n! Demo:CalculateN
从n!的数学公式可以看到,要计算n!可以先计算(n-1)!,得到(n-1)!的结果之后,将其乘以n就得到n!
递归的特点:
- 先从大到小,再从小到大
- 每个步骤要干的事情都是类似的,只不过其规模”小一号"
- 必须要保持递归调用的过程可以终结
递归编程的模式:
- 每个递归函数的开头一定是判断递归结束条件是否满足的语句(一般是if语句)
- 函数体一定至少有一句是“自己调用自己”的
- 每个递归函数一定有一个控制递归可以终结的变量(通常是作为函数的参数而存在),每次自己调用自己时,此变量会变化(一般是变小),并传送给被调用的函数。
递归和递推的比较:
1)递归是由后到前再回来,要求第n项,先求到第n-1项,...,倒推到前面的可计算出的某项,然后再返回
2)递推是从前到后,先求第1项,然后,在此基础上求第2项,第3项,直至第n项,通常可以直接使用循环语句实现
在开发中,很多算法既可以使用递归也可以使用递推实现,要依据具体情况进行决断
8、处理大数字与浮点数
演示:CalculateN示例程序中的BUG
结论:由于计算机使用固定的位数来保存数值,因此,能处理的数值大小是有限的,当要处理的数值超过了这一范围时,计算机将会自动截断数值的二进制表示为它所能处理的最多位数,这将导致错误的处理结果。
处理无限大的整数
Java提供了一个BigInteger类,支持大整数的加减乘除运算
public static BigInteger calculateN2(int n){ if(n==1||n==0) { return BigInteger.valueOf(1); } return BigInteger.valueOf(n).multiply(calculateN2((n-1))); }
注意:
计算机不能精确地表达浮点数(特殊形式的除外),因此,当需要比较两个浮点数是否相等时,应该比较其差的绝对值是否在某个允许范围之内即可。