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