JAVA和C++对比学习

JAVA与C++的比较网上有很多讨论。比较清晰完整的有:

http://zh.wikipedia.org/wiki/%E6%AF%94%E8%BE%83Java%E5%92%8CC%2B%2B

我无意比较哪个语言更好,只是希望总结对比一下两种语言,各自取其优点用于自己的开发中。

我认为是优点的标准是:是否能让代码更易理解,更不容易出错。至于运行效率未作为考虑因数。

1 编译与连接

1.1 导入

  • java使用import关键字直接导入目标码文件,IDE可以自动从中导出可用的接口信息
  • C++使用预处理命令导入头文件,之后才进行链接

头文件必须要作为代码连接的“门面”好好维护

1.2 文件

1.2.1 源代码

  • JAVA每个类一个文件,每个目录一个package
  • C++可以多个类一个文件

可以借鉴JAVA的package概念,以目录结构划分源代码。多用文件分割不同的类。

1.2.2

  • JAVA可直接使用和运行(只要带有mian())任何.class文件,或者打包成JAR文件
  • C++可以使用.o文件参与链接,但通常发布为静态库或动态库

需要注意维护.h文件和makefile文档说明,以免编译错误

1.3 组织

  • JAVA使用ClassLoader在运行时载入和调用
  • C++静态库在编译时写入可执行文件,动态库则在运行时通过系统调用加载和调用

每个库都提供动态和静态两种方式发布,以及足够简洁的makefile和安装脚本

2 语法特色

2.1 const

  • C++独有,可以限定指针指向的对象不可变,同时也可以限定指针本身不可变,常用于函数参数的声明,减少修改输入参数的恶劣实践
  • JAVA只有final关键字,只能限定对象的属性不可改变对象,但是其指向的对象本身是可变的

JAVA的推荐编码实践中有一条:不得修改函数参数传入的对象,以保持对象封装的完整性。如果有const修饰符就不需要靠人工来遵守了

2.2 默认参数

  • C++可以在声明函数时添加参数的默认值
  • JAVA没有办法添加默认值,只能通过方法重载,声明一堆不同参数数量的同名函数来实现

让用户可以用尽量少的参数来调用函数,是节省开发时间的重要手段,如果参数列表确实太长,考虑使用setter方法来简化对象的使用

2.3 函数指针

  • C++可以定义函数指针,并且可以放入各种STL容器
  • JAVA必须要通过定义一个Interface来声明函数的形式,然后用一个对象实现这个接口,最后把整个对象作为函数指针的载体来操作

现代脚本语言基本都有类似函数指针的设计,用以简化“回调”。JAVA的实现较为重型,需要仔细规划需要回调的模型

2.4 操作符重载

  • C++独有,可以用以实现很多特别的功能,STL容器就是一个。可以自造语法糖,非常不错。
  • JAVA只有String类的+、+=是内部重新定义过的,语法比较固定和标准

JAVA可以使用接口以及实现接口的方法,来增加更多的表意,如经典的equal()方法代替==运算符

2.5 异常

  • C++的异常可以是任何类型的数据,不强制处理

应该使用异常代替错误码返回值,而且应该通过宏功能让异常加入更多源代码信息,程序员应该强制自己处理所有的异常。

  • JAVA的异常全部是基于某个“可抛出类”,带有调用栈信息,在编译时强制处理

2.6 多线程

  • C++语言定义没有涉及多线程部分,STL也不考虑并发情况

通常并发锁是一个int或者文件,如果能与需锁对象关联起来,会让代码更易读,学习JAVA的synchonize的逻辑做法

  • JAVA语言有synchonize关键字用以锁定,标准库也有Thread类和Runable接口

3 内存管理

3.1 内存回收

  • C++可以自由选择在堆还是栈上申请内存(变量),栈上的变量会被自动回收,而且会自动调用析构函数,在堆上申请的变量,使用delete来回收内存以及调用析构函数
  • JAVA所有类对象只能new在堆上,不需要手动回收,也无法主动回收;

JAVA的对象使用起来较简单,但是没有C++的标准析构规则,对于非内存资源,需要手动关闭,要在代码文档中强调对close()方法的调用,new和close要成对使用

3.2 基本变量类型

  • C++变量类型长度不固定,有带符号和不带符号的区别

为了在32和64位机上通用,通常需要定义uint32_t之类的类型来统一长度

  • JAVA变量长度固定,全部都是带符号的

3.3 复合变量类型

  • C++中的struct实际上连续存放的内存块

利用指针运算读写结构比较容易出错或者溢出,挨个赋值虽然笨拙却较易找到问题

  • JAVA的对象内存结构比较复杂,无顺序规则

3.4 指针与句柄

  • C++拥有* & . -> []数种利用指针操作数据的手段,对于内存操作非常灵活
  • JAVA固定了基本类型只能按值传递,类对象只能按句柄(值)传递,类似某种智能指针

严格理解按值传递和句柄的理解,严防不合理的修改类对象数据

3.5 复制

  • C++拥有复制三法则,可以自己控制复制的细节

自己定义复制细节过于繁琐,而且不正确的复制容易产生“截断”属性,不如统一用clone()方法更实用

  • JAVA有默认的clone()方法,也可以自己实现clone(),hashCode(),equals()来实现细节

3.6 数组

  • C++的数组是连续内存空间

数组常用于申请一块内存供任何用途,从而缺乏对指针的控制,应该学习JAVA的数组,严格按照声明类型使用,并且小心记录自己的长度

  • JAVA数组是一种定长容器,下标溢出会有异常抛出

4 面向对象

4.1 多重继承

  • C++直接可以多重继承,因此引出了虚继承等比较复杂的概念

大部分情况下多重继承都容易让事情变得更复杂。一般来说认为委托比继承好,多写一些代码,用纯虚类继承加上委托来处理,会让耦合度降低

  • JAVA无法多重继承,必须要用接口和委托的方法来实现多重继承

4.2 覆盖

  • C++使用virtual关键字指定可覆盖方法
  • JAVA使用final关键指定不可覆盖的方法

JAVA的覆盖规则比较宽松,为了限定覆盖的扩散,应尽量收窄方法的访问权限,多用final和private,不要随便一写public

4.3 多态

  • C++使用指针或引用来实现动态绑定

C++需要额外注意需要动态绑定的时候,使用的是否引用和虚函数。

  • JAVA的类对象都是句柄,全部可以动态绑定

4.4 访问权限控制

  • C++有友元
  • JAVA的默认权限是friendly,包内可用

为了灵活划分代码的可耦合程度,必须善用“包”和friendly权限,减少public权限的内容

4.5 构造器

  • C++有初始化列表,可以在其中选择不同的基类构造函数
  • JAVA在子类构造器中假模假样的调用一下选择的基类构造器,实际上那行代码并非在那个时间被调用

JAVA缺乏明确的初始化个成员以及自己的语法,需要非常注意各属性的初始化写法,以防出现null句柄成员

4.6 反射

  • C++只能在运行时获取类型名字,无法进行进一步操作

用宏或者存储工厂函数指针的方法来实现反射,虽然麻烦但是也只能这样了

  • JAVA可以用类名和Class类执行全部的对象操作,如构造对象、调用方法

5 API与库

5.1 标准库

  • C++拥有STL库,可以完成基础的数据结构和最简单的IO任务,也有boost这个比较丰富的准标准库

统一的API库也许会丧失一定的灵活性,但是可以更好的提升代码的可读性,在学习API的使用技巧方面也能提供更大的空间

  • JAVA拥有一个包罗万象的标准库:JDK,而且发展和改进的非常快

5.2 扩展性

  • C++兼容C语言,windows和linux都是用C语言编写的软件,使用系统API时完全没有门槛
  • JAVA基本上只能用标准JDK来构造功能,另外也可以用JNI来引入本地(C语言编写)的代码

很多最时髦的操作系统功能,都不能做到跨平台,因此需要多多利用JNI功能,可以大大提高JAVA的工作效能

6 模板

6.1 运行机制

  • C++在编译时生成所有具体类的代码,在运行前已经自动生成好一批新的类
  • JAVA采用运行时动态转换类的做法处理

JAVA编译期间并未生成新的类,但应当视之为创建了新的类,不应该大量滥用,特别是和反射混搭来使用

6.2 算法基础

  • C++使用算术运算符如<来实现STL算法,需要用户重载运算符

运算符的数量和意义都比较有限,适用面比较窄,还是使用扩展纯虚基类方法来为特定算法服务比较好

  • JAVA使用equals(),compare()等接口方法来实现通用算法

最后不能免俗的总结一下:

1)编译构建部分,JAVA在易用性和规范性上完胜C++,基于VM的语言确实能让机器帮人做更多的事情

2)语法特色部分,C++从语法上实现了很多JAVA最佳实践,JAVA只在异常和多线程这类“时髦”特性上有所改进

3)内存管理各有千秋,C++更加严谨,而JAVA则更易用。C++就好像食堂吃饭,须自己交盘子,JAVA则好像饭店,有人会帮你收拾碗筷。但是JAVA如此更容易诱导程序员泄露非内存资源。

4)模板和API部分各自有优秀的地方,但是觉得模板范式C++更正宗,更能体现静态之美,JAVA只是利用动态的优势效颦了一下。

5)号称为面向对象而生的JAVA,在OO上确实得了VM动态运行的好处,但是也有很多容易诱导程序员犯错的地方,需要《最佳实践》之类的教条来自我约束。而C++则更加严格。

感谢大家的阅读,如觉得此文对你有那么一丁点的作用,麻烦动动手指转发或分享至朋友圈。如有不同意见,欢迎后台留言探讨。

原文发布于微信公众号 - 韩大(handa1740168)

原文发表时间:2016-01-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏飞雪无情的博客

编写高效的Android代码

毫无疑问,基于Android平台的设备一定是嵌入式设备。现代的手持设备不仅仅是一部电话那么简单,它还是一个小型的手持电脑,但是,即使是最快的最高端的手持设备也远...

863
来自专栏Java Web

Java 面试知识点解析(四)——版本特性篇(1)

在遨游了一番 Java Web 的世界之后,发现了自己的一些缺失,所以就着一篇深度好文:知名互联网公司校招 Java 开发岗面试知识点解析 ,来好好的对 Jav...

4016
来自专栏java一日一条

在Java中如何避免“!=null”式的判空语句?

我整天都是在跟Java打交道。我在Java开发中最常用的一段代码就是用object != null在使用对象之前判断是否为空。这么做是为了避免NullPoint...

111
来自专栏Celebi的专栏

C/C++ 学习笔记六(文件系统、预处理)

工作中经常使用到C/C++,为对C有个比较深刻的了解,重新拾起学习C的任务。在看书的同时,记录下思考的过程,也记录下重要的知识点。

850
来自专栏决胜机器学习

设计模式专题(七)——建造者模式

设计模式专题(七)——建造者模式 (原创内容,转载请注明来源,谢谢) 一、概述 建造者模式(Builder),又称生成器模式,是将一个复杂的对象的构建与它的表...

35211
来自专栏AndroidTv

谈谈你对 Java 平台的理解声明提问正文

874
来自专栏码云1024

java中的native关键字

2635
来自专栏CSDN技术头条

用 Webhook+Python+Shell 编写一套 Unix 类系统监控工具

本文来自作者 Alinx 在 GitChat 上分享 「用 Webhook+Python+Shell 编写一套 Unix 类系统监控工具」

874
来自专栏大内老A

通过内存分析工具来证明字符串驻留机制

在这之前我写过一些文章来介绍关于字符串内存分配和驻留的文章,涉及到的观点主要有:字符串的驻留机制避免了对具有相同字符序列的字符串对象的重复创建;被驻留的字符串是...

18410
来自专栏丑胖侠

Zookeeper之开源客户端ZkClient

ZkClient是由Datameer的工程师开发的开源客户端,对Zookeeper的原生API进行了包装,实现了超时重连、Watcher反复注册等功能。 ZKC...

2295

扫描关注云+社区