C++和JAVA的区别
一、C++有而Java没有的特性
由于Java本身就是从C++衍生出来的,这里只提C++具备的特性而被Java摒弃的——
00、Java不再支持指针。这可能是C++和Java之间的最大不同。
【注】既然JAVA中不存在指针,那么也不存在->操作符。
01、Java不再支持操作符重载。
02、Java不再包含结构或者联合。在可以完全包含它们的类出现后,这些结构成为冗余部分。
03、Java不再包括预处理,也不再支持预处理指令。
04、Java不支持自动的类型转换,必须显示强制执行类型转换。
05、在Java中的代码必须封装在一个或者多个类中。
【注】因此Java中不再包含所谓的全局变量或者全局函数。
06、Java不再允许默认参数。
07、Java不支持多继承,即不允许一个子类继承多个父类。
08、虽然Java支持构造函数,但是不再支持析构函数。但是Java增加了finalize( )函数。
09、Java不再支持typedef。
10、Java中不再可能声明无符号整数。
11、Java不再支持goto语句。
12、Java不再有delete操作符。
13、Java中的<>不再重载I/O操作。
14、Java中,对象只能由引用传递,C++中对象可由值或引用传递。
二、Java有而C++没有的特性
Java中的许多特性是C++中没有的。其中最重要的三个方面是多线程、包和接口,还有其他的许多独特之处都丰富了Java编程环境。
00、多线程。Java允许两个或者多个相同的线程并发运行。这是一种在语言级支持的并发机制。C++中没有类似的机制,或者说C++采用的是单线程的体系结构。如果需要并发执行一个C++程序,必须利用操作系统的功能手工启动。虽然这两种方法都可以同时执行两个或者多个线程,但是Java的方法清楚而且便于使用。
01、C++中没有可以与Java包对应的特性。最近似的是用一个公用头文件的一组库函数。然而,在C++中构建和使用库函数与在Java中构建包和使用包是完全不同的。
02、Java的接口与C++的抽象类相似(C++中的抽象类是包括至少一个纯虚函数的类)。例如,C++的抽象类和Java的接口都不能创建实例。两者都用于指定一个子类实现的一致接口。两者之间最大的不同之处在于接口更清晰的表明了这个概念。
03、Java提供一个流线型的内存分配机制(即系统自动回收内存机制)。与C++类似,Java支持new这个关键字。但是,不支持delete关键字。当对象的最后一个引用撤销时,对象本身被自动地删除,并进行内存垃圾回收。再考虑到Java没有指针,这使得Java语言安全性能更强。
04、Java丢弃了C++的标准库,将它替换成自己的API类集合。它们功能上有相似之处,但是名字和参数有显著的不同。同时,因为所有的Java API库都是面向对象的,而C++库只有部分是,所以库例程调用的方式不同。
05、Java增强了break和continue语句以接收标记。
06、Java中的char类型是国际通用的16位Unicode字符集,所以能自动表达大多数国家的字符。这与C++中的wchar_t型相似。使用Unicode字符增强了代码的可移植性。
07、Java增加了>>>操作,完成无符号的右移。
08、除支持单行和多行的注释之外,Java增加了第三种注释方法:文档注释。文档注释以结尾。
09、Java包含一个内置的字符串类型叫做String。String在某种程度上和C++提供的标准string类很相似。当然C++中的string只有在程序中声明后方可使用,它并不是内置的类型。
三、Java和C++都具备但是不同的方面
00、Java和C++都支持布尔类型的数据,但是Java实现true和false的方式和C++不同。在C++中,true是非零值,false是零。在Java中,true and false都是预先定义好的常量,并且是一个布尔表达式能得到的唯一的两个值。虽然C++也定义了true and false ,并指定为布尔变量,但是C++自动将非零值转换为true,零值转换为false。这种情况在Java中不会出现。
01、在创建C++类时,访问说明符应用到一组声明中。而Java中,访问说明符仅应用于其限定的声明中。
02、C++支持异常处理,这与Java类似,但是在C++中无需捕捉一个被引发的异常。
四、Java和C++的区别详细介绍(对部分知识点的扩充)
00、Java的运行速度(Java最大的障碍在于速度)
解释过的Java要比C的执行速度慢上约20倍。无论什么都不能阻止Java语言进行编译。当时刚刚出现了一些准实时编译器,它们能显著加快速度。当然,我们完全有理由认为会出现适用于更多流行平台的纯固有编译器,但假若没有那些编译器,由于速度的限制,必须有些问题是Java不能解决的。
许多企业的应用开发人员非常喜爱Java的语言特性,但是在开发重要系统时,语言特性和执行效率之间的抉择往往令人伤透脑筋。在关键计算中,用户可能并不 在乎数据如何压缩或者运行的延迟关系如何设置,但是对程序的运行速度却非常重视,这使厂商将Java的编译策略开发放在了首位。现在的Java语言,其执 行方式已经不仅仅是解释执行方式了,即时编译器(JITC、just-in-time compiler)技术和原型编译技术已经被许多厂家采用,包括Sun、IBM、Oracle以及Netscape等公司在内的技术提供商正在利用这些技 术逐步提高Java的执行速度,其中IBM公司早已将Java虚拟机(JVM,JavaVirtual Machine)、操作系统和硬件的特性有机的结合在一起,非常有效地提高了Java的执行效率。
01、Java所有东西都必须置入一个类。
Java是完全面向对象的语言,它不再支持C++程序时所使用的过程式的设计方法,所有函数和变量部必须是类的一部分。除了基本数据类型(例如整型、字符型、布尔型等)之外,其他的数据对Java来说都是对象,包括数组。
对象将数据和方法结合起来,把它们封装在类中,这样每个对象都可实现自己的特点和行为。Java不存在全局函数或者全局数据。如果想获得与全局函数等价的 功能,可考虑将static方法和static数据置入一个类里。而C++允许将函数和变量定义为全局的。此外,Java中取消了C和C++中的结构和联 合、枚举这一类的东西,一切只有“类”(Class),消除了不必要的麻烦。
Java的语法其实是参照C++的语法诞生的,但是她去除了C++中的多重继承,指针,delete等难于掌握的技术,为了便于移植和安全性,java采用了纯面向对象技术,即使是主函数public static void main(String[] args){}也要放在主类中,可以看出和C++的明显区别。
02、在Java中,类定义采取几乎和C++同样的形式。
但没有标志结束的分号。没有类声明,只有类定义。
03、Java中没有作用域范围运算符“::”。
Java利用点号做所有的事情,但可以不用考虑它,因为只能在一个类里定义元素。即使那些方法定义,也必须在一个类的内部,所以根本没有必要指定作用域的范围。我们注意到的一项差异是对static方法的调用:使用ClassName.methodName()。
除此以外,package(包)的名字是用点号建立的,并能用import关键字实现C++的“#include”的一部分功能。#include并不直接映射成import,但在使用时有类似的感觉。若想使用另一个库里的类,只需使用import命令,并指定库名即可。不存在类似于预处理机的宏。
C和C++在编译过程中都有一个预编译阶段,即众所周知的预处理器。预处理器为开发人员提供了方便,但增加了编译的复杂性。Java虚拟机没有预处理器,但它提供的引入语句(import)与c十十预处理器(#include)的功能类似。(注意:只是类似而已)
04、Java中没有预处理功能的详细介绍
Java不再有#define、#include等预处理程序(Preprocessor)的功能。C++语言很重要的一个特点就是它的预处理程序。有些其他程序 语言虽然也加入了#include的功能,但是还是欠缺处理宏(Macro)的能力。#define的功能在Java中我们可以用定义常数 (constant)的方式来取代,而#include在Java中是不需要的,因为在Java中程序在执行时,会把类型数据记录在对象实体之中,我们不 需要靠一些标头文件(header file)来知道我们使用的对象或数值是属于什么数据类型。
如果你使用C++语言时,只使用预处理程序的#include和#define功能的话,那么你大概不会觉得Java这样的设计对你产生什么样的困扰,但是如果你是使用C++语言预处理程序中宏功能的高手,你可能会觉得很不方便,进而怀疑Java如此设计的意义何在。
使用预处理程序虽然可以很方便地达到许多功能,但是站在软件工程的角度上看,对整个软件的维护其实是很不利的。由于C++语言中预处理程序的功能太过强 大,厉害的程序设计高手常会自行开发一套只有自己看的懂的宏语言,一旦整个软件要交给其他人去维护,后继者很难在短时间内了解前一个人所写下的宏功能,增 加软件开发时团队工作及日后维护的困难度。
另外一点则是C++语言的编译器所看到的程序代码,其实和程序设计者看到的程序代码是不同的。程序设计者看到的是尚未经过预处理程序处理过的程序代码,而 编译器看到的则是预处理程序处理过的程序代码,一旦交给预处理程序处理的宏内容有误,编译器产生的错误信息将不会是程序设计师所预料的。而这一点自然也增 加了程序在排错时的困难度。
预处理程序的存在也造成了阅读程序的不便。如果你想使用别人已经完成的C++语言程序,那么通常你不但要阅读他所写下的文件,还必须一并查阅上文件,才能了解其程序的全貌。如果换成是Java程序,只要查看java的程序文件就够了。
05、与C++类似,Java含有一系列“主类型”(Primitive type),以实现更有效率的访问 在Java中,这些类型包括boolean,char,byte,short,int,long,float以及double.所有主类型的大小都是 固有的,且与具体的机器无关(考虑到移植的问题)。这肯定会对性能造成一定的影响,具体取决于不同的机器。对类型的检查和要求在Java里变得更苛刻。
例如:
条件表达式只能是boolean(布尔)类型,不可使用整数。
必须使用象X+Y这样的一个表达式的结果;不能仅仅用“X+Y”来实现“副作用”。
06、Java静态引用的字串会自动转换成String对象。Java和C及C++不同,没有独立的静态字符数组字串可供使用。C和C++不支持字符串变量,在C和C++程序中使用Null终止符代表字符串的结束,在Java中字符串是用类对象(string和stringBuffer)来实现的,这些类对象是Java语言的核心,用类对象实现字符串有以下几个优点:
a)在整个系统中建立字符串和访问字符串元素的方法是一致的;
b)Java字符串类是作为Java语言的一部分定义的,而不是作为外加的延伸部分;
c)Java字符串执行运行时检查,可帮助排除一些运行时发生的错误;
d)可对字符串用“+”号进行连接操作。
07、Java增添了三个右移位运算符“>>>”,具有与“逻辑”右移位运算符类似的功用,可在最末尾插入零值。“>>”则会在移位的同时插入符号位(即“算术”移位)。
08、尽管表面上类似,但与C++相比,Java数组采用的是一个颇为不同的结构,并具有独特的行为。就是说Java提供数据下标越界检查,而C++没有提供.
有一个只读的length成员,通过它可知道数组有多大。而且一旦超过数组边界,运行期检查会自动丢弃一个异常。所有数组都是在内存“堆”里创建的,我们 可将一个数组分配给另一个(只是简单地复制数组句柄)。数组标识符属于第一级对象,它的所有方法通常都适用于其他所有对象。
09、对于所有不属于主类型的对象,都只能通过new命令创建 和C++不同,Java没有相应的命令可以“在堆栈上”创建不属于主类型的对象。所有主类型都只 能在堆栈上创建,同时不使用new命令。所有主要的类都有自己的“封装(器)”类,所以能够通过new创建等价的、以内存“堆”为基础的对象(主类型数组 是一个例外:它们可象C++那样通过集合初始化进行分配,或者使用new).
10、Java中不必进行提前声明方法。
若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。
11、Java用包代替了命名空间。
由于将所有东西都置入一个类,而且由于采用了一种名为 “封装”的机制,它能针对类名进行类似于命名空间分解的操作,所以命名的问题不再进入我们的考虑之列。数据包也会在单独一个库名下收集库的组件。我们只需简单地“import“(导入)一个包,剩下的工作会由编译器自动完成。
12、被定义成类成员的对象句柄会自动初始化成null。
对基本类数据成员的初始化在Java里得到了可靠的保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)可对它们进行明确的初始化(显式 初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且对于static和非static成员来说都是固定不变 的。我们不必从外部定义static成员的存储方式,这和C++是不同的。
13、在Java里,没有象C和C++那样的指针。
用new创建一个对象的时候,会获得一个引用(或者叫句柄) 例如: Strings = new String("helloworld");
然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java引用并不一定局限于创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。
在C和C++里大量采用指针的另一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java不提供这一支持的原因)。指针通常被看作 在基本变量数组中四处移动的一种有效手段。Java允许我们以更安全的形式达到相同的目标。解决指针问题的终极方法是“固有方法”。将指针传递给方法时,通常不会带来太大的问题,因为此时没有全局函数,只有类。而且我们可传递对对象的引用。Java语言最开始声称自己“完全不采用指针!”但随着许多程序员 都质问没有指针如何工作?于是后来又声明“采用受到限制的指针”(有人管它叫隐藏了的指针)。大家可自行判断它是否“真”的是一个指针。但不管在何种情况 下,都不存在指针“算术”。
Java语言让编程者无法找到指针来直接访问内存无指针,并且增添了自动的内存管理功能,从而有效地防止了C和C++语言中指针操作失误,如野指针所造成 的系统崩溃。但也不是说Java没有指针,虚拟机内部还是使用了指针,只是外人不得使用而已。这有利于Java程序的安全。
其实,取消指针(Pointer)这样数据类型,可能会让许多熟悉C++语言的程序设计师大吃一惊。在C++语言里,灵活地运用指针是许多程序设计师的得 意之作,但是占整个除错时间最久的也是指针的问题。配合上C++对内存管理的态度,程序设计师必须要自己去追踪自己向系统要到的内存,最后确实地交还给系 统,并且在使用指针时,要小心翼翼地注意不要跨过合法的记忆空间,造成Segmentation Fault或General Protection Fault之类的问题。
Java去掉了指针类型,并不表示程序设计师在开发高级数据结构,像堆栈(stack)、队列(queue)、二元树(binarytree)时,都必须要像在传统Basic上,利用大范围的数组来自行模拟系统内存,自行建构类似指针的表示方式。
相反地,Java提供了和Lisp语言中相似的Reference类型,通过Reference去读取配置到的内存内容,可以确保不会去读取到不属于自己 的内存空间,而另一方面,程序的执行系统也可以动态地去做内存垃圾回收的工作,将没有被reference参考到的内存空间回收给系统使用。
14、Java提供了与C++类似的“构建器”(Constructor)。
如果不自己定义一个,就会获得一个默认构建器。而如果定义了一个非默认的构建器,就不会为我们自动定义默认构建器。这和C++是一样的。注意没有复制构建器,因为所有自变量都是按引用传递的(注意:而C++中对象可由值或引用传递。)
15、Java中没有“破坏器”(Destructor)。
变量不存在“作用域”的问题。一个对象的“存在时间”是由对象的存在时间决定的,并非由垃圾收集器决定。有个finalize()方法是每一个类的成员,它在某种程度上类似于C++的“破坏器(就是析构函数的使用)”。但finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文件、 套接字、端口、URL等等)。如需在一个特定的地点做某样事情,必须创建一个特殊的方法,并调用它,不能依赖finalize()。而在另一方面,C++ 中的所有对象都会(或者说“应该”)破坏,但并非Java中的所有对象都会被当作“垃圾”收集掉。由于Java不支持破坏器的概念,所以在必要的时候,必 须谨慎地创建一个清除方法。而且针对类内的基础类以及成员对象,需要明确调用所有清除方法。
16、Java具有方法“重载”机制,它的工作原理与C++函数的重载载几乎是完全相同的。
17、Java不支持默认自变量。
18、Java中没有goto语句。
Java一方面移除了Goto的功能,它采取的无条件跳转机制是“break 标签”或者“continue 标签” ,另一方面同时扩大了break和continue的功能,可以允许多层循环的break或continue。如此一来不但避免了滥用Goto的可能性,同时也保存下Goto的好处。
“可怕”的goto语句是c和C++的“遗物”,它是该语言技术上的合法部分,引用goto语句引起了程序结构的混乱,不易理解,goto语句主要用于无 条件转移子程序和多结构分支技术。鉴于以上理由,Java不提供goto语句,也不提供goto关键字和of、const关键字,使程序简洁易读。(注 意:有些书上会说java也提供goto关键字,但是不使用,我不知道以前的说法如何,你只要记住java里边没有goto这个东西就可以了。而且不能用 goto做为对象名字、引用或方法名、类名等。)
在程序语言的发展史上,Goto一直是毁誉参半的一项功能。在很多时候使用Goto可以大幅减少不必要的程序代码,但是也由于Goto可以很自由地改变程 序的流程,如果冒然地使用,更可能造成程序结构混乱的情况。一般来说,正确使用Goto的例子多出现在循环内部,想要提早结束某一层循环。在C语言中,我 们可以使用break 或contine来改变某一层循环的流程,但如果想要改变两层以上的环执行流程,不是使用Goto就是以多余的布尔(boolean)变量,配合上一串 if-then-else的判断来达成。
19、Java采用了一种单根式的分级结构,因此所有对象都是从根类Object统一继承的。
而在C++中,我们可在任何地方启动一个新的继承树,所以最后往往看到包含了大量树的“一片森林”。在Java中,我们无论如何都只有一个分级结构。尽管 这表面上看似乎造成了限制,但由于我们知道每个对象肯定至少有一个Object接口,所以往往能获得更强大的能力。C++目前似乎是唯一没有强制单根结构 的唯一一种OO(面向对象)语言。
20、Java没有模板或者参数化类型的其他形式。
它提供了一系列集合:Vector(向量),Stack(堆栈)以及Hashtable(散列表),用于容纳Object引用。利用这些集合,我们的一系列要求可得到满足。但这些集合并非是为实现象C++“标准模板库”(STL)那样的快速调用而设计的。Java 1.2中的新集合显得更加完整,但仍不具备正宗模板那样的高效率使用手段。
21、“垃圾收集”意味着在Java中出现内存漏洞的情况会少得多,但也并非完全不可能。
若调用一个用于分配存储空间的固有方法,垃圾收集器就不能对其进行跟踪监视。
然而,内存漏洞和资源漏洞多是由于编写不当的finalize()造成的,或是由于在已分配的一个块尾释放一种资源造成的(“破坏器”在此时显得特别方 便)。垃圾收集器是在C++基础上的一种极大进步,使许多编程问题消弥于无形之中。但对少数几个垃圾收集器力有不逮的问题,它却是不大适合的。但垃圾收集 器的大量优点也使这一处缺点显得微不足道。
22、Java内建了对多线程的支持。
利用一个特殊的Thread类,我们可通过继承创建一个新线程(放弃了run()方法)。若将synchronized(同步)关键字作为方法的一个类型 限制符使用,相互排斥现象会在对象这一级发生。在任何给定的时间,只有一个线程能使用一个对象的synchronized方法。在另一方面,一个 synchronized方法进入以后,它首先会“锁定”对象,防止其他任何synchronized方法再使用那个对象。只有退出了这个方法,才会将对 象“解锁”。在线程之间,我们仍然要负责实现更复杂的同步机制,方法是创建自己的“监视器”类。递归的synchronized方法可以正常运作。若线程 的优先等级相同,则时间的“分片”不能得到保证。
23、我们不是象C++那样控制声明代码块,而是将访问限定符(public,private和 protected)置入每个类成员的定义里。
Java中若未规定一个“显式”(明确的)限定符,就会默认为“友好的”(friendly)。这意味着同一个包里的其他元素也可以访问它(相当于它们都成为 C++的“friends”——朋友),但不可由包外的任何元素访问。而在C++中如果未规定就会默认为私有的private。
类——以及类内的每个方法——都有一个访问限定符,决定它是否能在文件的外部“可见”private关键字通常很少在Java中使用,因为与排斥同一个包 内其他类的访问相比,“友好的”访问通常更加有用。 然而,在多线程的环境中,对private的恰当运用是非常重要的。Java的protected 关键字意味着“可由继承者访问,亦可由包内其他元素访问”。注意Java没有与C++的protected关键字等价的元素,后者意味着“只能由继承者访 问”(以前可用“private protected”实现这个目的,但这一对关键字的组合已被取消了)
24、嵌套的类。
在C++中,对类进行嵌套有助于隐藏名称,并便于代码的组织(但C++的“命名空间”已使名称的隐藏显得多余)。Java的“封装”或“打包”概念等价于 C++的命名空间,所以不再是一个问题。Java 1.1引入了“内部类”的概念,它秘密保持指向外部类的一个句柄——创建内部类对象的时候需要用到。这意味着内部类对象也许能访问外部类对象的成员,毋需 任何条件——就好象那些成员直接隶属于内部类对象一样。这样便为回调问题提供了一个更优秀的方案——C++是用指向成员的指针解决的。(由于存在前面介绍 的那种内部类,所以Java里没有指向成员的指针。 )
25、Java不存在inline方法。
Java所有方法都是在类的主体定义的。所以用C++的眼光看,似乎所有函数都已嵌入,但实情并非如此。Java编译器也许会自行决定嵌入一个方法,但我 们对此没有更多的控制权力。在Java中,可为一个方法使用final关键字,从而“建议”进行嵌入操作。然而,嵌入函数对于C++的编译器来说也只是一 种建议。
26、Java中的继承具有与C++相同的效果,但采用的语法不同。
Java用extends关键字标志从一个基础类的继承,并用super关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然 而,Java中的super关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在C++中设定基础类的作用域,我们可访问位于分级结构较深 处的方法。亦可用super关键字调用基础类构建器。正如早先指出的那样,所有类最终都会从Object里自动继承。和C++不同,不存在明确的构建器初 始化列表。但编译器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工作。通过组合运用自动初始化以及来自 未初始化对象句柄的异常,成员的初始化可得到有效的保证。
b举例说明
public class Foo extends Bar
{
publicFoo(String msg)
{
super(msg); Calls base constructor }
public baz(int i)
{ Override
super.baz(i);
Calls base method
}
}
27、Java中的继承不会改变基础类成员的保护级别。
我们不能在Java中指定public,priv ate或者protected继承,这一点与C++是相同的。此外,在衍生类中的优先方法不能减少对基础类方法的访问。例如,假设一个成员在基础类中属于public,而我们用另一个方法代替了它,那么用于替换的方法也必须属于public(编译器会自动检查)。
28、Java提供了一个interface关键字,它的作用是创建抽象基础类的一个等价物。
在其中填充抽象方法,且没有数据成员。这样一来,对于仅仅设计成一个接口的东西,以及对于用extends关键字在现有功能基础上的扩展,两者之间便产生 了一个明显的差异。不值得用abstract关键字产生一种类似的效果,因为我们不能创建属于那个类的一个对象。一个abstract(抽象)类可包含抽 象方法(尽管并不要求在它里面包含什么东西),但它也能包含用于具体实现的代码。因此,它被限制成一个单一的继承。通过与接口联合使用,这一方案避免了对 类似于C++虚拟基础类那样的一些机制的需要。
为创建可进行“例示”(即创建一个实例)的一个interface(接口)的版本,需使用implements关键字。它的语法类似于继承的语法,如下所示:
public interface Face
{
public void smile();
} public class Baz extends Bar implements Face
{
public void smile( )
{
System.out.println("a warm smile");
}
}
29、Java中没有virtual关键字,因为所有非static方法都肯定会用到动态绑定。
在Java中,程序员不必自行决定是否使用动态绑定。C++之所以采用了virtual,是由于我们对性能进行调整的时候,可通过将其省略,从而获得执行 效率的少量提升(或者换句话说:“如果不用,就没必要为它付出代价”)。virtual经常会造成一定程度的混淆,而且获得令人不快的结果。final关 键字为性能的调整规定了一些范围——它向编译器指出这种方法不能被取代,所以它的范围可能被静态约束(而且成为嵌入状态,所以使用C++非virtual 调用的等价方式)。这些优化工作是由编译器完成的。
30、Java不提供多重继承机制(MI),至少不象C++那样做。
与protected类似,MI表面上是一个很不错的主意,但只有真正面对一个特定的设计问题时,才知道自己需要它。由于Java使用的是“单根”分级结构,所以只有在极少的场合才需要用到MI。interface关键字会帮助我们自动完成多个接口的合并工作。
C++支持多重继承,这是C++的一个特征,它允许多父类派生一个类。尽管多重继承功能很强,但使用复杂,而且会引起许多麻烦,编译程序实现它也很不容 易。Java不支持多重继承,但允许一个类继承多个接口(extends+implement),实现了C++多重继承的功能,又避免了C++中的多重继 承实现方式带来的诸多不便。
所谓的interface基本上定义了一个类的对外沟通的方法原型,以及类内部的常数,和多重继承不同之处在于interface并不会定义类方法的内容,以及类中的变量数据。
31、运行期的类型标识功能与C++极为相似。
例如,为获得与句柄X有关的信息,可使用下述代码:
X.getClass().getName();
为进行一个“类型安全”的紧缩造型,可使用: derived d = (derived)base;
这与旧式风格的C造型是一样的。编译器会自动调用动态造型机制,不要求使用额外的语法。尽管它并不象C++的“new casts”那样具有易于定位造型的优点,但Java会检查使用情况,并丢弃那些“异常”,所以它不会象C++那样允许坏造型的存在。
32、Java采取了不同的异常控制机制,因为此时已经不存在构建器。
可添加一个finally从句,强制执行特定的语句,以便进行必要的清除工作。Java中的所有异常都是从基础类Throwable里继承而来的,所以可确保我们得到的是一个通用接口。
public void f(Obj b) throws IOException
{
myresource mr = b.createResource();
try
{
mr.UseResource();
} catch(MyException e)
{ handle my exception
}
catch(Throwable e)
{
handle all other exceptions
}
finally{ mr.dispose(); special cleanup }
}
33、Java的异常规范比C++的出色得多。
Java中的异常机制用于捕获例外事件,增强系统容错能力
如代码所示:
try
{
可能产生例外的代码
} catch(exceptionType name)
其中exceptionType表示异常类型。
{ 处理 }
而C++则没有如此方便的机制。
java丢弃一个错误的异常后,不是象C++那样在运行期间调用一个函数,Java异常规范是在编译期间检查并执行的。除此以外,被取代的方法必须遵守那 一方法的基础类版本的异常规范:它们可丢弃指定的异常或者从那些异常衍生出来的其他异常。这样一来,我们最终得到的是更为“健壮”的异常控制代码。
34、Java具有方法重载的能力,但不允许运算符(操作符)重新载OperatorOverloading
String类不能用+和+=运算符连接不同的字串,而且String表达式使用自动的类型转换,但那是一种特殊的内建情况。(备注:在C++中的string是小写的)
Java不支持操作符重载。操作符重载被认为是C++的突出特征,在Java中虽然类大体上可以实现这样的功能,但操作符重载的方便性仍然丢失了不少。
Java语言不支持操作符重载是为了保持Java语言尽可能简单。 C++中使用操作符重载主要是可以使你的程序看起来更为自然。
如下面是一个程序自定义的复数类:
C++中自定义的复数类及
0pemtor Overloading class Complex
{ public: Complex(double real,double image)
{
Real_number=real; Image_number=image;
} Complex operator+(Complex&rhs)
{
Return Complex(rhs.real_number+real_number,rhs.image_number+image_,nulnbef);
}
private:
doublereal_number 实部
doublejmage_nunmber; 虚部
}
在这里,如果你使用+来作为复数的加法符号,大家都不会有疑义,但是如果你使用的是*或》这样的符号,那么别人看到你的程序之后,难保不会产生认识上的错误。这也是Operator Overloading一大问题,当大家都对运算符赋予自己的定义后,整个程序的可读性就会大受影响。Operator Overloading的存在并不是必要的,我们一样可以定义类中的方法来达到同样的目的.
35、通过事先的约定,C++中经常出现的const问题在Java里已得到了控制。
我们只能传递指向对象的句柄,本地副本永远不会为我们自动生成。若希望使用类似C++按值传递那样的技术,可调用clone(),生成自变量的一个本地副 本(尽管clone()的设计依然尚显粗糙)。根本不存在被自动调用的副本构建器。为创建一个编译期的常数值,可象下面这样编码:
static finalint = 255
static finalint B = 8 *
36、由于安全方面的原因,“应用程序”的编程与“程序片”的编程之间存在着显著的差异。 一个最明显的问题是程序片不允许我们进行磁盘的写操作,因为这样做会造成从远程站点下载的、不明来历的程序可能胡乱改写我们的磁盘。随着Java 1.1对数字签名技术的引用,这一情况已有所改观。根据数字签名,我们可确切知道一个程序片的全部作者,并验证他们是否已获得授权。Java 1.2会进一步增强程序片的能力。
37、由于Java在某些场合可能显得限制太多,所以有时不愿用它执行象直接访问硬件这样的重要任务。
Java解决这个问题的方案是“固有方法”,允许我们调用由其他语言写成的函数(目前只支持C和C++)。这样一来,我们就肯定能够解决与平台有关的问题(采用一种不可移植的形式,但那些代码随后会被隔离起来)。程序片不能调用固有方法,只有应用程序才可以。
38、Java提供对注释文档的内建支持,所以源码文件也可以包含它们自己的文档。
通过一个单独的程序,这些文档信息可以提取出来,并重新格式化成HTML。这无疑是文档管理及应用的极大进步。
39、Java包含了一些标准库,用于完成特定的任务。
C++则依靠一些非标准的、由其他厂商提供的库。这些任务包括(或不久就要包括):
a)连网
b)数据库连接(通过JDBC)
c)多线程
d)分布式对象(通过RMI和CORBA)
e)压缩
f)商贸
由于这些库简单易用,而且非常标准,所以能极大加快应用程序的开发速度。
40、Java 1.1包含了Java Beans标准,后者可创建在可视编程环境中使用的组件。
由于遵守同样的标准,所以可视组件能够在所有厂商的开发环境中使用。由于我们并不依赖一家厂商的方案进行可视组件的设计,所以组件的选择余地会加大,并可提高组件的效能。除此之外,Java Beans的设计非常简单,便于程序员理解;而那些由不同的厂商开发的专用组件框架则要求进行更深入的学习。
41、若访问Java句柄失败,就会丢弃一次异常。
这种丢弃测试并不一定要正好在使用一个句柄之前进行。根据Java的设计规范,只是说异常必须以某种形式丢弃。许多C++运行期系统也能丢弃那些由于指针错误造成的异常。
42、Java通常显得更为健壮,为此采取的手段如下:
a)对象句柄初始化成null(一个关键字)
b)句柄肯定会得到检查,并在出错时丢弃异常
c)所有数组访问都会得到检查,及时发现边界违例情况
d)自动垃圾收集,防止出现内存漏洞
e)明确、“傻瓜式”的异常控制机制
f)为多线程提供了简单的语言支持
g)对网络程序片进行字节码校验
43、自动内存管理机制
Java程序中所有的对象都是用new操作符建立在内存堆栈上,这个操作符类似于C++的new操作符。下面的语句由一个建立了一个类Read的对象,然后调用该对象的work方法:
Readr=new Read();
r.work();
语句Readr=new Read();在堆栈结构上建立了一个Read的实例。Java自动进行无用内存回收操作,不需要程序员进行删除。而c十十中必须由程序来释放内存资源 (就是通过new和delete运算符来分配和释放内存),增加了程序设计者的负担。Java中当一个对象不被再用到时,无用内存回收器将给它加上标签以 示删除。Java里无用内存回收程序是以线程方式在后台运行的,利用空闲时间工作。
C++有栈内存与堆内存两种分配方式,程序员可以根据自己的需要来选择使用哪种内存分配的方式,Java中对象只有堆分配。区别是C++中的堆分配必须程 序员手动释放,Java通过垃圾收集器自动释放。其实Java和C++的区别也主要在这里:对于一个问题,C++实现了几乎所有的解决方法,程序员可以根 据自己的需要来选择一种实现方法;而Java只提供一两种实现方法,但通常是他认为最容易用最灵活的方法。
44、Java不支持缺省函数参数,而c十十支持
在c中,代码组织在函数中,函数可以访问程序的全局变量。c十十增加了类,提供了类算法,该算法是与类相连的函数,c十十类方法与Java类方法十分相 似,然而,由于c十十仍然支持c,所以不能阻止c十十开发人员使用函数,结果函数和方法混合使用使得程序比较混乱。(#ff0000也就是说C++里边既 有方法又有函数,我认为不能作为等同的概念来把二者混为一谈。)
Java不再有函数在Java程序语言中,去掉了程序向导语言中最重要的单元--函数(Function)。如果我们以对象向导的观念来看待函数,就可以 了解函数在对象向导的概念中,是不必要的。在对象向导的程序观念里,对象的数据才是真正的主体,而处理对象数据的方法则必须依附在对象内才有意义。因此,去掉函数并不表示不再有子程序等模组化程序的概念,相反地,是利用对象中的方法来取代函数,再一次强化对向导的发展策略。
Java没有函数,作为一个比c十十更纯的面向对象的语言,Java强迫开发人员把所有例行程序包括在类中,事实上,用方法实现例行程序可激励开发人员更好地组织编码。
45、类型转换
在C和C++中有时出现数据类型的隐含转换,这就涉及了自动强制类型转换问题。例如,在c十十中可将一浮点值赋予整型变量,并去掉其尾数。Java不支持c十十中的自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。
Java是一个严格进行类型检查的程序语言,对于下面这样的程序,在C++的编译器上编译时最多只会出现警告的信息,但是在Java里则不予通过:
Int aInteger; Double aDouble=2.71828; AInteger = aDouble;
虽然这样的转型在C++里是合法的,但是也会造成数据精确度的损失。Java为了要确定写程序的人充分地了解这点,必须要程序设计强制转型(type casting),Java的编译器才会接受:
int aInteger;
doublea Double=2.71828;
aInteger=(int)aDouble;
46、对C++而言,类库一旦升级,则必须对应用程序进行重新编译,否则就无法使用升级后类库的新增功能。而Java语言在其支持的类库升级后,只需要直接覆盖上已有的类库,不需要重新编译相应的应用程序。
47、java不再有structure、union及typedef
事实上,早在C++中就可以去掉C语言中的structure和union等对复杂数据的自定结构类型,因为类(Class)的定义方式可以完全做到这项 功能。而typedef也是不必要的,一切都用类就可以了。虽然C++这样的设计是为了和C语言兼容,但是使用多余的语言特点不但不必要,而且容易造成对 程序认识的混淆。
48、和C++连接
不管Java是多么强大,总是有人需要把它和C++连接起来。因为只要有一个新的程序语言或是软件开发工具一出现,大家就会问:"它是否具有和原有程序库 连接的能力呢?"也因为C++语言在电脑界中占了很重要的地位。大家的问题其实就等于是直接问"它是否可以和C++连接?"。目前在Java中,的确提供了和C++语言连接的方法,它的做法基本上是先将C++语言所写的程序建构成动态链接函数库(DynamicLinking Library,DLL),再由Java程序去调用DLL里的函数。
这种连接的方式,使得DLL中的函数,从Java的眼光看就是一个"方法"。不过因为这种方法是直接由其他的程序语言所提供,而不是以Java语言所写的,所以它被称之为"原生方法"(NativeMethod)。由于Java Applet一些安全上的限制,所以这种连接外部程序的方法只能用在Java Application内。
49、C++的跨平台问题!
Java编译器所生成的代码可以不基于任何具体的硬件平台,而是基于一种抽象的机器---虚拟机。而c,C++的源程序要在不同平台上运行,必须重新编译。
不论是C还是C++都会有依赖平台与实现的不同比如int的大小。
由于C以及C++库功能基本都是最简化的。所以基本没法开发什么比较有用处的可移植代码.比如GUI的不同,socket实现的不同等等都制约了C++的可移植性。
如果你要写一个完全可以跨平台编译的代码,只能依靠标准库来写,那样这个程序的功能就一定非常有限.当然也有一些跨平台的库可以使用.比如GUI方面的 wxWidgets等等。
不过尽管如此.我们还是可以做一些工作来方便移植工作。不要假想平台的硬件环境,如果你要做一些对字节操作或者位操作的内容,最好注意big endian以及small endian问题不同的平台实现不同.不要假想字节长度,int的大小是32,但是不同实现里面可能有不同的长度.这依赖实现,虽然大多数的实现都使用几 乎相同的标准。尽量不要操作底层的内容 基于上面两条,我们可以得出可移植性最高的代码,应该是那些不对位或者字节进行直接操作的.不对指针内容进行修 改的,大多调用标准库函数的.不使用高级模板功能的代码。
Linux下的G++编译器对标准C++支持得很好。如果做手机游戏,要用C++,nokia需要Symbian提供的C++开发环 境,smartphone则可以用vs.net提供的。这些环境开发出来的代码,都是与平台相关的。然而如果是游戏的话想跨平台就用J2ME吧。
纯C++代码的话,跨平台十分简单,重新编译就是了。但实际上哪有纯C++的软件?C++算是较底层的语言,所以用它写软件难免要出现平台相关的东西,这就是移植时要修改的重点。
总的来说,跨平台性还是不错的。
C++的跨平台就只有两点。
a)遵循标准。特定的平台除外。
b)禁用reinterpret_cast和C风格的强制转换。
当然上边说的两点只是针对与跨编译器。但是,如果说 OS 平台,那么基本所有功能都是与平台相关的,包括网络、文件系统等显而易见的功能,以及 IO、内存分配等那么不显而易见的。要让 C++ 代码跨平台,我们只能通过包装库来掩盖不同平台的区别,这样,基于这些包装库的 C++ 程序才能在【源码级别】实现“跨平台”。
跨平台当然要注意避免使用依赖系统的操作:
a)基本类型的长度以及相对这些类型的操作,如wchar_t。
b)字符操作,特别是汉字类的宽字符。
c)IO操作
另外不同编译器对C++的实现是不同的,这就要编译一下试验一下,不过这种问题都很容易修改的!
我感觉越涉及到底层的东西,越难实现跨平台。不同的硬件体系结构,不同的编译器和编译环境,都给跨平台带来了很多的困难。如果要写出跨平台的程序,尽量使用跨平台的函数库(STL+boost),尽量避免涉及到底层的编程。
C如果涉及到跨操作系统的东西,可以使用ace,这个东西是对系统的封装的程序包。还是不错的(备注:什么是ACE?ace的全名是adaptive communication environment(可适应的通信环境),它是一个通信中间件,具有良好的可移植性;winsock只是一个socket编程的api库,仅仅提供一组api给你调用,但是ace还提供了一个性能优异的框架,也就是说,ace已经把底层的socket api包装成一个具有逻辑性的框架,你只需要按照调用规范去使用就可以获得较好的性能)
在应用表示层上做到跨平台,低层实现上或多或少都是与平台相关的。
五、C++与Java区别小总结:
事实上,constant和typedef这两条语句包含了#define语句的作用。现在,结构和联合已经被Java的类所代替。删除这些特性的原因 是:由于其希望维持与C语言的向后兼容性,C ++的语言规范包含了大量冗余。比如,类实际上就已经包括了结构和联合的作用,因此这两种数据结构完全可以取消。关于#define语句,Java语言规 范的制订者认为:尽管该语句的出发点是为了增强程序的可读性,但实际效果却恰恰相反,它常常导致难读的代码,故应该予以取消。Java不再支持独立函数,因此任何函数都必须封装到某个类中。由于人们普遍认为,C++所用的超类是非常不稳定的,因此Java抛弃了C++中的多继承并代之以接口。Java的接口指的是,在别的类看来一个类所能实现的方法。它所显示 的只是一个类的方法或常量和变量,而不是这个类的全部结构。
最后,Java还取消了C++中的GOTO语句、操作符重载、自动类型转换及指针数据类型。 GOTO语句引起的争议已经有很多年了,可一直阴魂不散,这跟某些程序员对该语句一直情有独钟有关。C++仍然支持数据类型的自动转换,但Java要求编 程人员显式实现数据类型之间的转换。自动数据类型转换使得两个数据类型互不兼容的变量可以相互赋值,而不需要给出显式说明。这有时会导致一些问题,其中最 常见的是精确度损失。比方说,如果把一个带符号的32位整数赋给一个无符号整数,则所有的结果均为正数。Java的设计者们认为这很容易引起程序错误,从 而决定不支持这种转换方式。
欢迎补充和指正!!!
由于Java本身就是从C++衍生出来的,这里只提C++具备的特性而被Java摒弃的——
00、Java不再支持指针。这可能是C++和Java之间的最大不同。
【注】既然JAVA中不存在指针,那么也不存在->操作符。
01、Java不再支持操作符重载。
02、Java不再包含结构或者联合。在可以完全包含它们的类出现后,这些结构成为冗余部分。
03、Java不再包括预处理,也不再支持预处理指令。
04、Java不支持自动的类型转换,必须显示强制执行类型转换。
05、在Java中的代码必须封装在一个或者多个类中。
【注】因此Java中不再包含所谓的全局变量或者全局函数。
06、Java不再允许默认参数。
07、Java不支持多继承,即不允许一个子类继承多个父类。
08、虽然Java支持构造函数,但是不再支持析构函数。但是Java增加了finalize( )函数。
09、Java不再支持typedef。
10、Java中不再可能声明无符号整数。
11、Java不再支持goto语句。
12、Java不再有delete操作符。
13、Java中的<>不再重载I/O操作。
14、Java中,对象只能由引用传递,C++中对象可由值或引用传递。
二、Java有而C++没有的特性
Java中的许多特性是C++中没有的。其中最重要的三个方面是多线程、包和接口,还有其他的许多独特之处都丰富了Java编程环境。
00、多线程。Java允许两个或者多个相同的线程并发运行。这是一种在语言级支持的并发机制。C++中没有类似的机制,或者说C++采用的是单线程的体系结构。如果需要并发执行一个C++程序,必须利用操作系统的功能手工启动。虽然这两种方法都可以同时执行两个或者多个线程,但是Java的方法清楚而且便于使用。
01、C++中没有可以与Java包对应的特性。最近似的是用一个公用头文件的一组库函数。然而,在C++中构建和使用库函数与在Java中构建包和使用包是完全不同的。
02、Java的接口与C++的抽象类相似(C++中的抽象类是包括至少一个纯虚函数的类)。例如,C++的抽象类和Java的接口都不能创建实例。两者都用于指定一个子类实现的一致接口。两者之间最大的不同之处在于接口更清晰的表明了这个概念。
03、Java提供一个流线型的内存分配机制(即系统自动回收内存机制)。与C++类似,Java支持new这个关键字。但是,不支持delete关键字。当对象的最后一个引用撤销时,对象本身被自动地删除,并进行内存垃圾回收。再考虑到Java没有指针,这使得Java语言安全性能更强。
04、Java丢弃了C++的标准库,将它替换成自己的API类集合。它们功能上有相似之处,但是名字和参数有显著的不同。同时,因为所有的Java API库都是面向对象的,而C++库只有部分是,所以库例程调用的方式不同。
05、Java增强了break和continue语句以接收标记。
06、Java中的char类型是国际通用的16位Unicode字符集,所以能自动表达大多数国家的字符。这与C++中的wchar_t型相似。使用Unicode字符增强了代码的可移植性。
07、Java增加了>>>操作,完成无符号的右移。
08、除支持单行和多行的注释之外,Java增加了第三种注释方法:文档注释。文档注释以结尾。
09、Java包含一个内置的字符串类型叫做String。String在某种程度上和C++提供的标准string类很相似。当然C++中的string只有在程序中声明后方可使用,它并不是内置的类型。
三、Java和C++都具备但是不同的方面
00、Java和C++都支持布尔类型的数据,但是Java实现true和false的方式和C++不同。在C++中,true是非零值,false是零。在Java中,true and false都是预先定义好的常量,并且是一个布尔表达式能得到的唯一的两个值。虽然C++也定义了true and false ,并指定为布尔变量,但是C++自动将非零值转换为true,零值转换为false。这种情况在Java中不会出现。
01、在创建C++类时,访问说明符应用到一组声明中。而Java中,访问说明符仅应用于其限定的声明中。
02、C++支持异常处理,这与Java类似,但是在C++中无需捕捉一个被引发的异常。
四、Java和C++的区别详细介绍(对部分知识点的扩充)
00、Java的运行速度(Java最大的障碍在于速度)
解释过的Java要比C的执行速度慢上约20倍。无论什么都不能阻止Java语言进行编译。当时刚刚出现了一些准实时编译器,它们能显著加快速度。当然,我们完全有理由认为会出现适用于更多流行平台的纯固有编译器,但假若没有那些编译器,由于速度的限制,必须有些问题是Java不能解决的。
许多企业的应用开发人员非常喜爱Java的语言特性,但是在开发重要系统时,语言特性和执行效率之间的抉择往往令人伤透脑筋。在关键计算中,用户可能并不 在乎数据如何压缩或者运行的延迟关系如何设置,但是对程序的运行速度却非常重视,这使厂商将Java的编译策略开发放在了首位。现在的Java语言,其执 行方式已经不仅仅是解释执行方式了,即时编译器(JITC、just-in-time compiler)技术和原型编译技术已经被许多厂家采用,包括Sun、IBM、Oracle以及Netscape等公司在内的技术提供商正在利用这些技 术逐步提高Java的执行速度,其中IBM公司早已将Java虚拟机(JVM,JavaVirtual Machine)、操作系统和硬件的特性有机的结合在一起,非常有效地提高了Java的执行效率。
01、Java所有东西都必须置入一个类。
Java是完全面向对象的语言,它不再支持C++程序时所使用的过程式的设计方法,所有函数和变量部必须是类的一部分。除了基本数据类型(例如整型、字符型、布尔型等)之外,其他的数据对Java来说都是对象,包括数组。
对象将数据和方法结合起来,把它们封装在类中,这样每个对象都可实现自己的特点和行为。Java不存在全局函数或者全局数据。如果想获得与全局函数等价的 功能,可考虑将static方法和static数据置入一个类里。而C++允许将函数和变量定义为全局的。此外,Java中取消了C和C++中的结构和联 合、枚举这一类的东西,一切只有“类”(Class),消除了不必要的麻烦。
Java的语法其实是参照C++的语法诞生的,但是她去除了C++中的多重继承,指针,delete等难于掌握的技术,为了便于移植和安全性,java采用了纯面向对象技术,即使是主函数public static void main(String[] args){}也要放在主类中,可以看出和C++的明显区别。
02、在Java中,类定义采取几乎和C++同样的形式。
但没有标志结束的分号。没有类声明,只有类定义。
03、Java中没有作用域范围运算符“::”。
Java利用点号做所有的事情,但可以不用考虑它,因为只能在一个类里定义元素。即使那些方法定义,也必须在一个类的内部,所以根本没有必要指定作用域的范围。我们注意到的一项差异是对static方法的调用:使用ClassName.methodName()。
除此以外,package(包)的名字是用点号建立的,并能用import关键字实现C++的“#include”的一部分功能。#include并不直接映射成import,但在使用时有类似的感觉。若想使用另一个库里的类,只需使用import命令,并指定库名即可。不存在类似于预处理机的宏。
C和C++在编译过程中都有一个预编译阶段,即众所周知的预处理器。预处理器为开发人员提供了方便,但增加了编译的复杂性。Java虚拟机没有预处理器,但它提供的引入语句(import)与c十十预处理器(#include)的功能类似。(注意:只是类似而已)
04、Java中没有预处理功能的详细介绍
Java不再有#define、#include等预处理程序(Preprocessor)的功能。C++语言很重要的一个特点就是它的预处理程序。有些其他程序 语言虽然也加入了#include的功能,但是还是欠缺处理宏(Macro)的能力。#define的功能在Java中我们可以用定义常数 (constant)的方式来取代,而#include在Java中是不需要的,因为在Java中程序在执行时,会把类型数据记录在对象实体之中,我们不 需要靠一些标头文件(header file)来知道我们使用的对象或数值是属于什么数据类型。
如果你使用C++语言时,只使用预处理程序的#include和#define功能的话,那么你大概不会觉得Java这样的设计对你产生什么样的困扰,但是如果你是使用C++语言预处理程序中宏功能的高手,你可能会觉得很不方便,进而怀疑Java如此设计的意义何在。
使用预处理程序虽然可以很方便地达到许多功能,但是站在软件工程的角度上看,对整个软件的维护其实是很不利的。由于C++语言中预处理程序的功能太过强 大,厉害的程序设计高手常会自行开发一套只有自己看的懂的宏语言,一旦整个软件要交给其他人去维护,后继者很难在短时间内了解前一个人所写下的宏功能,增 加软件开发时团队工作及日后维护的困难度。
另外一点则是C++语言的编译器所看到的程序代码,其实和程序设计者看到的程序代码是不同的。程序设计者看到的是尚未经过预处理程序处理过的程序代码,而 编译器看到的则是预处理程序处理过的程序代码,一旦交给预处理程序处理的宏内容有误,编译器产生的错误信息将不会是程序设计师所预料的。而这一点自然也增 加了程序在排错时的困难度。
预处理程序的存在也造成了阅读程序的不便。如果你想使用别人已经完成的C++语言程序,那么通常你不但要阅读他所写下的文件,还必须一并查阅上文件,才能了解其程序的全貌。如果换成是Java程序,只要查看java的程序文件就够了。
05、与C++类似,Java含有一系列“主类型”(Primitive type),以实现更有效率的访问 在Java中,这些类型包括boolean,char,byte,short,int,long,float以及double.所有主类型的大小都是 固有的,且与具体的机器无关(考虑到移植的问题)。这肯定会对性能造成一定的影响,具体取决于不同的机器。对类型的检查和要求在Java里变得更苛刻。
例如:
条件表达式只能是boolean(布尔)类型,不可使用整数。
必须使用象X+Y这样的一个表达式的结果;不能仅仅用“X+Y”来实现“副作用”。
06、Java静态引用的字串会自动转换成String对象。Java和C及C++不同,没有独立的静态字符数组字串可供使用。C和C++不支持字符串变量,在C和C++程序中使用Null终止符代表字符串的结束,在Java中字符串是用类对象(string和stringBuffer)来实现的,这些类对象是Java语言的核心,用类对象实现字符串有以下几个优点:
a)在整个系统中建立字符串和访问字符串元素的方法是一致的;
b)Java字符串类是作为Java语言的一部分定义的,而不是作为外加的延伸部分;
c)Java字符串执行运行时检查,可帮助排除一些运行时发生的错误;
d)可对字符串用“+”号进行连接操作。
07、Java增添了三个右移位运算符“>>>”,具有与“逻辑”右移位运算符类似的功用,可在最末尾插入零值。“>>”则会在移位的同时插入符号位(即“算术”移位)。
08、尽管表面上类似,但与C++相比,Java数组采用的是一个颇为不同的结构,并具有独特的行为。就是说Java提供数据下标越界检查,而C++没有提供.
有一个只读的length成员,通过它可知道数组有多大。而且一旦超过数组边界,运行期检查会自动丢弃一个异常。所有数组都是在内存“堆”里创建的,我们 可将一个数组分配给另一个(只是简单地复制数组句柄)。数组标识符属于第一级对象,它的所有方法通常都适用于其他所有对象。
09、对于所有不属于主类型的对象,都只能通过new命令创建 和C++不同,Java没有相应的命令可以“在堆栈上”创建不属于主类型的对象。所有主类型都只 能在堆栈上创建,同时不使用new命令。所有主要的类都有自己的“封装(器)”类,所以能够通过new创建等价的、以内存“堆”为基础的对象(主类型数组 是一个例外:它们可象C++那样通过集合初始化进行分配,或者使用new).
10、Java中不必进行提前声明方法。
若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。
11、Java用包代替了命名空间。
由于将所有东西都置入一个类,而且由于采用了一种名为 “封装”的机制,它能针对类名进行类似于命名空间分解的操作,所以命名的问题不再进入我们的考虑之列。数据包也会在单独一个库名下收集库的组件。我们只需简单地“import“(导入)一个包,剩下的工作会由编译器自动完成。
12、被定义成类成员的对象句柄会自动初始化成null。
对基本类数据成员的初始化在Java里得到了可靠的保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)可对它们进行明确的初始化(显式 初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且对于static和非static成员来说都是固定不变 的。我们不必从外部定义static成员的存储方式,这和C++是不同的。
13、在Java里,没有象C和C++那样的指针。
用new创建一个对象的时候,会获得一个引用(或者叫句柄) 例如: Strings = new String("helloworld");
然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java引用并不一定局限于创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。
在C和C++里大量采用指针的另一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java不提供这一支持的原因)。指针通常被看作 在基本变量数组中四处移动的一种有效手段。Java允许我们以更安全的形式达到相同的目标。解决指针问题的终极方法是“固有方法”。将指针传递给方法时,通常不会带来太大的问题,因为此时没有全局函数,只有类。而且我们可传递对对象的引用。Java语言最开始声称自己“完全不采用指针!”但随着许多程序员 都质问没有指针如何工作?于是后来又声明“采用受到限制的指针”(有人管它叫隐藏了的指针)。大家可自行判断它是否“真”的是一个指针。但不管在何种情况 下,都不存在指针“算术”。
Java语言让编程者无法找到指针来直接访问内存无指针,并且增添了自动的内存管理功能,从而有效地防止了C和C++语言中指针操作失误,如野指针所造成 的系统崩溃。但也不是说Java没有指针,虚拟机内部还是使用了指针,只是外人不得使用而已。这有利于Java程序的安全。
其实,取消指针(Pointer)这样数据类型,可能会让许多熟悉C++语言的程序设计师大吃一惊。在C++语言里,灵活地运用指针是许多程序设计师的得 意之作,但是占整个除错时间最久的也是指针的问题。配合上C++对内存管理的态度,程序设计师必须要自己去追踪自己向系统要到的内存,最后确实地交还给系 统,并且在使用指针时,要小心翼翼地注意不要跨过合法的记忆空间,造成Segmentation Fault或General Protection Fault之类的问题。
Java去掉了指针类型,并不表示程序设计师在开发高级数据结构,像堆栈(stack)、队列(queue)、二元树(binarytree)时,都必须要像在传统Basic上,利用大范围的数组来自行模拟系统内存,自行建构类似指针的表示方式。
相反地,Java提供了和Lisp语言中相似的Reference类型,通过Reference去读取配置到的内存内容,可以确保不会去读取到不属于自己 的内存空间,而另一方面,程序的执行系统也可以动态地去做内存垃圾回收的工作,将没有被reference参考到的内存空间回收给系统使用。
14、Java提供了与C++类似的“构建器”(Constructor)。
如果不自己定义一个,就会获得一个默认构建器。而如果定义了一个非默认的构建器,就不会为我们自动定义默认构建器。这和C++是一样的。注意没有复制构建器,因为所有自变量都是按引用传递的(注意:而C++中对象可由值或引用传递。)
15、Java中没有“破坏器”(Destructor)。
变量不存在“作用域”的问题。一个对象的“存在时间”是由对象的存在时间决定的,并非由垃圾收集器决定。有个finalize()方法是每一个类的成员,它在某种程度上类似于C++的“破坏器(就是析构函数的使用)”。但finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文件、 套接字、端口、URL等等)。如需在一个特定的地点做某样事情,必须创建一个特殊的方法,并调用它,不能依赖finalize()。而在另一方面,C++ 中的所有对象都会(或者说“应该”)破坏,但并非Java中的所有对象都会被当作“垃圾”收集掉。由于Java不支持破坏器的概念,所以在必要的时候,必 须谨慎地创建一个清除方法。而且针对类内的基础类以及成员对象,需要明确调用所有清除方法。
16、Java具有方法“重载”机制,它的工作原理与C++函数的重载载几乎是完全相同的。
17、Java不支持默认自变量。
18、Java中没有goto语句。
Java一方面移除了Goto的功能,它采取的无条件跳转机制是“break 标签”或者“continue 标签” ,另一方面同时扩大了break和continue的功能,可以允许多层循环的break或continue。如此一来不但避免了滥用Goto的可能性,同时也保存下Goto的好处。
“可怕”的goto语句是c和C++的“遗物”,它是该语言技术上的合法部分,引用goto语句引起了程序结构的混乱,不易理解,goto语句主要用于无 条件转移子程序和多结构分支技术。鉴于以上理由,Java不提供goto语句,也不提供goto关键字和of、const关键字,使程序简洁易读。(注 意:有些书上会说java也提供goto关键字,但是不使用,我不知道以前的说法如何,你只要记住java里边没有goto这个东西就可以了。而且不能用 goto做为对象名字、引用或方法名、类名等。)
在程序语言的发展史上,Goto一直是毁誉参半的一项功能。在很多时候使用Goto可以大幅减少不必要的程序代码,但是也由于Goto可以很自由地改变程 序的流程,如果冒然地使用,更可能造成程序结构混乱的情况。一般来说,正确使用Goto的例子多出现在循环内部,想要提早结束某一层循环。在C语言中,我 们可以使用break 或contine来改变某一层循环的流程,但如果想要改变两层以上的环执行流程,不是使用Goto就是以多余的布尔(boolean)变量,配合上一串 if-then-else的判断来达成。
19、Java采用了一种单根式的分级结构,因此所有对象都是从根类Object统一继承的。
而在C++中,我们可在任何地方启动一个新的继承树,所以最后往往看到包含了大量树的“一片森林”。在Java中,我们无论如何都只有一个分级结构。尽管 这表面上看似乎造成了限制,但由于我们知道每个对象肯定至少有一个Object接口,所以往往能获得更强大的能力。C++目前似乎是唯一没有强制单根结构 的唯一一种OO(面向对象)语言。
20、Java没有模板或者参数化类型的其他形式。
它提供了一系列集合:Vector(向量),Stack(堆栈)以及Hashtable(散列表),用于容纳Object引用。利用这些集合,我们的一系列要求可得到满足。但这些集合并非是为实现象C++“标准模板库”(STL)那样的快速调用而设计的。Java 1.2中的新集合显得更加完整,但仍不具备正宗模板那样的高效率使用手段。
21、“垃圾收集”意味着在Java中出现内存漏洞的情况会少得多,但也并非完全不可能。
若调用一个用于分配存储空间的固有方法,垃圾收集器就不能对其进行跟踪监视。
然而,内存漏洞和资源漏洞多是由于编写不当的finalize()造成的,或是由于在已分配的一个块尾释放一种资源造成的(“破坏器”在此时显得特别方 便)。垃圾收集器是在C++基础上的一种极大进步,使许多编程问题消弥于无形之中。但对少数几个垃圾收集器力有不逮的问题,它却是不大适合的。但垃圾收集 器的大量优点也使这一处缺点显得微不足道。
22、Java内建了对多线程的支持。
利用一个特殊的Thread类,我们可通过继承创建一个新线程(放弃了run()方法)。若将synchronized(同步)关键字作为方法的一个类型 限制符使用,相互排斥现象会在对象这一级发生。在任何给定的时间,只有一个线程能使用一个对象的synchronized方法。在另一方面,一个 synchronized方法进入以后,它首先会“锁定”对象,防止其他任何synchronized方法再使用那个对象。只有退出了这个方法,才会将对 象“解锁”。在线程之间,我们仍然要负责实现更复杂的同步机制,方法是创建自己的“监视器”类。递归的synchronized方法可以正常运作。若线程 的优先等级相同,则时间的“分片”不能得到保证。
23、我们不是象C++那样控制声明代码块,而是将访问限定符(public,private和 protected)置入每个类成员的定义里。
Java中若未规定一个“显式”(明确的)限定符,就会默认为“友好的”(friendly)。这意味着同一个包里的其他元素也可以访问它(相当于它们都成为 C++的“friends”——朋友),但不可由包外的任何元素访问。而在C++中如果未规定就会默认为私有的private。
类——以及类内的每个方法——都有一个访问限定符,决定它是否能在文件的外部“可见”private关键字通常很少在Java中使用,因为与排斥同一个包 内其他类的访问相比,“友好的”访问通常更加有用。 然而,在多线程的环境中,对private的恰当运用是非常重要的。Java的protected 关键字意味着“可由继承者访问,亦可由包内其他元素访问”。注意Java没有与C++的protected关键字等价的元素,后者意味着“只能由继承者访 问”(以前可用“private protected”实现这个目的,但这一对关键字的组合已被取消了)
24、嵌套的类。
在C++中,对类进行嵌套有助于隐藏名称,并便于代码的组织(但C++的“命名空间”已使名称的隐藏显得多余)。Java的“封装”或“打包”概念等价于 C++的命名空间,所以不再是一个问题。Java 1.1引入了“内部类”的概念,它秘密保持指向外部类的一个句柄——创建内部类对象的时候需要用到。这意味着内部类对象也许能访问外部类对象的成员,毋需 任何条件——就好象那些成员直接隶属于内部类对象一样。这样便为回调问题提供了一个更优秀的方案——C++是用指向成员的指针解决的。(由于存在前面介绍 的那种内部类,所以Java里没有指向成员的指针。 )
25、Java不存在inline方法。
Java所有方法都是在类的主体定义的。所以用C++的眼光看,似乎所有函数都已嵌入,但实情并非如此。Java编译器也许会自行决定嵌入一个方法,但我 们对此没有更多的控制权力。在Java中,可为一个方法使用final关键字,从而“建议”进行嵌入操作。然而,嵌入函数对于C++的编译器来说也只是一 种建议。
26、Java中的继承具有与C++相同的效果,但采用的语法不同。
Java用extends关键字标志从一个基础类的继承,并用super关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然 而,Java中的super关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在C++中设定基础类的作用域,我们可访问位于分级结构较深 处的方法。亦可用super关键字调用基础类构建器。正如早先指出的那样,所有类最终都会从Object里自动继承。和C++不同,不存在明确的构建器初 始化列表。但编译器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工作。通过组合运用自动初始化以及来自 未初始化对象句柄的异常,成员的初始化可得到有效的保证。
b举例说明
public class Foo extends Bar
{
publicFoo(String msg)
{
super(msg); Calls base constructor }
public baz(int i)
{ Override
super.baz(i);
Calls base method
}
}
27、Java中的继承不会改变基础类成员的保护级别。
我们不能在Java中指定public,priv ate或者protected继承,这一点与C++是相同的。此外,在衍生类中的优先方法不能减少对基础类方法的访问。例如,假设一个成员在基础类中属于public,而我们用另一个方法代替了它,那么用于替换的方法也必须属于public(编译器会自动检查)。
28、Java提供了一个interface关键字,它的作用是创建抽象基础类的一个等价物。
在其中填充抽象方法,且没有数据成员。这样一来,对于仅仅设计成一个接口的东西,以及对于用extends关键字在现有功能基础上的扩展,两者之间便产生 了一个明显的差异。不值得用abstract关键字产生一种类似的效果,因为我们不能创建属于那个类的一个对象。一个abstract(抽象)类可包含抽 象方法(尽管并不要求在它里面包含什么东西),但它也能包含用于具体实现的代码。因此,它被限制成一个单一的继承。通过与接口联合使用,这一方案避免了对 类似于C++虚拟基础类那样的一些机制的需要。
为创建可进行“例示”(即创建一个实例)的一个interface(接口)的版本,需使用implements关键字。它的语法类似于继承的语法,如下所示:
public interface Face
{
public void smile();
} public class Baz extends Bar implements Face
{
public void smile( )
{
System.out.println("a warm smile");
}
}
29、Java中没有virtual关键字,因为所有非static方法都肯定会用到动态绑定。
在Java中,程序员不必自行决定是否使用动态绑定。C++之所以采用了virtual,是由于我们对性能进行调整的时候,可通过将其省略,从而获得执行 效率的少量提升(或者换句话说:“如果不用,就没必要为它付出代价”)。virtual经常会造成一定程度的混淆,而且获得令人不快的结果。final关 键字为性能的调整规定了一些范围——它向编译器指出这种方法不能被取代,所以它的范围可能被静态约束(而且成为嵌入状态,所以使用C++非virtual 调用的等价方式)。这些优化工作是由编译器完成的。
30、Java不提供多重继承机制(MI),至少不象C++那样做。
与protected类似,MI表面上是一个很不错的主意,但只有真正面对一个特定的设计问题时,才知道自己需要它。由于Java使用的是“单根”分级结构,所以只有在极少的场合才需要用到MI。interface关键字会帮助我们自动完成多个接口的合并工作。
C++支持多重继承,这是C++的一个特征,它允许多父类派生一个类。尽管多重继承功能很强,但使用复杂,而且会引起许多麻烦,编译程序实现它也很不容 易。Java不支持多重继承,但允许一个类继承多个接口(extends+implement),实现了C++多重继承的功能,又避免了C++中的多重继 承实现方式带来的诸多不便。
所谓的interface基本上定义了一个类的对外沟通的方法原型,以及类内部的常数,和多重继承不同之处在于interface并不会定义类方法的内容,以及类中的变量数据。
31、运行期的类型标识功能与C++极为相似。
例如,为获得与句柄X有关的信息,可使用下述代码:
X.getClass().getName();
为进行一个“类型安全”的紧缩造型,可使用: derived d = (derived)base;
这与旧式风格的C造型是一样的。编译器会自动调用动态造型机制,不要求使用额外的语法。尽管它并不象C++的“new casts”那样具有易于定位造型的优点,但Java会检查使用情况,并丢弃那些“异常”,所以它不会象C++那样允许坏造型的存在。
32、Java采取了不同的异常控制机制,因为此时已经不存在构建器。
可添加一个finally从句,强制执行特定的语句,以便进行必要的清除工作。Java中的所有异常都是从基础类Throwable里继承而来的,所以可确保我们得到的是一个通用接口。
public void f(Obj b) throws IOException
{
myresource mr = b.createResource();
try
{
mr.UseResource();
} catch(MyException e)
{ handle my exception
}
catch(Throwable e)
{
handle all other exceptions
}
finally{ mr.dispose(); special cleanup }
}
33、Java的异常规范比C++的出色得多。
Java中的异常机制用于捕获例外事件,增强系统容错能力
如代码所示:
try
{
可能产生例外的代码
} catch(exceptionType name)
其中exceptionType表示异常类型。
{ 处理 }
而C++则没有如此方便的机制。
java丢弃一个错误的异常后,不是象C++那样在运行期间调用一个函数,Java异常规范是在编译期间检查并执行的。除此以外,被取代的方法必须遵守那 一方法的基础类版本的异常规范:它们可丢弃指定的异常或者从那些异常衍生出来的其他异常。这样一来,我们最终得到的是更为“健壮”的异常控制代码。
34、Java具有方法重载的能力,但不允许运算符(操作符)重新载OperatorOverloading
String类不能用+和+=运算符连接不同的字串,而且String表达式使用自动的类型转换,但那是一种特殊的内建情况。(备注:在C++中的string是小写的)
Java不支持操作符重载。操作符重载被认为是C++的突出特征,在Java中虽然类大体上可以实现这样的功能,但操作符重载的方便性仍然丢失了不少。
Java语言不支持操作符重载是为了保持Java语言尽可能简单。 C++中使用操作符重载主要是可以使你的程序看起来更为自然。
如下面是一个程序自定义的复数类:
C++中自定义的复数类及
0pemtor Overloading class Complex
{ public: Complex(double real,double image)
{
Real_number=real; Image_number=image;
} Complex operator+(Complex&rhs)
{
Return Complex(rhs.real_number+real_number,rhs.image_number+image_,nulnbef);
}
private:
doublereal_number 实部
doublejmage_nunmber; 虚部
}
在这里,如果你使用+来作为复数的加法符号,大家都不会有疑义,但是如果你使用的是*或》这样的符号,那么别人看到你的程序之后,难保不会产生认识上的错误。这也是Operator Overloading一大问题,当大家都对运算符赋予自己的定义后,整个程序的可读性就会大受影响。Operator Overloading的存在并不是必要的,我们一样可以定义类中的方法来达到同样的目的.
35、通过事先的约定,C++中经常出现的const问题在Java里已得到了控制。
我们只能传递指向对象的句柄,本地副本永远不会为我们自动生成。若希望使用类似C++按值传递那样的技术,可调用clone(),生成自变量的一个本地副 本(尽管clone()的设计依然尚显粗糙)。根本不存在被自动调用的副本构建器。为创建一个编译期的常数值,可象下面这样编码:
static finalint = 255
static finalint B = 8 *
36、由于安全方面的原因,“应用程序”的编程与“程序片”的编程之间存在着显著的差异。 一个最明显的问题是程序片不允许我们进行磁盘的写操作,因为这样做会造成从远程站点下载的、不明来历的程序可能胡乱改写我们的磁盘。随着Java 1.1对数字签名技术的引用,这一情况已有所改观。根据数字签名,我们可确切知道一个程序片的全部作者,并验证他们是否已获得授权。Java 1.2会进一步增强程序片的能力。
37、由于Java在某些场合可能显得限制太多,所以有时不愿用它执行象直接访问硬件这样的重要任务。
Java解决这个问题的方案是“固有方法”,允许我们调用由其他语言写成的函数(目前只支持C和C++)。这样一来,我们就肯定能够解决与平台有关的问题(采用一种不可移植的形式,但那些代码随后会被隔离起来)。程序片不能调用固有方法,只有应用程序才可以。
38、Java提供对注释文档的内建支持,所以源码文件也可以包含它们自己的文档。
通过一个单独的程序,这些文档信息可以提取出来,并重新格式化成HTML。这无疑是文档管理及应用的极大进步。
39、Java包含了一些标准库,用于完成特定的任务。
C++则依靠一些非标准的、由其他厂商提供的库。这些任务包括(或不久就要包括):
a)连网
b)数据库连接(通过JDBC)
c)多线程
d)分布式对象(通过RMI和CORBA)
e)压缩
f)商贸
由于这些库简单易用,而且非常标准,所以能极大加快应用程序的开发速度。
40、Java 1.1包含了Java Beans标准,后者可创建在可视编程环境中使用的组件。
由于遵守同样的标准,所以可视组件能够在所有厂商的开发环境中使用。由于我们并不依赖一家厂商的方案进行可视组件的设计,所以组件的选择余地会加大,并可提高组件的效能。除此之外,Java Beans的设计非常简单,便于程序员理解;而那些由不同的厂商开发的专用组件框架则要求进行更深入的学习。
41、若访问Java句柄失败,就会丢弃一次异常。
这种丢弃测试并不一定要正好在使用一个句柄之前进行。根据Java的设计规范,只是说异常必须以某种形式丢弃。许多C++运行期系统也能丢弃那些由于指针错误造成的异常。
42、Java通常显得更为健壮,为此采取的手段如下:
a)对象句柄初始化成null(一个关键字)
b)句柄肯定会得到检查,并在出错时丢弃异常
c)所有数组访问都会得到检查,及时发现边界违例情况
d)自动垃圾收集,防止出现内存漏洞
e)明确、“傻瓜式”的异常控制机制
f)为多线程提供了简单的语言支持
g)对网络程序片进行字节码校验
43、自动内存管理机制
Java程序中所有的对象都是用new操作符建立在内存堆栈上,这个操作符类似于C++的new操作符。下面的语句由一个建立了一个类Read的对象,然后调用该对象的work方法:
Readr=new Read();
r.work();
语句Readr=new Read();在堆栈结构上建立了一个Read的实例。Java自动进行无用内存回收操作,不需要程序员进行删除。而c十十中必须由程序来释放内存资源 (就是通过new和delete运算符来分配和释放内存),增加了程序设计者的负担。Java中当一个对象不被再用到时,无用内存回收器将给它加上标签以 示删除。Java里无用内存回收程序是以线程方式在后台运行的,利用空闲时间工作。
C++有栈内存与堆内存两种分配方式,程序员可以根据自己的需要来选择使用哪种内存分配的方式,Java中对象只有堆分配。区别是C++中的堆分配必须程 序员手动释放,Java通过垃圾收集器自动释放。其实Java和C++的区别也主要在这里:对于一个问题,C++实现了几乎所有的解决方法,程序员可以根 据自己的需要来选择一种实现方法;而Java只提供一两种实现方法,但通常是他认为最容易用最灵活的方法。
44、Java不支持缺省函数参数,而c十十支持
在c中,代码组织在函数中,函数可以访问程序的全局变量。c十十增加了类,提供了类算法,该算法是与类相连的函数,c十十类方法与Java类方法十分相 似,然而,由于c十十仍然支持c,所以不能阻止c十十开发人员使用函数,结果函数和方法混合使用使得程序比较混乱。(#ff0000也就是说C++里边既 有方法又有函数,我认为不能作为等同的概念来把二者混为一谈。)
Java不再有函数在Java程序语言中,去掉了程序向导语言中最重要的单元--函数(Function)。如果我们以对象向导的观念来看待函数,就可以 了解函数在对象向导的概念中,是不必要的。在对象向导的程序观念里,对象的数据才是真正的主体,而处理对象数据的方法则必须依附在对象内才有意义。因此,去掉函数并不表示不再有子程序等模组化程序的概念,相反地,是利用对象中的方法来取代函数,再一次强化对向导的发展策略。
Java没有函数,作为一个比c十十更纯的面向对象的语言,Java强迫开发人员把所有例行程序包括在类中,事实上,用方法实现例行程序可激励开发人员更好地组织编码。
45、类型转换
在C和C++中有时出现数据类型的隐含转换,这就涉及了自动强制类型转换问题。例如,在c十十中可将一浮点值赋予整型变量,并去掉其尾数。Java不支持c十十中的自动强制类型转换,如果需要,必须由程序显式进行强制类型转换。
Java是一个严格进行类型检查的程序语言,对于下面这样的程序,在C++的编译器上编译时最多只会出现警告的信息,但是在Java里则不予通过:
Int aInteger; Double aDouble=2.71828; AInteger = aDouble;
虽然这样的转型在C++里是合法的,但是也会造成数据精确度的损失。Java为了要确定写程序的人充分地了解这点,必须要程序设计强制转型(type casting),Java的编译器才会接受:
int aInteger;
doublea Double=2.71828;
aInteger=(int)aDouble;
46、对C++而言,类库一旦升级,则必须对应用程序进行重新编译,否则就无法使用升级后类库的新增功能。而Java语言在其支持的类库升级后,只需要直接覆盖上已有的类库,不需要重新编译相应的应用程序。
47、java不再有structure、union及typedef
事实上,早在C++中就可以去掉C语言中的structure和union等对复杂数据的自定结构类型,因为类(Class)的定义方式可以完全做到这项 功能。而typedef也是不必要的,一切都用类就可以了。虽然C++这样的设计是为了和C语言兼容,但是使用多余的语言特点不但不必要,而且容易造成对 程序认识的混淆。
48、和C++连接
不管Java是多么强大,总是有人需要把它和C++连接起来。因为只要有一个新的程序语言或是软件开发工具一出现,大家就会问:"它是否具有和原有程序库 连接的能力呢?"也因为C++语言在电脑界中占了很重要的地位。大家的问题其实就等于是直接问"它是否可以和C++连接?"。目前在Java中,的确提供了和C++语言连接的方法,它的做法基本上是先将C++语言所写的程序建构成动态链接函数库(DynamicLinking Library,DLL),再由Java程序去调用DLL里的函数。
这种连接的方式,使得DLL中的函数,从Java的眼光看就是一个"方法"。不过因为这种方法是直接由其他的程序语言所提供,而不是以Java语言所写的,所以它被称之为"原生方法"(NativeMethod)。由于Java Applet一些安全上的限制,所以这种连接外部程序的方法只能用在Java Application内。
49、C++的跨平台问题!
Java编译器所生成的代码可以不基于任何具体的硬件平台,而是基于一种抽象的机器---虚拟机。而c,C++的源程序要在不同平台上运行,必须重新编译。
不论是C还是C++都会有依赖平台与实现的不同比如int的大小。
由于C以及C++库功能基本都是最简化的。所以基本没法开发什么比较有用处的可移植代码.比如GUI的不同,socket实现的不同等等都制约了C++的可移植性。
如果你要写一个完全可以跨平台编译的代码,只能依靠标准库来写,那样这个程序的功能就一定非常有限.当然也有一些跨平台的库可以使用.比如GUI方面的 wxWidgets等等。
不过尽管如此.我们还是可以做一些工作来方便移植工作。不要假想平台的硬件环境,如果你要做一些对字节操作或者位操作的内容,最好注意big endian以及small endian问题不同的平台实现不同.不要假想字节长度,int的大小是32,但是不同实现里面可能有不同的长度.这依赖实现,虽然大多数的实现都使用几 乎相同的标准。尽量不要操作底层的内容 基于上面两条,我们可以得出可移植性最高的代码,应该是那些不对位或者字节进行直接操作的.不对指针内容进行修 改的,大多调用标准库函数的.不使用高级模板功能的代码。
Linux下的G++编译器对标准C++支持得很好。如果做手机游戏,要用C++,nokia需要Symbian提供的C++开发环 境,smartphone则可以用vs.net提供的。这些环境开发出来的代码,都是与平台相关的。然而如果是游戏的话想跨平台就用J2ME吧。
纯C++代码的话,跨平台十分简单,重新编译就是了。但实际上哪有纯C++的软件?C++算是较底层的语言,所以用它写软件难免要出现平台相关的东西,这就是移植时要修改的重点。
总的来说,跨平台性还是不错的。
C++的跨平台就只有两点。
a)遵循标准。特定的平台除外。
b)禁用reinterpret_cast和C风格的强制转换。
当然上边说的两点只是针对与跨编译器。但是,如果说 OS 平台,那么基本所有功能都是与平台相关的,包括网络、文件系统等显而易见的功能,以及 IO、内存分配等那么不显而易见的。要让 C++ 代码跨平台,我们只能通过包装库来掩盖不同平台的区别,这样,基于这些包装库的 C++ 程序才能在【源码级别】实现“跨平台”。
跨平台当然要注意避免使用依赖系统的操作:
a)基本类型的长度以及相对这些类型的操作,如wchar_t。
b)字符操作,特别是汉字类的宽字符。
c)IO操作
另外不同编译器对C++的实现是不同的,这就要编译一下试验一下,不过这种问题都很容易修改的!
我感觉越涉及到底层的东西,越难实现跨平台。不同的硬件体系结构,不同的编译器和编译环境,都给跨平台带来了很多的困难。如果要写出跨平台的程序,尽量使用跨平台的函数库(STL+boost),尽量避免涉及到底层的编程。
C如果涉及到跨操作系统的东西,可以使用ace,这个东西是对系统的封装的程序包。还是不错的(备注:什么是ACE?ace的全名是adaptive communication environment(可适应的通信环境),它是一个通信中间件,具有良好的可移植性;winsock只是一个socket编程的api库,仅仅提供一组api给你调用,但是ace还提供了一个性能优异的框架,也就是说,ace已经把底层的socket api包装成一个具有逻辑性的框架,你只需要按照调用规范去使用就可以获得较好的性能)
在应用表示层上做到跨平台,低层实现上或多或少都是与平台相关的。
五、C++与Java区别小总结:
事实上,constant和typedef这两条语句包含了#define语句的作用。现在,结构和联合已经被Java的类所代替。删除这些特性的原因 是:由于其希望维持与C语言的向后兼容性,C ++的语言规范包含了大量冗余。比如,类实际上就已经包括了结构和联合的作用,因此这两种数据结构完全可以取消。关于#define语句,Java语言规 范的制订者认为:尽管该语句的出发点是为了增强程序的可读性,但实际效果却恰恰相反,它常常导致难读的代码,故应该予以取消。Java不再支持独立函数,因此任何函数都必须封装到某个类中。由于人们普遍认为,C++所用的超类是非常不稳定的,因此Java抛弃了C++中的多继承并代之以接口。Java的接口指的是,在别的类看来一个类所能实现的方法。它所显示 的只是一个类的方法或常量和变量,而不是这个类的全部结构。
最后,Java还取消了C++中的GOTO语句、操作符重载、自动类型转换及指针数据类型。 GOTO语句引起的争议已经有很多年了,可一直阴魂不散,这跟某些程序员对该语句一直情有独钟有关。C++仍然支持数据类型的自动转换,但Java要求编 程人员显式实现数据类型之间的转换。自动数据类型转换使得两个数据类型互不兼容的变量可以相互赋值,而不需要给出显式说明。这有时会导致一些问题,其中最 常见的是精确度损失。比方说,如果把一个带符号的32位整数赋给一个无符号整数,则所有的结果均为正数。Java的设计者们认为这很容易引起程序错误,从 而决定不支持这种转换方式。
欢迎补充和指正!!!