JFreeChart 0.9.21 源码分析报告
作者:北京赌车王
报告 1: 分析为何使用 Comparable 和 Number 接口
方法类中使用 import java.lang.Comparable 类和 java.lang.Number 类,主要因为
数字 Long,Btye,Float,Short,Double,Integer 继承了 Number 类,实现了 Comparable 接口,以下 J2SE 中 UML 类图。
图 1 。 0
赋值和取值都使用 Comparable 和 Number 类。
(1) 剖析赋值操作。
例子源码如下:
private Number value = null;
public void setValue(final Comparable key, final Number value) {
this.value = value;
}
使用 Comparable 和 Number 类,可以使用户输入任意数字类型。
(2) 剖析取值操作。
例子源码如下:
public Number getValue(final Comparable key) {
// 取值操作。。。。。
return this. value;
}
使用 Comparable 和 Number 类,可以使用户输入任意数字类型。
(3) 多态取值使用操作。
例子源码如下:
Comparable key = (Comparable) iterator1.next();
Number n = this.dataset.getValue(key);
if (n != null)
double v = n.doubleValue(); // 注意这个地方使用类型转换,实现得向下转型
if (key != null)
String k = key.toString(); // 注意这个地方使用了 Object 类得转换。
Number 最终使用得是 double 类型。
Comparable 最终使用得是 String 类型。
小结: 以上操作灵活得使用了接口 Comparable 和抽象类 Number ,这样操作方便了用户得输入操作,可以适应用户任意输入类型,最后转型由程序完成,从用户角度来看,认为输入任何数字类型,程序都不会出错。从编程角度来看,可以只编写一个 Number 对象 和一个 Comparable 对象 ,就可以任意赋值了,不用为了用户输入得类型,而重新定义对象类型, Number 对象 最终使用得是 double 类型 Comparable 对象 最终使用得是 String 类型,在需要向下转型得时候,直接由多态实现。
报告 2 :方法参数中使用 final 关键字
final 关键字得使用方法:
对于基本类型的变量,这样做并没有什么实际意义,因为基本类型的变量在调用方法时是传值的,也就是说你可以在方法中更改这个参数变量而不会影响到调用语句,然而对于对象变量,却显得很实用,因为对象变量在传递时是传递其引用,这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量,当你在方法中不需要改变作为参数的对象变量时,明确使用 final 进行声明,会防止你无意的修改而影响到调用方法。
对不变的 data 和 object reference 使用 final 了让 data 或 object reference 成为不变量(常数),请使用 final 。注意, final 仅仅令 object reference 自身成为不变量,并不限制它所指对象的改变。
在方法参数中,使用 final 关键字。例如:
public Number getValue(final Comparable key) {
Number result = null;
final int index = getIndex(key);
if (index >= 0) {
result = getValue(index);
}
return result;
}
分析: 源码中大量在方法中使用了 public Number getValue( final Comparable key) final 关键字。 使 方法中不需要改变作为参数的对象变量时,明确使用 final 进行声明,会防止无意的修改而影响到调用方法。
小结: 在方法内部声明为 final ,灵活的使用的 final 提升了程序速度,也明确了不能修改的变量,而且还体现了程序的强内聚,由于 final 出现在方法内部,所以不会出现把类的成员声明为 final ,在之后难以修改类的局面,这种使用 final 的方法,是很符合逻辑的。
报告 3 :如何适应输入任意类型的数字
在 jfreechart 中使用的数据集,当对数据集合赋值得时候,会发现你可以输入任意类型得数字,我本已为 jfreechat 可以实现任意输入数字,可以实现任意形式得多态转换,但是最后我发现,原来是使用了 NumberFormat 类得 format 方法,这个方法可以实现任意类型,转换成字符串,从表面上看上去,很象实现得任意数字类型得多态。
以下我写了一个简单例子,来说明这个问题的实现过程:
功能:输入任意类型得数字,程序对输入得数字类型,实现对应的转换,最后输入 String 类型。
package myPack;
import java.lang.Number;
import java.lang.Comparable;
import java.util.ArrayList;
import java.text.NumberFormat;
/* 例子实现得用户任意输入数字类型,转换成对应得字符串
例如:输入 int 22 结果 : 22
输入 float 22f 结果: 22
输入 double 22.22 结果: 22.22
输入 double 22.22L 结果: 22.22
*/
public class MatchAnyNumber {
private ArrayList list = null;
private NumberFormat numberFormat = null;
public MatchAnyNumber() {
list = new ArrayList();
numberFormat= NumberFormat.getNumberInstance();
}
public void setInfo(){
try{
// 测试 Int 型数字
NumberInfo ni1 = new NumberInfo();
ni1.setName("int");
ni1.setValue(22);
list.add(ni1);
// 测试 Float 型数字
NumberInfo ni2 = new NumberInfo();
ni2.setName("float");
ni2.setValue( 22.22F );
list.add(ni2);
// 测试 Double 型数字
NumberInfo ni3 = new NumberInfo();
ni3.setName("double");
ni3.setValue(22.22D);
list.add(ni3);
// 测试 Long 型数字
NumberInfo ni4 = new NumberInfo();
ni4.setName("long");
ni4.setValue( 22L );
list.add(ni4);
}
catch(Exception e){
e.printStackTrace();
}
}
public void getInfo(){
java.util.Iterator iter = list.iterator();
while(iter.hasNext()){
NumberInfo ni = (NumberInfo) iter.next();
String testName = ni.getName().toString();
String testValue = numberFormat.format(ni.getValue());
System.out.println("input number type:"+testName+"/ value:"+ni.getValue());
System.out.println("out number type:"+testName+"/ value:"+testValue);
}
}
private class NumberInfo{
private Comparable name = null;
private Number value = null;
public void setName(final Comparable name){
this.name = name;
}
public Comparable getName(){
return this.name;
}
public void setValue(final Number value){
this.value = value;
}
public void setValue(final double value){
setValue(new Double(value));
}
public Number getValue(){
return this.value;
}
}
public static void main(String[] args){
MatchAnyNumber test = new MatchAnyNumber();
test.setInfo();
test.getInfo();
}
}
输出结果:
input number type:int/ value:22.0
out number type:int/ value:22
input number type:float/ value:22.219999313354492
out number type:float/ value:22.22
input number type:double/ value:22.22
out number type:double/ value:22.22
input number type:long/ value:22.0
out number type:long/ value:22
结论: 面向 Number 接口的编程,加上数字类型的转换,实现了数据集合,可以输入任意数字类型。
报告 4 :如何面向接口编程
网上有很多人在谈论面向接口编程,但是没有很详细,说出真正使用接口的价值。
经过分析 jfreechart 可以清晰的获得,面向接口编程的特点。
例如 :jfeechart 中绘制圆饼图,使用数据集合的定义如下:
//PieDataset 是一个接口
//DefaultPieDataset 是一个实现 PieDataset 接口的实体类
private PieDataset createDataset() {
DefaultPieDataset dataset = new DefaultPieDataset();
dataset.setValue("One", 10;
return dataset;
}
// 后续操作都在使用 PieDataset 对象
分析 :代码中可以看到数据集实例化的时候,使用的是 DefaultPieDataset 类,但是返回的是一个接口 PieDataset ,在传递和调用的时候,都使用的是接口 PieDataset 对象,但是当操作时候,对象实际调用的是实体类的 DefaultPieDataset 对象 , 在 Jfreechart 源码中,如果要使用链表,那么就传递 List ,如果要使用数字,那么就传递 Number ,如果要使用 String ,那么就传递 Comparable ,这些都是面向接口编程的体现。
优点 :面向接口和抽象类的编程,可以使程序变的很灵活,在程序传递对象过程中,都使用的是接口和抽象类,如果实现这些接口的实体类,发生修改变化,可以直接修改这些实体类,其他调用这些程序的地方可以不用修改,或是很少量的修改,这样实现强内聚底偶合。
缺点 :程序的可读性能下降,对于初级程序员,很难了解程序结构。
结论 :面向接口和抽象类编程是大事所驱的,人心所向的事情,可能有人说那不一定,但是从实际编程经验来说,这是程序员必经之路,这种编程适合,很强的编程团队,这样编写的程序,可以适应用户的需求变化,改动相对很少,但是要求程序员本身素质也很高。
本文章未经过作者同意,不能转载。如有任何问题,请发送E-mail:llhdf@yahoo.com.cn