设为首页收藏本站language 语言切换
查看: 1635|回复: 0
收起左侧

谈谈Java1.5和.NET2.0中Generics

[复制链接]
发表于 2010-2-25 10:36:09 | 显示全部楼层 |阅读模式
<p >    Java最新的1.5SE (市场名字是J2SE 5.0,代号Tiger) 和微软的.NET 2.0现在都已经浮出水面了,.NET 2.0虽然离最后的发布还有一些日子,但是它的基本框架我们已经可以感受到了,所以对Java 1.5和.NET 2.0的Beta版进行评测还是可以比较准确地看出这两种技术的总体情况和技术特色的。今天我要讨论的是Java 1.5和.NET 2.0中Generics。<p >    Generics对于Java和.NET来说,都是非常重要的一个新的语言特色。熟悉C++中Template的朋友可能对这个概念不会陌生。从本质上来说,Generics就是使你的类型(Type)具有参数能力,即所谓的参数化类型或参数式多态性。用.NET和C# 设计师Anders Hejlsberg的话来说就是"Generics is essentially the ability to have type parameters on your type. They are also called parameterized types or parametric polymorphism."从理论上说, Generics应该具有这样四个突出的优点。<p >    <I><B>·        类型安全</B></I><BR>    举个最简单的例子来说吧。在以前的Java或是.NET中,如果我们往ArrayList里加入一个任何一种对象,ArrayList都将这个对象视为最宽泛的Object类型。在取出对象使用的时候,我们必须要先转化为相应的对象(Casting),这个类型转换操作是一个无法避免的开销,并且也是一个没有类型安全保障的操作。因为你取出的对象理论上可以是任何类型。很多情况下,我们希望某个ArrayList是用来专门存放某一种对象,比如说是String对象的。但是编译器没法保障我们的这个目的。别人可以向这个ArrayList加入任何对象。在编译的时候,编译器认为这都是合法的操作而给与编译通过。但是这样的程序在运行的时候就会出现问题。因为你从这个ArrayList里取出的不一定是String对象。你在转化为String类型的时候就会出现异常(Exception)。<p >    使用了Generics,这个问题就可以避免。比如在Java 1.5中,你可以这样使用ArrayList。<BR>    ArrayList<String> myList = new ArrayList<String>();<p >    这样的话,编译器在编译的时候就会发现一切可能的类型匹配问题。试图向这个ArrayList加入其它非String对象的操作都会被视为非法的。这样保证加入的对象一定是String 类型的。而从这个ArrayList取出的对象也一定是String类型的,你不需要再进行类型转化了。<p >    <I><B>·        二进制代码重用性</B></I><BR>    有人可能会说了,对于你上面所说的问题,不用Generics,我一样有办法解决。比如对ArryList进行包装(Wrap-up)或是从ArryList派生出一个新的类,在这个新的类中改变函数的参数类型,从而保证只有String对象可以被加入。<p >    这样做是可以的,但是问题也是非常明显的。为了String类型,你创建了一个新的类型,那么对于Integer,Double,DateTime以及用户自定义的类型呢?你对每一个类型都要创建一个新的专门的类,这是非常繁琐和容易出错的。这些新的类型功能是类似的,功能类似的函数一次又一次的被定义和实现,这是不符合面向对象编程原则的。<p >    使用Generics,这些问题就都可以避免。你的算法可以最大限度的得到重用。如果需要改动的话,那么你也只需要修改一个地方。<p >    <I><B>·        性能提高</B></I><p >    使用Generics,类型安全问题在编译的时候就决定了,而不是在运行时。另外我们还避免了类型转化的开销(Casting Overhead)以及包装和解包装的开销(Boxing and Unboxing Overhead),这使得程序性能有了很大提高。有趣的是,Java和.NET由于实现上的不同,在性能问题上有巨大的区别,后文中会详细讨论。<p >    <I><B>·        语义清晰</B></I><p >    使用Generics,我们的程序变得更清晰和明确。有潜在类型安全的问题的程序将不能被编译通过。在.NET中,我们还可以对Generics加以限制(Constraints),这可以进一步明确程序的意图和目的,减少歧义性。<p >    那么,Java和.NET的Generics实现这些承诺了吗?我们可以通过下面这个简单的程序来看个究竟。<p >    这个程序非常简单,就是事先准备三个数组,这三个数组分别存放整数,双精度浮点数和String,然后我们来将这些东西分别放入使用了Generics的Collection对象和没有使用Generics的对象中,然后再取出,看看他们到底表现如何。<p >    <B>Java 1.5 程序(使用支持Generics的NetBeans 4.0 IDE)</B><p ><img  src="http://www.hh010.com/upload_files/article/244/9_lqdxva351771.jpg"><p ><ccid_nobr><table width="400" border="1" cellspacing="0" cellpadding="2"  bordercolorlight = "black" bordercolordark = "#FFFFFF" align="center"><tr><td bgcolor="e6e6e6" class="code" ><pre><ccid_code>import java.util.LinkedList;import java.util.ArrayList;import java.util.List;import java.util.Vector;/** * @author  Jinsong Zhang */public class JavaGenerics {        private int[] m_testInt= null;    private double[] m_testDouble = null;    private String[] m_testString = null;    private int m_dataSize = 0;    private int m_loopNum = 0;     public JavaGenerics(int dataSize, int loopNum) {        this.m_dataSize = dataSize;        this.m_loopNum = loopNum;        prepareData(m_dataSize);    }        private void prepareData(int dataSize) {        m_testInt = new int[dataSize];        m_testDouble = new double[dataSize];        m_testString = new String[dataSize];        for(int i=0; i&lt;dataSize; i++){            m_testInt = i;            m_testDouble = i * 1.0;            m_testString = Double.toString(m_testDouble);        }    }     private void testIntA(){        long startTime = System.currentTimeMillis();        long totalInt = 0;        for(int num=0;num&lt;this.m_loopNum;num++){            LinkedList&lt;Integer&gt; iList = new LinkedList&lt;Integer&gt;();            for(int i=0;i&lt;m_dataSize; i++)               iList.add(m_testInt);                        for(Integer i:iList)                totalInt += i;        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Generics LinkedList Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + totalInt);    }    private void testIntB(){        long startTime = System.currentTimeMillis();        long totalInt = 0;        for(int num=0;num&lt;this.m_loopNum;num++){            List&lt;Integer&gt; iList= new ArrayList&lt;Integer&gt;();            for(int i=0;i&lt;m_dataSize; i++)               iList.add(m_testInt);                        for(Integer i:iList)                totalInt += i;        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Generics ArrayList  Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + totalInt);    }    private void testIntC(){        long startTime = System.currentTimeMillis();        long totalInt = 0;        for(int num=0;num&lt;this.m_loopNum;num++){            ArrayList iList = new ArrayList();            for(int i=0;i&lt;m_dataSize; i++)               iList.add(m_testInt);                        for(Object i:iList)                totalInt += ((Integer)i).intValue();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Regular  ArrayList  Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + totalInt);    }          private void testDoubleA(){        long startTime = System.currentTimeMillis();        double totalDouble = 0;        for(int num=0;num&lt;this.m_loopNum;num++){            LinkedList&lt;Double&gt; dList = new LinkedList&lt;Double&gt;();            for(int i=0;i&lt;m_dataSize;i++)                dList.add(m_testDouble);            for(Double d :dList)                totalDouble += d.doubleValue();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Generics LinkedList Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + totalDouble);    }        private void testDoubleB(){        long startTime = System.currentTimeMillis();        double totalDouble = 0;        for(int num=0;num&lt;this.m_loopNum;num++){            List&lt;Double&gt; dList = new ArrayList&lt;Double&gt;();            for(int i=0;i&lt;m_dataSize;i++)                dList.add(m_testDouble);            for(Double d :dList)                totalDouble += d.doubleValue();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Generics ArrayList  Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + totalDouble);    }        private void testDoubleC(){        long startTime = System.currentTimeMillis();        double totalDouble = 0;        for(int num=0;num&lt;this.m_loopNum;num++){            ArrayList dList = new ArrayList();            for(int i=0;i&lt;m_dataSize;i++)                dList.add(m_testDouble);            for(Object d :dList)                totalDouble += ((Double)d).doubleValue();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Regular  ArrayList  Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + totalDouble);    }     private void testStringA(){        long startTime = System.currentTimeMillis();        String temp = null;        for(int num=0;num&lt;this.m_loopNum;num++){                    LinkedList&lt;String&gt; sList = new LinkedList&lt;String&gt;();            for(int i=0;i&lt;m_dataSize; i++){               sList.add(m_testString);            }                       for(String s : sList)              temp = s.toUpperCase();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Generics LinkedList Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + temp);            }        private void testStringB(){        long startTime = System.currentTimeMillis();        String temp = null;        for(int num=0;num&lt;this.m_loopNum;num++){                    List&lt;String&gt; sList = new ArrayList&lt;String&gt;();            for(int i=0;i&lt;m_dataSize; i++){               sList.add(m_testString);            }                       for(String s : sList)              temp = s.toUpperCase();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Generics ArrayList  Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + temp);            }           private void testStringC(){        long startTime = System.currentTimeMillis();        String temp = null;        for(int num=0;num&lt;this.m_loopNum;num++){                    ArrayList sList = new ArrayList();            for(int i=0;i&lt;m_dataSize; i++)               sList.add(m_testString);                       for(Object s : sList)              temp = ((String)s).toUpperCase();        }        long time = System.currentTimeMillis()-startTime;                System.out.println(&quot;Using Regular  ArrayList  Takes Time: &quot; + time + &quot; millseconds. Result: &quot; + temp);            }    public static void main(String[] args) throws Exception{        if(args.length != 2){            System.out.println(&quot;Usage:JavaGenerics dataSize loopNumber &quot;);            System.exit(0);        }        int dataSize = Integer.parseInt(args[0]);        int loopNumber = Integer.parseInt(args[1]);        JavaGenerics obj = new JavaGenerics(dataSize,loopNumber);        System.out.println(&quot;\nPrimary type int test...&quot;);         obj.testIntA();        obj.testIntB();        obj.testIntC();                System.out.println(&quot;\nPrimary type double test...&quot;);         obj.testDoubleA();        obj.testDoubleB();        obj.testDoubleC();                System.out.println(&quot;\nReference type String test...&quot;);         obj.testStringA();        obj.testStringB();        obj.testStringC();    }}</ccid_code></pre></td></tr></table></ccid_nobr><p >    下一篇我们将会介绍.NET 2.0 程序(使用支持Generics的Visual Studio 2005 Beta1 IDE)。(T111)                                 <p align="center"></p></p>
您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2025-4-17 03:45 , Processed in 0.156681 second(s), 24 queries , Redis On.  

  Powered by Discuz!

  © 2001-2025 HH010.COM

快速回复 返回顶部 返回列表