Hello World
Spiga

Why Java Sucks and C# Rocks(4):泛型

2010-05-18 00:23 by 老赵, 10531 visits

Java 5.0和C# 2.0发布于同一年,各自添加了一个重要的特性:泛型。泛型可以让程序员针对泛化的数据类型编写相同的算法,这大大增强了两种语言的类型系统及抽象能力。不过即便是这看似相近的功能,Java和C#两者在语言实现和功能上也有很明显的区别,这甚至会形成编程方式上的不同。在这里可能需要事先打声招呼,因为在这个特定的话题上,语言和运行时的确是密不可分的,因此在这篇文章中我会涉及到相对较多的“运行平台”上的比较,而这点在整个系列中是我尽量避免的。不过您请放心,只此一次,欢迎监督。

Java的泛型:Type Erasure

Java语言里的泛型完全是由编译器实现的,JVM在这里不提供任何支持。因此Java泛型是所谓的“类型擦除(Type Erasure)式泛型”,因为代码中的类型信息在编译成bytecode之后便完全消失了,被“擦除”了。如果要说的具体一些,那便是说如下的代码:

// Java
public class MyHashMap<TKey, TValue> {
    private HashMap<TKey, TValue> m_map = new HashMap<TKey, TValue>();
    
    public TValue get(TKey key) {
        return this.m_map.get(key);
    }
    
    public void put(TKey key, TValue value) {
        this.m_map.put(key, value);
    }

    public static void main(String[] args) {
        MyHashMap<String, Integer> map = new MyHashMap<String, Integer>();
        map.put("Hello", 5);
        int i = map.get("Hello");
    }    
}

上面的代码简单地没有意义:我们开发了一个MyHashMap泛型类,封装了标准库中HashMap泛型类,并暴露出简单的get和set两个泛型方法。不过,这段代码在编译成bytecode之后其实就变成了下面的样子:

// Java
public class MyHashMap {
    private HashMap m_map = new HashMap();
    
    public Object get(Object key) {
        return this.m_map.get(key);
    }
    
    public void put(Object key, Object value) {
        this.m_map.put(key, value);
    }

    public static void main(String[] args) {
        MyHashMap map = new MyHashMap();
        map.put("Hello", 5);
        int i = (Integer)map.get("Hello");
    }    
}

事实上,这两段代码可以说是等价的。那么编译器在这里做了哪些事情呢?首先,它把标准库中的HashMap还原成本来面目:键和值都是Object类型的容器。同时,我们编写的MyHashMap类的泛型信息也消失了。最后,在使用MyHashMap的地方编译器为我们添加了类型转化的代码。这种做法的确在代码层面保证了类型安全,不过在运行时层面上和以前没有任何区别。

Type Erasure的缺点

有人说,如何实现有什么大不了的,只要Java语言也实现了和C#一样的泛型不就行了么。只可惜,Java语言在实际上带来了许多限制。如果您是一个C#开发人员,可能很难想象以下Java代码都是不合法的:

// Java
public class MyClass<E> {
    public static void myMethod(Object item) {
        if (item instanceof E) { // Compiler error 
            ...
        }
        E item2 = new E(); // Compiler error 
        E[] iArray = new E[10]; // Compiler error 
    }
}

由于JVM不提供对泛型的支持,因此对于JVM上支持泛型的语言,如Scala,这方面的压力就完全落在编译器身上了。而且,由于这些语言以JVM为底,Type Erasure会影响JVM平台上几乎所有语言。以Scala为例,它的模式匹配语法可以用来判断一个变量的类型:

// Scala
value match {
    case x:String => println("Value is a String")
    case x:HashMap[String, Int] => println("Value is HashMap[String, Int]")
    case _ => println("Value is not a String or HashMap[String, Int]")
}

猜猜看,如果value变量是个HashMap[Int, Object]类型的对象,上面的代码会输出什么结果呢?由于JVM的Type Erasure特性,以上代码输出的却是“Value is HashMap[String, Int]”。这是因为在运行期间JVM并不包含泛型的类型信息,HashMap[K, V]即是HashMap,无论HashMap[String, Int]还是HashMap[Int, Object]都是HashMap,JVM无法判断不同泛型类型的集合之间有什么区别。不过还好,Scala编译器遇到这种情况会发出警告,程序员可以了解这些代码可能会出现的“误会”,一定程度上避免了违反程序员直觉的情况发生。

但是Java的泛型实现相对于C#来说更明显的区别可能是在性能上。.NET 2.0引入了泛型之后,带来的显著优势之一便是性能上的提高。因为在写一些容器类,如List<T>,Dictionary<TKey, TValue>的时候,无须像Java平台里那样不断的拆箱装箱,这方面真正的泛型容器无疑具有性能优势。这篇文章便进行了这方面的讨论和比较。在评论中有人说,这方面可以通过使用特定类型的容器,如IntFloatHashMap来改进性能。但显然,这除了引入更多代码造成复杂度的提高之外,更加丧失了“泛型”本身的最大优势:抽象能力、泛化能力。试想,我们又该如何为不同的非泛型容器统一增加一些处理方法呢?而在.NET中,我们只要针对Dictionary<TKey, TValue>写通用的代码即可,运行时会为我们生成最优化的执行代码

之前我也谈到过,使用值类型在某些场景下——如并行计算时,对性能的影响十分显著。这方面JVM多核计算的专家Dr. Cliff Click也表达过类似的观点,您可以在他的文章中搜索“Value Types”相关的内容。不过,这更像是前一篇谈Java基础类型时该讨论的问题,现在权当一个补充吧。

C#与Java的常见编程方式

在C#中,我们时常会写一些这样的辅助方法:

// C#
public static class Retriever
{
    public static T TryGet<T>(IDictionary<string, object> dict, string key, T defaults)
    {
        object value;
        if (dict.TryGetValue(key, out value) && value is T)
        {
            return (T)value; 
        }
        else
        {
            return defaults;
        }
    }
}

由于.NET 2.0在运行时层面上对泛型提供了支持,因此事实上TryGet方法在调用时,泛型类型T也是方法体内获得的信息之一。于是,我们便可以在C#中便可以判断一个对象的类型是不是T。那么上面这代码可以如何使用呢?

// C#
var dict = new Dictionary<string, object>();

int intValue = Retriever.TryGet(dict, "UserID", 0);
string userName = Retriever.TryGet(dict, "UserName", "");

这个辅助方法常用于与JSON的互操作中。例如客户端传递过来一个JSON字符串,我们只能将其反序列成“字符串到Object类型的映射”,因为在C#或Java这种强类型语言中,我们只有这样才能统一数字、时间或是布尔值等多种类型。这使我们在获取值的时候,必须不断和“类型”打交道。还好,我们在TryGet里封装了“尝试获取”、“判断类型”、“返回默认值”等逻辑,便可以让代码变得简洁优雅了许多(只可惜现在还在谈C# 2.0,如果有了3.0的扩展方法之后会更漂亮)。

当然,这方面还是动态语言的优势比较明显。当然,C# 4.0的动态支持在这方面也可以大显神威——不过这是后话,暂且按下不表。

同样,在Java中我们无法创建泛型类型的数组:

// Java
public static <T> T[] convert(List<T> list) {
    T[] array = new T[list.size()]; // Compiler error
    ...
}

为了创建数组,我们必须将元素的类型(类似于.NET中的Type对象)作为方法的参数传进去:

// Java
public static <T> T[] convert(List<T> list, Class<T> componentType) {
    T[] array = (T[])Array.newInstance(componentType, list.size());
    ...
}

于是在使用时:

// Java
List<Integer> list = ...
Integer[] array = convert(list, Integer.class);

对于我这种习惯写C#代码的人来说,这又何必这么麻烦呢?幸运的是,在Java语言中,Class本身可以进行泛型约束,这样我们至少可以保证传入的Class对象和list的元素是相同类型的(否则无法编译通过)。这样的麻烦之处还有许多,例如最近我写的项目中有一个类似于克隆对象的方法,假设现也在Java中实现一下吧:

// Java
public static <T> T clone(T entity) {
    T copy = new T(); // Compiler error
    ...
}

只可惜我们无法这样创建一个泛型对象,我们最多只能这么做:

// Java
public static <T> T clone(T entity) throws Exception {
    T copy = (T)type.newInstance();
    ...
}

那么在C#中呢?我们完全可以添加针对构造函数的“泛型约束”来实现优雅高效(避免了反射)的代码:

// C#
public static T Clone<T>(T entity) where T : new()
{
    T copy = new T();
    ...
}

不过在这里,我认为更重要的一点是,一但添加了泛型约束,用户便必须传入一个拥有默认构造函数的类型作为泛型参数,否则无法编译通过。这点在Java语言中并没有类似的东西,这意味着如果传入的类型不包含默认构造函数的话,就只能在运行时由newInstance方法抛出异常了。

事实上,在Java中“显示”传入类型参数的做法,不仅仅是冗余和麻烦,我认为这也会导致一些API设计上的问题。我在想会不会有这种情况,例如某个泛型方法,它在v1.0中的实现不需要从调用折那里得到一个类型信息,但是在v2.0的开发过程中,API的编写者忽然发现这个方法需要得到泛型类型的具信息才能进行功能上的改进——那么这时能否加上额外的参数呢?当然不行,这样就破坏了公开的API,会造成不兼容的情况出现。这实在是种难以两全的做法。

关于Java的Type Erasure特性,以及基于C#与.NET中泛型特性的常见编程模式(如泛型类型字典),在我之前的文章中也有过讨论,您可以将其(以及评论)作为本文的补充。

相关文章

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

82 条回复

  1. roy_hu
    199.111.222.*
    链接

    roy_hu 2010-05-18 03:32:58

    C#的泛型是不是F#作者Don Syme设计的?

  2. Snake
    120.42.197.*
    链接

    Snake 2010-05-18 09:06:03

    借此机会了解一下JAVA:-)

  3. 老赵
    admin
    链接

    老赵 2010-05-18 09:23:29

    @roy_hu

    嗯,Don Syme是主要设计者。

  4. 链接

    yiliang053674 2010-05-18 09:35:39

    作为一个C#er,由于各种原因要成为javaer,会不会很失败。

  5. _龙猫
    124.160.91.*
    链接

    _龙猫 2010-05-18 09:51:06

    Java这个做法看起来是有点偷懒的嫌疑。

  6. 老赵
    admin
    链接

    老赵 2010-05-18 10:02:23

    @_龙猫

    肯定不会是偷懒,而是权衡的结果。我以前认为是兼容方面的考虑,不过有牛人告诉我其实也并没有兼容。这我就不明白了,希望有高人可以指点一下。

    不过就结果来说,Java的泛型从设计和能力上,从C#或.NET的角度看来都是很不足的——更多问题我会在以后谈协变逆变时进行讨论。

  7. 老赵
    admin
    链接

    老赵 2010-05-18 10:04:09

    @yiliang053674: 作为一个C#er,由于各种原因要成为javaer,会不会很失败。

    失败不失败一般和干什么无关,和怎么干有关。就像我如果现在去写Java代码,我觉得我也不会是个失败的人。当然,我会很不爽,我会努力推动周围环境摆脱Java语言,如果推动不了那么就自己进行调整,比如换个事儿做什么的,呵呵。

  8. lee51076008
    222.82.90.*
    链接

    lee51076008 2010-05-18 11:29:56

    继续支持.......

  9. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-18 13:25:39

    我个人觉得老赵应该是一个底层的coder。目光不仅短浅,并且还特别固步自封。

    所有的事物,没有最好;只有最合适。编程语言也是一样,你觉得不行的,90%的情况下可能是不适合你的环境,另外10%是你对他不够足够的了解。

    Java作为一门编程语言来说,他可以跨平台运行,就意味着可以使用免费的linux。对于一个企业来说,就意味着可以省掉很多服务器的操作系统的license费用。

    Windows呢,从2K up 2k3,再up Server 8哪一项不要钱?

    另外,我觉得你的本意不是贬低Java。而是凤姐作风,引来围观吧?

  10. norm
    207.46.55.*
    链接

    norm 2010-05-18 13:51:10

    @架构之美

    请问.net为何不能在linux上跑?

  11. norm
    207.46.55.*
    链接

    norm 2010-05-18 14:03:28

    @架构之美

    另外我觉得你是个回帖不看贴的人,老赵这里关注的是语言本身。

  12. 老赵
    admin
    链接

    老赵 2010-05-18 14:04:13

    @架构之美

    全在说套话,没点新意,我估计你连操作系统的License价格都没有去了解过,我是做过Web 2.0项目的,做过了解和比较的,知道哪些贵哪些不贵。如果你真的觉得Java语言适合哪些环境,那么就具体说说?

    你说Java作为编程语言用就可以跨平台运行,那么为什么不可以去用Scala?我的目的写得那么明白:希望Java程序员转向Scala,不知道你是回帖不看贴,还是真的看不懂——还是以您的广阔的眼界还不知道有Scala这门语言吧?否则就不会连Java语言和Java平台/JVM都区分不开了。

    最后一点你也说错了,我的本意就是贬低Java,这点我毫不隐瞒。引来围观自然是需要的,否则我写给谁看?

  13. 链接

    clk_z 2010-05-18 15:26:29

    @架构之美

    如果老赵的目光短浅,不思进取,那么阁下就是鼠目寸光抑或是没有光,典型NC精锐分子。

    如果要反对请拿出真凭实据,但是从你的回复就可以看出来,你TM连文章都不看一眼就开始揣测人家的意图,你真是高瞻远瞩,心胸宽广啊!!

    引用老赵的话(大意):一个要靠.net程序员来帮你开拓视野的JAVA程序员,你是不是觉得很爽?

  14. 链接

    晓强 2010-05-18 16:08:38

    我低调几句,我是从java转向C#的,当然刚开始选java也是被人忽悠了,多多NB,多多强,微软那个.NET的鸟东西都是抄袭java的,于是乎我折腾啊折腾,折腾了N久,基于一个朴素的想法,我想做个小东西放到桌面上自己用用,Oh,My God!那速度真是惊人(就这都干号称C++的运行速度).--当时还在上学呢.后来一个偶然的机会结识了一些搞.NET的人,了解了一下C#语言,觉得语言上C#很优美,我以前在Java遇到的不爽的地方现在都爽了,于是乎格了系统装Visual Studio.

    我用C#不为别的,就因为它用着爽.我的感觉是:人在玩计算机,不是计算机在玩人.C#给我玩计算机的感觉.

  15. 老赵
    admin
    链接

    老赵 2010-05-18 16:21:54

    @晓强

    桌面应用到真不是Java的强项,这也怪不得Java语言或是Java平台。

  16. 老菜
    222.134.33.*
    链接

    老菜 2010-05-18 17:15:27

    啥人都有啊,楼上有个人本来就不懂吧,还不知道掩饰和低调,被人围攻了不爽吧。 别人围攻你,我就不点名了,同情一下弱者。 不知道你咋想的啊,啥都不懂,就敢出来回帖。回帖也就罢了,还特高调,直接敢说老赵目光短浅。你发狂也就罢了,可是连老赵的帖子你都没看(或者没看懂?),就敢口出狂言,啥人都有啊。

    先做人,再做事。你这做人风格,不敢恭维啊。你刚毕业吗?一般来说,刚毕业的人喜欢说自己精通这个,精通那个,什么都会。

  17. 链接

    装配脑袋 2010-05-18 17:30:11

    老赵这次比较怎么没有以前那么细致入微啊~ 是因为泛型涉及了CLR所以不能多说吗

  18. 老赵
    admin
    链接

    老赵 2010-05-18 18:00:26

    @装配脑袋

    有点想回避CLR的意思。关于泛型和类型系统,我以后会在结合协变逆变比较一下,脑袋觉得哪些地方可以再深入或细致一下嘛?

  19. youngz
    220.181.61.*
    链接

    youngz 2010-05-18 19:46:23

    5月的排名出炉了,java在n年后被c拉下榜首。

  20. 老赵
    admin
    链接

    老赵 2010-05-18 20:11:28

    @youngz

    上个月就这样了,不过我倒不关心这个。

  21. 横刀天笑
    125.39.108.*
    链接

    横刀天笑 2010-05-19 01:26:30

    @老赵

    对于泛型,那个《编程之魂》里貌似Anders有简单的一点说辞。

    是滴,这篇文章觉得写的不够细致,不牵扯CLR,还可以提提.Net的这种泛型具备类型推断的能力,而类型推断对后面的Linq等又是何其的有用,而Linq等几乎又带来新的编程风格...... 这个应该说说~~

  22. 老赵
    admin
    链接

    老赵 2010-05-19 09:27:56

    @横刀天笑: 是滴,这篇文章觉得写的不够细致,不牵扯CLR,还可以提提.Net的这种泛型具备类型推断的能力,而类型推断对后面的Linq等又是何其的有用,而Linq等几乎又带来新的编程风格...... 这个应该说说~~

    类型推断不是.NET的,是C#的,而且Java里也有类型推断,而且为“Java已有的功能”服务似乎已经足够了(其实从上面的代码里应该也能看的出来吧)。至于更细致的内容,自然要放到谈Lambda表达式和LINQ再说了,而且会拉上Java进行比较的。

    现在才刚刚踏入Java 5.0和C# 2.0时代,还在04-05年呢,别急,呵呵。

  23. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-19 11:10:34

    从市场占有率来讲,从大公司使用的语言来讲。java哪一项不是遥遥挺先?这年头,spring.net、nhibernate框架难道从java中移植过去的?

    java开源免费框架多如牛毛,替公司省了多少钱?

    Java语言本身确实发展有些慢,但是这并没有使java的光芒被遮盖。scale我了解得比你更多。

    Java要解决的不是for each之类的,而是一整套解决方案。Java只出标准,一般不出实现。不象ms,既当裁判又当运动员。

    光IIS和windows的漏洞就足够抛弃.net语言了。

    老赵,你继续努力,慢慢吠~

  24. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-19 11:21:35

    17.95%的份额和4.779%份额就说明了一切,群众眼睛是雪亮的。

    跟你说过多少次,Java要解决的不是foreach。

    HP、IBM、Bea、Oracle哪一个不是用java。

    没有听说Oracle要支持c#。。

    开发者大会上要讲的也只会讲Java或者与Java相关的。出去讲c#?会被人笑话的~

    招的一个.Net的程序,4年以上,多线程都不太懂。搞一个WebService异步调用,以为调用async就OK了。结果大并发情况下,服务器收到的数据全部一样。

    .Net封装的内容太多,源代码都不提供。。有啥bug在里面还不知道。

  25. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-19 11:27:27

    以后不能叫你老赵,叫你老凤就行了。喜被人围观!

    长得丑不是你的错,出来吓人就是你的不对了。

  26. 老赵
    admin
    链接

    老赵 2010-05-19 11:44:30

    @架构之美

    你既然知道有Scala这个东西,那就是在故意忽视我的观点了。我否定了Java的全部了?我否定的只是Java语言,我承认Java的生态环境很好,但你也无法因此来说明Java语言的缺点和弱势它就不是问题了。我针对的也是这点而已,我建议您先去看看我一开始的文章。

    您的逻辑也很古怪,居然用Oracle技术大会上只谈Java来说明Java比C#好。这纯粹是搞笑了,微软大会还只谈.NET不谈Java呢,这难道说明Java不如.NET?我都没有这样认为。至于语言份额之类的,比的是大环境,和我比的这个纵向方面是没有太大参考价值的。比如我以后也会Scala的优势,它在语言排行榜中占什么地方?但是它就是比Java强大,能够、也应该代替Java,排行关我什么事情。

    至于您说Hibnernate框架云云,我最乐意谈这个,因为这就是Java语言限制框架发展的最好示例,这点上面我已经谈过了。.NET方面因为C#优秀的语言特性,也出了许多开源框架,只是被您故意忽略掉了而已,而那些是Java语言方面不会有的。语言能力不够,没法移植过去。你知道.NET里面哪些是国际标准吗?你知道.NET哪些核心代码是公开的吗?

    总而言之,您是为了反驳我而反驳,我不参与这种无聊的活动。

  27. 链接

    clk_z 2010-05-19 11:46:34

    @架构之美

    典型的NC,你再牛B又如何? 老赵这一系列说过一句让你JAVA转C#了?JVM转.NET了? 人也只是比较了一下两个语言之间的优缺点,而人家也拿出事实证明了确实JAVA相对C#是落后的!

    那么你不同意你就应该拿出证据说JAVA不落后于C# 就说这个泛型吧,如果你觉得JAVA的实现更好更牛B,请你拿出事实依据,光扯理论光看什么排名有个毛用!

    明眼人都能看出来其实老赵是有一种恨铁不成钢的意思,希望JAVA更好的发展,但是JAVA却一直‘不思进取’!

    你这个SB一上来就一堆理论,连这点都看不懂,说你SB其实已经很恭维你了,不否认你是牛人,但是,更可能的是丫写代码已经把脑子写出问题了!

  28. billlo
    221.4.199.*
    链接

    billlo 2010-05-19 11:46:38

    @架构之美

    建議寫blog文反駁老趙,可以從你的觀點分析嘛. 每個語言的變更都有它身的考慮的.

  29. 老赵
    admin
    链接

    老赵 2010-05-19 11:47:52

    @billlo: 建議寫blog文反駁老趙,可以從你的觀點分析嘛. 每個語言的變更都有它身的考慮的.

    这种做法我万分支持,我也很想了解一下Java语言的设计思路,这方面我也一直有很多疑惑。

  30. 老赵
    admin
    链接

    老赵 2010-05-19 11:49:38

    @clk_z: 都能看出来其实老赵是有一种恨铁不成钢的意思,希望JAVA更好的发展,但是JAVA却一直‘不思进取’!

    类似的观点其实我已经说的很明白了,以前的文章里我也写过:Java语言让我远离Java平台,但Scala却让我有回到Java平台的冲动。我不信有谁无法理解这句话的含义。

  31. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-19 11:56:49

    @clk_z

    请注意你的用词。.net的程序员都是你这模样吗?

  32. 链接

    clk_z 2010-05-19 11:58:15

    @架构之美

    我只是说出了我自己想说的!和我是不是.NET程序员没有半毛钱关系! 那我是不是可以这样说:难道JAVA程序员的理解能力都你这样的么?

  33. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-19 11:59:08

    请问.net为何不能在linux上跑?

    请问你敢在生产环境上跑吗?

  34. 老赵
    admin
    链接

    老赵 2010-05-19 11:59:35

    楼上两位弟兄,不要纠缠用词了,双方都注意点就行了。上面两条回复我保留,以下再偏题的话就删了啊,呵呵。

  35. 架构之美
    123.129.249.*
    链接

    架构之美 2010-05-19 12:01:07

    Java有maven2非常优秀的项目管理工具,请问.Net有吗?

  36. 老赵
    admin
    链接

    老赵 2010-05-19 12:04:37

    @架构之美: 请问你敢在生产环境上跑吗?

    我2年多前就开始在生产环境上用了,现在开发的项目也有一大部分是基于mono的,希望一段时间以后有机会能让你了解到。使用mono的系统还有很多,比如Second Life之类的,都是生产环境,mono官网上都有。mono已经出现在各技术大会上了,包括微软组织的MIX10。现在社区里的项目基本都是支持mono的。说mono不成熟很正常,这是个相对的概念,但关键是要给出具体原因,否则就只是FUD。

    看我简介,我是打算推广mono的。话说我不是在组织.NET技术会议嘛,我会考虑加上这方面内容的,您感兴趣的话也欢迎到时候来交流一下。

  37. 老赵
    admin
    链接

    老赵 2010-05-19 12:08:02

    @架构之美: Java有maven2非常优秀的项目管理工具,请问.Net有吗?

    maven2是不错,我以前写.NET项目也尝试过一段时间,后来就用Team City了。这也是一个关键,你认为Java和.NET是分离的,我认为它们是合作的。看我的简介:致力于开源社区与微软平台的组合优化。

    此外,就算你举100个Java的项目出来,也无法证明Java语言不该被Scala替代。不知道我这样说你是否明白了。吃饭,回头再来讨论。

  38. zhangronghua
    218.30.165.*
    链接

    zhangronghua 2010-05-19 12:41:49

    我当时就是因为觉得C#语法比java优雅才选择的C#,话说现在c#正处于高速发展的阶段, 而java则处于一个相对稳定的阶段,抛开平台只说语言,两者已不可同日而语了。 感觉好多的评论没有分清好老赵的限定:只比较语言,不说平台。

  39. 链接

    Ivony 2010-05-19 13:55:47

    @mcpssx @老赵

    其实我觉得你们俩的争吵,有点儿鸡同鸭讲的意思。

    其实都没错,老赵不是只说语言么,莫非mcpssx你真能找出Java语言优越于C#语言的若干理由?

    当然我也认同mcpssx的观点,一个语言烂不代表就要抛弃么,Java还是有很多可圈可点之处的,甚至于,语言的评判标准都不应该是唯一的。作为中国人,我很喜欢分析语,汉语就是么,这样我们可以自由组词。要换个德国人,恐怕就会有别的观点,汉语这什么破语言,没格、没态、没……。

    从老赵的观点来说,C#比Java先进,生产力高。mcpssx就说,是先进,但生产力不一定高,先进的语言还有很多。这样,是争不出结果来的。

    总而言之,软件行业已经走过了一招鲜吃遍天的时代,没有什么程序设计语言是全能的,在平台(JVM和CLR)的协助下,几乎所有的语言都得到了几乎相同的能力。这个时候再去强调语言的占有率什么的,显得有点不合时宜。

  40. 老赵
    admin
    链接

    老赵 2010-05-19 14:04:20

    @Ivony

    因为有了平台作保证,换一门语言并不会丧失生态环境,并不会损失历史积淀,反而很容易带来生产力的提高。在平台的协助下,已经给了开发人员选择语言的空间了,所以我最近对于语言的考虑也越来越多。

  41. 链接

    ydntlk 2010-05-20 11:25:04

    其实就老赵的结论而言,还是很显然的,应该没有什么异议。但是,从下面的评论来看,其实大家更关注的其实是这两个问题:

    1. 这些更优秀的语言特性(即使是“能够改变编程思维、或是引出额外的编程范式”的语言特性)到底能在多大的程度上改变生产力?如果这种改变与库、框架和整个生态环境所带来的优势或是和学习成本相比不够明显的话,那自然就没有人会关心。

    2. 这些特性的大多数是否是真的无法用库或IDE的扩展来弥补,比如xuwenhao举的那个lambda表达式的例子。

    如果这两个问题没能得到很好的解决(尤其是第一点),无论老赵怎样强调自己的论点是什么而不是什么,都难以避免大家会这样想,“C#语言更优秀。Huh?那又怎样?”。而在这两个问题中,老赵在“比较的意义和目的”中的论述还很不够。不过,这些问题如果不是在一个真实的环境中,而仅是靠几个三、五十行的例子也确实难以说清楚。

  42. xiaoetmac
    222.66.14.*
    链接

    xiaoetmac 2010-05-20 12:25:48

    问个题外话,scala的智能提示如何获得呢~我在eclipse中用scala plugin无智能提示~~~

  43. 老赵
    admin
    链接

    老赵 2010-05-20 13:18:55

    @xiaoetmac

    不行吗?我以前用过NetBeans,记得是有提示的,eclipse不该没有才对。

  44. 老赵
    admin
    链接

    老赵 2010-05-20 13:26:25

    @ydntlk: 如果这两个问题没能得到很好的解决(尤其是第一点),无论老赵怎样强调自己的论点是什么而不是什么,都难以避免大家会这样想,“C#语言更优秀。Huh?那又怎样?”。而在这两个问题中,老赵在“比较的意义和目的”中的论述还很不够。

    我讨论的还不够吗?我觉得我该说的东西都已经说过了,哪里还不够啊。我目前没有看到过超出我论述内容的质疑,因为遇到这种情况的话,我是会修改那第一篇文章的,呵呵。

    对于学习成本和生产力提高是否合适的问题,我会讨论到的。不过我也只能摆出事实,再给出我的观点了。每个团队都有自己的的情况,比如时间,比如人员能力等等,我不可能给出统一的答案的。我可以做的其实就是保持客观。

    至于这些特性是不是能够用IDE和库弥补,以后会讨论到的。而且有一点我觉得您不需要担心:大部分特性的确是十几行代码就能看出区别来的。而我引用的每一行代码都可以说是真实环境中的。

  45. 链接

    May 2010-05-20 18:53:40

    用通俗的话说,其实就是这样:

    就算你C#和.NET再有优点又如何?只要我们只强调用Java的人多,别人就会自然而然地认为Java才是首选,然后就会有更多的人加入我们的阵营,让更多的人认为Java是首选,这样.NET就一直翻不了身。

    .NET的优点是事实上存在的,尽管它不可能在所有方面都超过Java。 然而每当谈到.NET的优点的时候,总会有人说出像是“用.NET的少,所以.NET不好”这样的话……也许.NET诞生的时间并不短了,但从.NET诞生以来就不停地被“少,所以不好”“不好,就不用”“不用,所以少”这样的一个正反馈系统所影响。

    总是想说.NET不如Java的人,应该静下来思考一下到底是自己不知不觉地进入了这个正反馈系统,还是说只是因为某种原因不想承认.NET。

    老赵可以把我上面的两条删掉吗?我刚刚才注意到不登录是不能修改的。

  46. 老赵
    admin
    链接

    老赵 2010-05-20 19:09:24

    @May

    嗯,不过其实我写这些文章也不是想证明.NET优于Java平台,只是想证明C#语言优于Java语言,并且推动别人进行Java语言到Scala语言的转变。这点我从一开始就强调,评论中更是不断强调,只可惜许多人似乎一看到在说Java坏话,就热血上涌,不管三七二十一了。

    我很无奈。

  47. 链接

    NanaLich 2010-05-20 19:29:20

    有的时候我真觉得老赵你就是存心调戏那些爱冲动的Java使用者,故意让他们感觉你是在说Java坏话——结果实际上你还不是。

    WJSNCSR系列我从刚开始准备的时候就在关注,我自然是看得出你的目的不是证明.NET和Java平台谁优谁劣,但是看看下面的评论,似乎总是有不少的人有一种被害的危机感,然后马上就跳出来强调.NET如何地无法战胜Java平台……

    总这样的话我就不得不产生这样的想给“他们”敲敲警钟的想法了。 但是怎么说呢——就好像卷进了一个跳不出的怪圈一样,不管怎么做都还是会演变变成(某种意义上的)平台之争……

  48. 链接

    NanaLich 2010-05-21 21:19:41

    xml literal并不是一个好例子,其它的地方看起来没什么问题。

  49. 链接

    xiaotie 2010-05-23 18:35:22

    这是好事啊,哈哈哈哈。用的少,竞争少。开发效率高,赚钱快。闷头数钱,多爽啊,哈哈哈哈。当然,那些客户主导的项目除外。

    .NET的优点是事实上存在的,尽管它不可能在所有方面都超过Java。然而每当谈到.NET的优点的时候,总会有人说出像是“用.NET的少,所以.NET不好”这样的话……也许.NET诞生的时间并不短了,但从.NET诞生以来就不停地被“少,所以不好”“不好,就不用”“不用,所以少”这样的一个正反馈系统所影响。

  50. Duron800
    125.39.108.*
    链接

    Duron800 2010-05-24 22:45:20

    评论多是吵架,没劲。 说说文章里的多好,var在C# 2.0里有吗?那代码是不是该改一下?

  51. 老赵
    admin
    链接

    老赵 2010-05-24 23:41:57

    @Duron800

    var是C# 3.0里的东西。这方面……还行吧,问题也不算太大,就不改了,呵呵。

  52. 一切都是界面
    59.57.229.*
    链接

    一切都是界面 2010-06-22 15:21:16

    看到我眼睛都花了,你们这讨论没完没了的,又不对重点加颜色标注啊。 建议楼主的这个回复编辑区能加不同颜色区分重点文字。

  53. 链接

    草头蕾 2010-08-10 02:28:14

    赵哥,俺顶你。我本来看文章看的很爽,看到讨论都看不下去了,有些人根本没有用过就开始贬低。 程序员怎么一副“文人相轻”的样子。老赵,无聊回复就不要理了,时间应该花在多写博客上呵呵。

  54. fyhao
    118.101.146.*
    链接

    fyhao 2010-11-22 21:13:32

    看评论看到很烦。 支持Java阵营的人用的理论都是偏搏站不住脚。 老赵的文章只比较语言特性,就在这个语言特性上,请说说Java好过C#.NET的部分吧? 别说什么Java跳到.NET的。

  55. BlueTrees
    222.70.194.*
    链接

    BlueTrees 2010-12-14 14:33:12

    老赵,你吃了那么多的C#的语法糖,会不会觉得太腻了啊!对于高性能的程序,这些语法糖会不会给开发者造成更大的困惑而不是便利呢?

  56. 老赵
    admin
    链接

    老赵 2010-12-14 15:43:11

    @BlueTrees

    为什么会腻?语法糖就是帮助开发的,知道它是怎么回事就行了,不要老是拿高性能啊高稳定性出来吓唬人……

  57. 打倒狂妄
    218.242.204.*
    链接

    打倒狂妄 2011-09-09 16:41:46

    老赵,你举出几个大公司敢用Sclala代替Java的例子,我算服你了。要么是这领导太白痴,要么是他太有魄力

  58. 老赵
    admin
    链接

    老赵 2011-09-09 23:30:02

    @打倒狂妄

    不要以为你不知道就是世界上没有,懒得和你这种人说,要例子自己去搜,我刚还翻译过一些呢,就是不找给你看。

  59. ying
    58.19.32.*
    链接

    ying 2012-11-19 21:46:03

    我觉得标题叫“Jvm sucks and Clr rocks”才合理吧,语言层面,c#基本上只是多了一些var,event之类的语法糖.都是编译器搞鬼.

    一些模式化的东西,还是java实现比较优雅

  60. 老赵
    admin
    链接

    老赵 2012-11-20 12:33:35

    @ying

    说的就是C#编译器搞鬼搞的好。什么叫做模式化?Java怎么就优雅了?就这么说吧,Java有什么模式化的东西用C#没法搞?

  61. 银剑
    218.5.1.*
    链接

    银剑 2015-01-12 16:22:33

    说实话,Java真的很繁琐! 早期刚毕业时我是同时都有接触一点.Net和Java,一开始并没什么感觉,后来就专注做Java了。 最近因为一个项目要用桌面端,所以我使用了VisualStudio来开发,虽然我的.Net基础很差,但完全做到了平滑过度,从Java转到.Net几乎就是无缝衔接,因为只需要一个VS,直接写代码,运行! 然后项目做完呢,自然就要转回老本行Java了,这时候才头大的发现,原来Java怎么这么烦,还要Tomcat还要手动配置,做个简单小项目还得去下载好几个jar包,费老大劲搭个框架,以前做这么久怎么就不觉得烦呢? 想想才悟明白一个道理:当一个人天天都干一些很烦琐的事情,干久了之后就会形成一种习惯,就像古时候的人天天都要生火来煮饭一样,回回不都是这么一条龙做么,习惯了就没什么感觉了。但是一旦哪天用了一个很称手的工具,比如用电瓷炉,不再需要生柴火了,这样用了一段时间之后,再让你回到解放前,天天生火煮饭,一定会觉得很不爽对吧,怎么就这么多事,以前咋不觉得呢。

已自动隐藏某些不合适的评论内容(主题无关,争吵谩骂,装疯卖傻等等),如需阅读,请准备好眼药水并点此登陆后查看(如登陆后仍无法浏览请留言告知)。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我