热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从C/C++与Java的语言设计看代码质量问题

历代编程语言演化,都尝试着去解决不同的附属性困难问题。从Java反省C++的诸般问题而进行改良的结果,我们可以看出它所尝试要解决的问题的困难。Java中有一个很重大的特色,就是垃圾收集机制(GarbageCollection,GC)。垃圾收集机制允许程序设计者尽管放心的去配置所需的内存空间,而毋需自行处理这些内存空间的

历代编程语言演化,都尝试着去解决不同的附属性困难问题。从Java反省C++的诸般问题而进行改良的结果,我们可以看出它所尝试要解决的问题的困难。

为什么Java要采用垃圾收集机制?

Java中有一个很重大的特色,就是垃圾收集机制(Garbage Collection,GC)。垃圾收集机制允许程序设计者尽管放心的去配置所需的内存空间,而毋需自行处理这些内存空间的释放问题,因为垃圾收集器(Garbage Collector)会自动判断已经不被程序所使用的内存空间,并且自动释放。

惯用C/C++程序语言的程序设计者都知道,自己配置的内存必须自己妥善释放,无论是没有释放或是重复释放,都会造成程序的Bug。程序设计者自己配置内存、自己释放是一种程序设计模型,而只管配置、不管释放,又是另一种程序设计模型。

Java继承了C/C++的血统,却选择了另外一种截然不同处理内存配置与释放的程序设计模型,为什么呢?在Java问世之前,垃圾收集机制已经存在,但鲜少看到十分主流的程序语言采用,原因就是在于它的效能问题。因为自动判断每一块内存区块是否该被回收及加以回收,都需要不少计算量,因而影响到程序的效能。而Java发明者决心以效能换得这个垃圾收集机制,是一个重大的决定,为什么呢?这自然是因为让程序设计者自己配置内存、自己释放的程序设计模型,存在着影响深远的问题,容易滋生出Bug。

从指针与数组来看C/C++

除了内存配置与释放的问题之外,还有许多问题长期以来困扰着C/C++的程序设计者,例如指针的问题。

指针是C/C++中十分具有威力的语法元素,运用指针可以达到许多神奇的效果,也能写出相当优雅的程序代码。指针的运用,可以说是C/C++语言中的一门艺术。但是不幸的,水能载舟亦能覆舟,指针相较于内存配置与释放的问题,更是容易成为Bug的温床。相信有足够C/C++经验的程序设计者,都能理解指标的误用、错用,十分容易引发程序的Bug,而且相当不易察觉。指针允许你指向内存的任意位置,但是一旦指向不属于应用程序可存取的内存地址范围、或是以不正确的方式解读所指向内存中的数据,就会引发严重的错误。

而数组的越位存取也是和指针类似的问题,这一类的问题,甚至可以被刻意操作,衍生成为缓冲区溢位攻击。这类的问题,只要有过足够C/C++程序设计经验的程序设计者,应当都能体会这些在程序设计过程中所可能造成的困扰。它们不仅容易造成Bug,而且所长出来的Bug有很高的比例,都会藏在程序中最隐晦的角落,让你难以发觉。

效果强与易犯错之间如何取舍?

C/C++的程序设计者在内存处理的动作上,得到极为高度的自由,但又吃尽苦头。C/C++在内存处理的程序设计模型很有威力,却也容易让程序设计者犯错,而且一旦犯了错,程序设计者必须花费数倍、甚至数十倍撰写出该错误的心力和时间,才能揪出这个错误并加以修正。这当然是一个值得思考的问题,我们是否要在一个语言中,放入一个极有威力、却容易造成程序设计者犯错的程序模型?

显然Java的发明者选择不这么做,他宁可放弃有威力的武器,也不希望这个武器在伤敌的同时,也同样伤到自己。

而这也反映Java语言在众多面向上的设计哲学,宁可削除一些看似弹性、看似有威力的语法元素,也要换取降低程序设计者因而犯错的机会。所以,Java才会得到一个 “C++ --“ 的评语。身为一个后继、流着相同血源的程序语言,却试图削减,可以想见其中一定充满着许多的反省。

所以,我们可以看见Java中取消了指针,改用参照(reference)来指向对象,没有指针指向任意内存地址的能力。一旦程序设计者做了越界的数组操作,Java的虚拟机器就会掷出异常,并且不允许执行该操作。同样的,程序设计者也无法对指向null的空参照值进行存取,一样会受到虚拟机器的控管,掷出对应的异常对象,待应用程序处理。

从生产力来看,质量才是关键

上述这几个例子,都是传统C/C++程序设计容易犯错的地方,Java从语言的根本上尝试杜绝这几类问题的发生。这些在语言上的设计,也都反映Java的基本哲学──减少程序设计者犯错的机会。

为什么Java这么重视这件事?因为如此才能大大提升软件开发时的生产力。事实上的确如此,正如前段所提的,一旦写下了一个错误,就必须花费数倍、甚至数十倍撰写出该错误的心力和时间,才能揪出这个错误并加以修正。你可以想象,这样开发对生产力会有多大的影响。

花多少时间写下程序代码或许是生产力的关键之一,但是,总共花多少时间得到足够质量的程序代码,才是最后所展现出来的真正生产力指针。我们可以说,Java是把生产力当做最高指导原则之一的程序语言,而它想要得到生产力的重要途径之一,就是在语言层次上尽量避免程序设计者犯错。

C和C++这两个语言中,存在不少容易让程序设计者犯错的地方,这是Java之所以要C加加之后再减减的原因。

举例来说:

int a = 3; 
int b = 1; 
if( a = b ) // if( a == b ) 
{ 
	// 执行一些动作 
} 

这样的写法无论在C或C++里都是合法的,但是,你有没有注意到,在if的条件式中,程序设计者有可能少打了一个 = 号,他原先想写下的条件式可能是 a == b,但因为疏失写成了 a = b,而这仍然是可通过编译的C/C++程序代码,它的语义从原先的若a值等于b值则条件成立,变成了将b值指派给变数a,若a在指派后的值大于0,则条件成立。

相信写过C/C++的程序设计者都可能犯下这样子的错误,而且也都能理解这样子的错单纯只是因为输入程序代码的错误,却有可能花上你许多的时间才能找到。从语法上来看,这是从C时代就具备的语法,它很强大、很有弹性,可以写出很取巧的程序代码,但是也留下了让程序设计者犯下上述错误的空间。当然,这样子的语法到了Java,已经不允许了。

你可以在C++中,找到更多更有威力、更有弹性的语法,程序设计者得以凭借来达成很厉害的效果,但是,使用它们要更小心、更谨慎、甚至需要对语言更了解,也更需要技巧,才能将它们运用地淋漓尽致,而且,一不小心,就会犯下难以修正的错误。而其中并不是难在纠正本身,而是难在找到为什么而错。

像C++中的运算子重载,基本上在Java程序语言中是没有的,而像C++中的多重继承,在Java中也仅提供多重接口的实作。从这种角度来看,你可以说Java比较弱,但这是透过刻意削减容易出错的语言元素,来减少程序设计者犯错的机会,即使语言威力变弱了、看起来不那么巧妙了、或许要用比较多的程序代码才能做到一样的事,而程序代码或许看起来很笨,但因为不容易犯错,反而可以提高生产力。

这就是Java尝试提高生产力的一个重要方向。

本文地址:http://www.nowamagic.net/librarys/veda/detail/172,欢迎访问原出处。


推荐阅读
  • 本文详细介绍了在腾讯云服务器上配置 phpMyAdmin 的方法,包括安装、配置和解决常见问题。通过这些步骤,您可以轻松地在腾讯云环境中部署并使用 phpMyAdmin。 ... [详细]
  • Python 内存管理机制详解
    本文深入探讨了Python的内存管理机制,涵盖了垃圾回收、引用计数和内存池机制。通过具体示例和专业解释,帮助读者理解Python如何高效地管理和释放内存资源。 ... [详细]
  • Appium + Java 自动化测试中处理页面空白区域点击问题
    在进行移动应用自动化测试时,有时会遇到某些页面没有返回按钮,只能通过点击空白区域返回的情况。本文将探讨如何在Appium + Java环境中有效解决此类问题,并提供详细的解决方案。 ... [详细]
  • 如何清除Chrome浏览器地址栏的特定历史记录
    在使用Chrome浏览器时,你可能会发现地址栏保存了大量浏览记录。有时你可能希望删除某些特定的历史记录而不影响其他数据。本文将详细介绍如何单独删除地址栏中的特定记录以及批量清除所有历史记录的方法。 ... [详细]
  • JavaScript 中创建对象的多种方法
    本文详细介绍了 JavaScript 中创建对象的几种常见方式,包括对象字面量、构造函数和 Object.create 方法,并提供了示例代码和属性描述符的解释。 ... [详细]
  • 本文详细介绍了如何在PHP中实现基于概率的随机抽奖功能。通过实例代码,解释了抽奖逻辑、奖品设置及结果统计的方法。适合PHP开发者参考学习。 ... [详细]
  • 本文对宋代词人朱雍的《迷神引》进行翻译和赏析,深入探讨其词作的艺术特色与情感表达。 ... [详细]
  • 本文详细介绍了优化DB2数据库性能的多种方法,涵盖统计信息更新、缓冲池调整、日志缓冲区配置、应用程序堆大小设置、排序堆参数调整、代理程序管理、锁机制优化、活动应用程序限制、页清除程序配置、I/O服务器数量设定以及编入组提交数调整等方面。通过这些技术手段,可以显著提升数据库的运行效率和响应速度。 ... [详细]
  • 利用Selenium与ChromeDriver实现豆瓣网页全屏截图
    本文介绍了一种使用Selenium和ChromeDriver结合Python代码,轻松实现对豆瓣网站进行完整页面截图的方法。该方法不仅简单易行,而且解决了新版Selenium不再支持PhantomJS的问题。 ... [详细]
  • 本文介绍如何使用PHP在WordPress中根据分类类别ID或名称获取所有相关文章,提供详细的方法和代码示例。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • 本文详细介绍了如何使用 PHP 接收并处理微信支付的回调结果,确保支付通知能够被正确接收和响应。 ... [详细]
  • 小编给大家分享一下如何移除URL中的index.php,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收 ... [详细]
  • 本文详细介绍了如何在PHP中删除数组中的指定元素、第一个元素和最后一个元素,并提供了具体的代码示例和相关函数的使用说明。 ... [详细]
  • 本文详细解析了汉字‘犐’的基本字义及其在古代文献中的应用,旨在为读者提供全面而深入的理解。 ... [详细]
author-avatar
手机用户2502884625
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有