比较C++, C#和Java

10 篇文章 0 订阅

对比C++和Java

事实上,Java本来就是从C++衍生出来的。
然而,C++和Java之间仍存在一些显著的差异。可以这样说,这些差异代表着技术的极大进步。一旦我们弄清楚了这些差异,就会理解为什么说Java是一种优秀的程序设计语言。本附录将引导大家认识用于区分Java和C++的一些重要特征。
(1) 最大的障碍在于速度:解释过的Java要比C的执行速度慢上约20倍。无论什么都不能阻止Java语言进行编译。写作本书的时候,刚刚出现了一些准实时编译器,它们能显著加快速度。当然,我们完全有理由认为会出现适用于更多流行平台的纯固有编译器,但假若没有那些编译器,由于速度的限制,必须有些问题是 Java不能解决的。
(2) 和C++一样,Java也提供了两种类型的注释。
(3) 所有东西都必须置入一个类。不存在全局函数或者全局数据。如果想获得与全局函数等价的功能,可考虑将static方法和static数据置入一个类里。注意没有象结构、枚举或者联合这一类的东西,一切只有“类”(Class)!
(4) 所有方法都是在类的主体定义的。所以用C++的眼光看,似乎所有函数都已嵌入,但实情并非如何(嵌入的问题在后面讲述)。
(5) 在Java中,类定义采取几乎和C++一样的形式。但没有标志结束的分号。没有class foo这种形式的类声明,只有类定义。

class aType()
void aMethod() {/* 方法主体 */}
}

(6) Java中没有作用域范围运算符“::”。Java利用点号做所有的事情,但可以不用考虑它,因为只能在一个类里定义元素。即使那些方法定义,也必须在一个类的内部,所以根本没有必要指定作用域的范围。我们注意到的一项差异是对static方法的调用:使用ClassName.methodName()。除此以外,package(包)的名字是用点号建立的,并能用import关键字实现C++的“#include”的一部分功能。例如下面这个语句:
import java.awt.*;
(#include并不直接映射成import,但在使用时有类似的感觉。)
(7) 与C++类似,Java含有一系列“主类型”(Primitive type),以实现更有效率的访问。在Java中,这些类型包括boolean,char,byte,short,int,long,float以及 double。所有主类型的大小都是固有的,且与具体的机器无关(考虑到移植的问题)。这肯定会对性能造成一定的影响,具体取决于不同的机器。对类型的检查和要求在Java里变得更苛刻。例如:
■条件表达式只能是boolean(布尔)类型,不可使用整数。
■必须使用象X+Y这样的一个表达式的结果;不能仅仅用“X+Y”来实现“副作用”。
(8) char(字符)类型使用国际通用的16位Unicode字符集,所以能自动表达大多数国家的字符。
(9) 静态引用的字串会自动转换成String对象。和C及C++不同,没有独立的静态字符数组字串可供使用。
(10) Java增添了三个右移位运算符“>>>”,具有与“逻辑”右移位运算符类似的功用,可在最末尾插入零值。“>>”则会在移位的同时插入符号位(即“算术”移位)。
(11) 尽管表面上类似,但与C++相比,Java数组采用的是一个颇为不同的结构,并具有独特的行为。有一个只读的length成员,通过它可知道数组有多大。而且一旦超过数组边界,运行期检查会自动丢弃一个异常。所有数组都是在内存“堆”里创建的,我们可将一个数组分配给另一个(只是简单地复制数组句柄)。数组标识符属于第一级对象,它的所有方法通常都适用于其他所有对象。
(12) 对于所有不属于主类型的对象,都只能通过new命令创建。和C++不同,Java没有相应的命令可以“在堆栈上”创建不属于主类型的对象。所有主类型都只能在堆栈上创建,同时不使用new命令。所有主要的类都有自己的“封装(器)”类,所以能够通过new创建等价的、以内存“堆”为基础的对象(主类型数组是一个例外:它们可象C++那样通过集合初始化进行分配,或者使用new)。
(13) Java中不必进行提前声明。若想在定义前使用一个类或方法,只需直接使用它即可——编译器会保证使用恰当的定义。所以和在C++中不同,我们不会碰到任何涉及提前引用的问题。
(14) Java没有预处理机。若想使用另一个库里的类,只需使用import命令,并指定库名即可。不存在类似于预处理机的宏。
(15) Java用包代替了命名空间。由于将所有东西都置入一个类,而且由于采用了一种名为“封装”的机制,它能针对类名进行类似于命名空间分解的操作,所以命名的问题不再进入我们的考虑之列。数据包也会在单独一个库名下收集库的组件。我们只需简单地“import”(导入)一个包,剩下的工作会由编译器自动完成。
(16) 被定义成类成员的对象句柄会自动初始化成null。对基本类数据成员的初始化在Java里得到了可靠的保障。若不明确地进行初始化,它们就会得到一个默认值(零或等价的值)。可对它们进行明确的初始化(显式初始化):要么在类内定义它们,要么在构建器中定义。采用的语法比C++的语法更容易理解,而且对于 static和非static成员来说都是固定不变的。我们不必从外部定义static成员的存储方式,这和C++是不同的。
(17) 在Java里,没有象C和C++那样的指针。用new创建一个对象的时候,会获得一个引用(本书一直将其称作“句柄”)。例如:
String s = new String("howdy";);
然而,C++引用在创建时必须进行初始化,而且不可重定义到一个不同的位置。但Java引用并不一定局限于创建时的位置。它们可根据情况任意定义,这便消除了对指针的部分需求。在C和C++里大量采用指针的另一个原因是为了能指向任意一个内存位置(这同时会使它们变得不安全,也是Java不提供这一支持的原因)。指针通常被看作在基本变量数组中四处移动的一种有效手段。Java允许我们以更安全的形式达到相同的目标。解决指针问题的终极方法是“固有方法” (已在附录A讨论)。将指针传递给方法时,通常不会带来太大的问题,因为此时没有全局函数,只有类。而且我们可传递对对象的引用。Java语言最开始声称自己“完全不采用指针!”但随着许多程序员都质问没有指针如何工作?于是后来又声明“采用受到限制的指针”。大家可自行判断它是否“真”的是一个指针。但不管在何种情况下,都不存在指针“算术”。
(18) Java提供了与C++类似的“构建器”(Constructor)。如果不自己定义一个,就会获得一个默认构建器。而如果定义了一个非默认的构建器,就不会为我们自动定义默认构建器。这和C++是一样的。注意没有复制构建器,因为所有自变量都是按引用传递的。
(19) Java中没有“破坏器”(Destructor)。变量不存在“作用域”的问题。一个对象的“存在时间”是由对象的存在时间决定的,并非由垃圾收集器决定。有个finalize()方法是每一个类的成员,它在某种程度上类似于C++的“破坏器”。但finalize()是由垃圾收集器调用的,而且只负责释放“资源”(如打开的文件、套接字、端口、URL等等)。如需在一个特定的地点做某样事情,必须创建一个特殊的方法,并调用它,不能依赖 finalize()。而在另一方面,C++中的所有对象都会(或者说“应该”)破坏,但并非Java中的所有对象都会被当作“垃圾”收集掉。由于 Java不支持破坏器的概念,所以在必要的时候,必须谨慎地创建一个清除方法。而且针对类内的基础类以及成员对象,需要明确调用所有清除方法。
(20) Java具有方法“过载”机制,它的工作原理与C++函数的过载几乎是完全相同的。

C#和Java的对比

自从互联网出现以来,Java就成了许多开发者的首选.而许多C++开发者在较短的时间内转移到了Java开发者的队伍中来. Java成功的开发和实现了许多高质量的多线程动画, 游戏, 以及分布的应用程序. 更重要的是,Java 语言是完全平台无关的.
被称作Apllets(小应用程序)的Java程序在被下载到本地以前必须首先通过安全认证,这样就避免了任何病毒钻入用户的计算机的企图. 许多新的改进,诸如旋摆软件包(swing package), Java2D API, 连网软件包(java .net)在最初的Java开发包发布以后被加进了这种语言里. 从Sun公司发布Java以来,它的许多竞争对手开发了这种热门语言的替代品,一些公司甚至在两年以前就开始了.
现在一家无需更多介绍的公司--微软已经发布了一种新的叫做微软.NET的技术. .NET家族的一种主要的语言是C#或者说C-sharp. 这种语言是从Java/C++继承而来的. 从我的对C#的六个月的技术上的经验来说,我觉得C#或多或少与Java是相似的.但是C++的许多功能,比方说操作符重载(它在Java中已经被移去了)还存在于C#中.
Java程序能够在安装了Java虚拟机或者JVM的任何平台上运行.但是.NET程序的平台要求安装了通用语言运行库或者称做CLR. 它是所有.NET语言运行所需的运行库.所以一种.NET语言能够调用另一种.NET语言写成的模块和函数. 更进一步的说,如果你学习了种像C#之类的语言,那么你就很容易学习另一种.NET语言因为所有的.NET语言遵循微软所谓的.NET Framework(架构). 这种架构包括了编写和安装健壮的.NET应用程序所必需的类库.使用.NET你可以通过ASP.NET进行服务器端的编程,这点非常像JAVA中的 servlets.
就象Java中的Applets, C#引入了WinForms 和WebForms的概念.使用WinForms你可以设计基于Windows的应用程序而使用WebForms你能够开发Web应用程序. 这点可以要么通过C#编程或者是使用Visual Studio.NET这样的开发环境工具来实现. 它包含了Visual C#,使用Visual C#你可以非常容易的编写C#应用程序.
在我们使用Visual C++编程的时候,WinForms几乎就是win32程序.用C++来开发这些程序是可能的.但是VC++给我们提供向导来简化我们的开发过程.现在 Visual C#也在做同样的工作.因此如果你已经是一个VC++的程序员了,那么你最好试一试VC#.

Java程序和C#程序的比较:我们应该比较一下用Java写成的程序和C#的有什么不同. 我们将讨论两个程序间主要的不同点.

Hello Java 程序

class Hello { // 类声明
public static void main(String args[]) { // main 方法,入口点
System.out.println("Hello Java";); // 向控制台输出Hello Java
}
}

Hello C# 程序

using System; // 调用System命名空间
class Hello { // 类声明
public static void Main () { // main 方法, 入口点
console.writeLine("Hello C#";); // 向控制台输出 Hello C#
}
}
在Java中, lang软件包是自动引入的.在简单的程序里没有必要引入这个包.但是在C#中,我们不得不在所有的程序里调用System命名空间. 请记住控制台是System命名空间下的一个类. 试着运行一下上面的程序并查看它们的输出结果.

Main方法

Java:你有可能编写一个没有main方法的Java程序,只要这个类是用来作为父类.但是只有类中包含有正确的Main方法的时候程序才能运行.
C#:没有正确的Main方法就不可能编译C#源程序.如果main方法缺失了,那么编译器就会显示一个错误消息:程序’filename.exe’没有定义入口点.

继承:
Java 和C#都不支持多重继承而且都提供接口的概念作为多重继承的替代品.但是C#在接口中包括了更高级的内容.请在本文末找出题为新增 加的特点的内容.
操作符和控制流语句:
Java中出现的所有诸如算术,逻辑,自增和自减等操作符都可以在C#中找到. 而Java中的像if, else, if-else, for, do-while, while等控 制流语句C#统统支持. 但是C# 增加了C++中流行的goto语句.
异常处理:
在C#中你可以重用try, catch, finally, throws 语句处理运行时错误(通常也叫做异常).C# 中的异常处理过程除了一些小的不同以外几乎 与Java完全相同. C#中System.Exception命名空间是所有异常类的基类.
多线程:
C#中多线程的应用比起Java来要容易得多.我们可以使用Monitor 和 Mutex类同步线程.
新增特点:
索引,属性和代理是C#中的新概念.索引几乎与Java中的向量相同. 对其新特点的完全的讨论已经超出了我们的范围.但是我将尽量在这个网 站的其它地方解释它们. C#引入了Java所没有的操作符重载的概念.但是Java和C#都支持方法重载.
让我们回到对接口的讨论,我们能够验证包括在接口中的方法是否是使用is 和 as 操作符实现的.当我们实现接口的时候能避免命名冲突.你甚至可以将两个接口结合到一个中来,并在类中实现这个复合的接口,如下面的代码所示:

using System;
public interface First {
void A();
void B();
}
public interface Second {
void C();
}
public interface Combined: First, Second { }
class Combineimple: Combined {
// 这里是程序代码
// main方法
} }
而且C#在显示编译错误的时候还显示它们的错误代码.你可以搜索与SDK有关的在线文档寻找和这个错误代码有关的内容并找出这个错误发生的原因的细节.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值