谈谈 C++ 和 Java 的区别

4 篇文章 0 订阅
我有多年的 C++ 开发经验,但是最近由于公司的关系,不得不转 Java。看了几天 Java,谈谈感想。
     经验丰富的 C++ 程序员应该可以很容易转到 Java 上来,因为他们有许多相似之处,基本语法是完全一样的,只是 Java 砍掉了大量的 C++ 特性,仅仅保留了类相关的部分,在 Java 的世界里,一切都是类。
 1. 对象 & 指针
     大部分的 Java 书籍都会告诉你,Java 是没有指针的,因为指针太过灵活,十分难用。但其实,对 C++ 程序员来说,Java 里到处都是指针!
     比如 Java 代码:


     MyObject my=new MyObject();
     MyObject my2;
     my2 = my;


     my2 和 my 指向的是同一个对象!另外,my2 可以是 Null,也可以指向其他对象, 所以,my 和 my2 其实是对象指针!Java 社区里还经常对参数到底是传值还是传引用争论不休,其实把他们看成指针,一切就都可以解释通了。当然,由于垃圾收集器的存在,所以 Java 的对象都不需要释放,所以可以看成,Java 里 new 出来的,都是智能指针。
    C++ 传递参数的时候,可以传值,传引用,传指针,C++11里还有右值引用,还可以配上 const 修饰,完全由程序员自己指定,真是太灵活了,同时也实在是太复杂了。多少初学者看着眼晕?比如对象的传值,有用吗?99%以上其实是不会这么用的,而传指针也可以完全替代传引用的功能,右值引用是为了移动对象,其实是对传值的优化。所以 Java 语言本身将它简化成了一种,这点上比C++简单多了。


2. 操作符重载
    C++ 里的操作符重载是相当灵活的一个特性,但是 Java 里由于对象其实都是指针,因此操作符重载会带来歧义,所以它很干脆完全不支持这个特性。
    从 C++ 转过来的 Java 程序员应该都写过 if( str == "Val" )... 这样的代码吧!由于没有操作符重载,而 str 其实是指针,所以这个代码在 Java 中是在做指针比较,其实 Java 要写成 if( str.equal("Val") ) ... 。个人感觉还是 C++ 的写法比较自然,特别是一些强大的库,甚至可以把其他语言用 C++ 模拟出来,就代码的表现力来说,强大不少。
    简单的说,C++ 的代码看起来就像数学公式,而 Java 看起来就是把公式用英文描述一遍。初学者也许喜欢后者,但是如果你看得懂,绝对是前者更能准确的表达作者的目的。
好比给你看一个公式 X=2Y/3 和一段文字,大部分学过数学的人应该都会喜欢公式吧。
    当然,由于 Java 语言本身的特性,操作符重载是绝对不可能出现的,所以大家都习惯了。
3. 回调函数 & Lambda 表达式
    C++中的回调函数最初是用函数指针,成员函数指针来实现的,语法古怪而难以使用,幸运的是,C++ 有许许多多有趣或者奇怪的特性,而大神们使用各种技巧,完成了对语言本身的改造。boost::function 和 bind 库的出现,重新定义了回调函数的写法,简单而优雅。
   
那么在 Java 中呢?它是用对象来模拟的,也就是先定义一个接口,然后把它给继承并实现,然后把它当回调函数来用,毕竟 Java 中一切都是对象。相当麻烦,而且限制多多,不是么?幸运的是,Java 中提供了一个语法糖,可以在 new 对象的同时定义它,这减少了部分代码,也基本实现了 Lambda 表达式的功能。顺便吐槽一下 Java 1.8 里的 Lambda, 希望它不仅仅是另一颗语法糖而已。
     Java 事件处理机制完全是通过类的继承来模拟回调的机制,要定义一个事件并发送它?ok,先定义一个事件类,然后定义一个对应的监听接口,再然后还要实现它。你看,3个文件就干了定义事件并且发送这么点事。
     其实这在很多语言都是内置机制,比如C#的委托。顺便说一句,个人感觉 C#设计得其实比 Java 好得多,可惜由于商业原因被扼杀了。
     上面说过 C++ 已经通过 function, bind 这样的类库完全实现了闭包,而通过挖掘类似语言细节,也可以写出相当方便使用的库。我写过一个 observer 的库,定义事件仅需要一句:
          OBSERVER_EVENT( MyEvent, int, std::string, long )
     而注册也只需要调用一个函数:
          observer a;
          a.subscribe<Name>( Handle );
     当事件发生时,可以通过 observer 对象来发送事件,当然也只有一个调用:
          a.shot<Name>( <Params> );
     我特意设计为强类型,编译器会帮你检查错误,参数填错是完全不可能的!如果想用弱类型的事件机制,请参考 QT。


     顺便吐槽一下 bean 关于 seter, geter 的机制,对程序员来说其实除了增加代码量基本没好处。仅仅是系统需要你就不得不输入这么多文本,还好 IDE 会帮你干这个,但是文件还是会看得你眼晕啊!


4. 类库,或者说“框架”
     Java 类库和 C++ 类库的设计哲学完全不一样。C++ 里的一个库只干一件事,比如 Boost.Asio 库的设计,就是完全只封装了网络 IO,完全没有多余的东西。而 Java 里的库追求大而全,所以一般叫“框架”,框架越大越被人推崇。看看同样处理网络的 netty 吧!


     你看,它不但包含了网络部分,同时还包括 HTTP, SSL 等一大堆东西,它已经把做 Web 服务器的所有东西都包含进去了。


     另外,为什么要叫框架?因为它的设计者已经把程序的结构也完全帮你设计好了,你只需要填入少量的代码,就能完成“框架”可以完成的功能,比如搭建一个 Web 服务器,傻瓜式编程!Java 的流行框架大多有相当清晰结构和设计。并且 Java 的框架相当多,并且得益于 Java 本身的简单。因此“快速开发”成为了 Java 成功的一大推动力,这也是 Java 成功的基础。当初 Sun 就聪明在推出 Java 的同时,同步推出了强大的 Java SDK 的类库!
     于是 Java 有了庞大的人口基数,因为几天的学习后他们就会觉得自己“无所不能”!
     值得警惕端的是,一直在框架的帮助下傻瓜式编程,对程序员的提升没什么帮助。很多工作多年的 Java 程序员,从来不问为什么,只是知道怎么做,因此极度缺乏设计的能力,因为他们从来不需要设计;完全不了解细节,因为所有的细节都被封装了;他们会缺乏探索精神,不去关心新技术,因为他们会觉得没必要。Java 的语言本身比较简单,只有 OO 一种思想,程序员也很容易养成一切都是 OO 的狭隘思维。他们会很难从 Java 里跳出来。
     
     Java “高手”很容易在某些工作超出了框架的范围后,完全抓瞎。我看的一个服务器代码,需要对其他服务器进行大量的异步 http 访问,猜猜作者怎么干的?每个 Http 开个线程!这可是工业级别的代码。它能稳定工作,而且可以快速开发完毕,不是么?至于效率,从来不在 Java 程序员的脑海里。反正效率本身不是 Java 的强项。
     程序是人写的,因此思想才是软件开发界更重要的东西。从这点上说,希望 Java 新手保持学习的态度,别满足于“我能做什么”,那都是人家帮你做好的。多想想为什么,多看看框架的源代码,真正搞清楚他们为什么要这么设计。最好能同时掌握另一门编程语言,而且最好是非 OO 的,比如 Go。
     


未完待续……
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值