比较C++和Java 一

作为C++程序员,你已经具备了基本的面向对象编程的意识,而且Java的语法毫无疑问对你来说很熟悉。这很正常,因为Java就是从C++衍生而来的。
然而,C++和Java之间有诸多不同之处。这些不同目的在于带来重大改善,如果你理解了这些不同之处,你就会感受到为什么Java是一门不错的编程语言。本附录带你纵览Java不同于C++的重要特性。

1.最大的潜在障碍是速度:解释型的Java比C慢20倍以内。没有什么可以阻止Java语言被编译,而且在本文写作时就有即时编译器出现来提供重大的速度提升。不难想象,完全的本地编译器将会出现在流行的平台上,没有这些,Java会由于速度面对许多问题。

2.Java和C++有相同的注释风格。

3.所有的代码都必须位于类中。没有全局方法和数据。如果你需要类似全局的效果,就在类中使用static方法和数据。Java中没有结构体、枚举或者联合,只有类。

4.所有的方法直接定义于类中。在C++中,这看起来像把所有的方法都内联了,但是在Java中不是这样。

5.Java的类定义与C++大致相同,但是没有C++类定义中的结束分号。Java中没有形如class foo的类声明,只有类定义。

class aType {
  void aMethod() { /* method body */ }
}

6.Java中没有作用域操作符::。Java使用点(.)来完成所有操作,但是可以不用它,因为你可以只在类中定义元素。甚至方法定义必须位于类中,所以Java中也不需要作用域操作符。你会在调用静态方法的地方发现两者的不同:Java中你使用ClassName.methodName();。除此之外,package名字也使用点来建立,并且Java中使用import关键字来实现如同C++中#include的效果。例如:import java.awt.*;。(#include并非直接对应import,但是与之使用感觉很相像)。

7.Java,和C++一样,为了高效存取保留了原生数据类型。在Java中,原生数据类型包括boolean, char, byte, short, int, long, float,double。所有的原生数据类型出于可移植性考虑,都有机器无关的特定大小。(这肯定对性能有影响,与不同的机器相关。)Java中类型检查与类型要求更加严格。例如,

  • 条件表达式的值只能是boolean,不能是整数。

  • 形如X+Y这样的表达式,其结果必须被使用;不能仅使用X+Y的副作用。

8.char类型使用内置的16位Unicode字符集,所以它能用来表示大多数国家的字符。

9.静态引用的字符串(如:”Hello”)会自动转换为String对象。没有像C和C++中的独立的静态字符数组字符串。

10.Java添加了三个一组的右移操作符>>>进行逻辑右移 - - 在顶端插入0;>>会在移动过程中插入符号位(算术移位)。

11.虽然看起来很像,但是Java和C++中的数组在结构和行为方面有很大不同。Java中的数组有只读的length成员来告诉你数组的大小,并且当你越界时运行时检查会抛出异常。Java中所有的数组都在堆上创建,你能够将一个数组赋给另一个数组(仅仅简单地拷贝数组句柄)。数组标识符是一个一级对象,几乎可以使用所有其他对象可使用的方法。

12.所有的非原生类型对象只能用new来创建。与C++不同,无法在栈上创建非原生类型的对象。所有的原生类型只能创建于栈上,没有new。Java中对应所有的原生类型都有包装类,以便于你通过new创建基于堆的等价对象。(原生类型的数组是个特例:他们和C++中一样,会通过聚合初始化在堆中分配空间,或者使用new)。

13.Java中无需提前声明。如果你想在一个类或方法定义(位置)之前使用它,你使用它就好了 - - 编译器保证有合适的定义存在。因此,你不会遇到C++中的任何提前引用问题。

14.Java没有预处理。如果你想使用另一个库中的类,你使用库名配合import即可。Java中没有预处理类的宏。

15.Java中使用包(packages)来替代命名空间(namespaces)。名称问题通过把一切放于类中并且使用类似于C++中的名称空间的称为“包”的机制来隔离类名得以被处理。包同样收集库组件于一个单独的库名下。你只用简单的import一个包,编译器处理剩下的事情。

16.对象句柄定义为类成员时自动初始化为null。在Java中原生类型成员数据会被初始化;如果你没有显式初始化他们,他们会获得一个默认值(零或等价物)。你可以在他们定义时,或构造函数中对他们进行显式初始化。这种语法比C++更合理,并且对于staticnon-static成员的处理是一致的。你不必像在C++中一样,于类的外部定义static成员。

17.Java中没有指针。当你使用new创建了一个对象,你会获得一个引用(上文中也将其称为句柄)。例如:

String s = new String("howdy");

然而,不像C++的引用,必须在创建时初始化并且无法重新绑定另一个位置,Java引用不必在创建时就初始化。他们也可以在需要的时候被重新绑定,这一方式部分消除了对于指针的需求。在C和C++中定义指针另一个原因是需要来指向内存中的任何位置并进行操作(这使得他们是不安全的,这也是为何Java不支持指针)。指针通常被视为是一种直接移动原生类型数组的高效方式;Java数组允许你以一种更安全的方式进行同样的操作。指针问题的终极解决方案是本地方法(在附录A中讨论)。传递指针(译者注:即引用)给方法是没有问题的,因为没有全局方法,只有类,你可以传递引用给对象。
Java语言的推广者起初说“没有指针!”,但是当许多程序员问及没有指针你如何让其正常工作的,推广者开始说“受限制的指针。”你可以自己下定决心认为Java的引用是不是真的指针。但无论如何,没有指针运算。

18.Java有同C++类似的构造器。如果你没有定义构造器,编译器会为你提供一个默认的构造器,当你定义了一个非默认的构造器,编译器就不会为你提供默认构造器了,如同C++一样。Java没有拷贝构造函数,因为所有的参数都是通过引用传递的。

19.Java中没有析构函数。Java中变量本身没有“范围”,去表明何时对象的生命期结束 - - 一个对象的生命期转而由垃圾收集器决定。Java中每个类都有finalize()成员方法,在某些方面如同C++析构函数一样,但是finalize()方法由垃圾收集器调用,并且被认为只负责释放“资源”(例如打开的文件,套接字,端口,URLs等)。如果你需要在某个特定的点执行某些操作,你必须创建一个专门的方法并且调用它,不要依赖finalize()方法。换句话说,C++中所有的对象将会被(或者不如说,应该被)销毁,但是并非Java中的所有对象都会被垃圾回收。因为Java不支持析构函数,所以你必须要自己创建清理方法(有必要的话)并且显式调用所有的清理方法(为基类和你类中定义的成员对象)。

20.Java的方法重载几乎同C++函数重载一样。

21.Java不支持默认参数。即:

class A
{
public:
    void func_a(int, int);
};

void A::func_a(int a, int b = 10)
{ /* function body */ }

22.Java中没有goto语句。Java中的无条件跳转机制是break标号与continue标号,它们用于从多层嵌套循环中跳出。

23.Java继承结构为单根层次,所以所有的对象最终都继承自根类Object。在C++中,你可以随意开启一个新的继承树,以至于最后你会得到一片继承森林。在Java中你会得到一个单独的最终层次结构。这似乎是有限制性的,但是它提供了很大的优势,因为你知道每一个对象都至少可以保证有Object接口。C++好像是唯一的没有强加单根层次结构的面向对象语言。

24.Java中没有模板或其他的参数化类型实现。其包括一套集合:VectorStack,和Hashtable,来容纳Object引用,通过这些集合来满足你的收集需求,但是这些集合没有C++标准模板库高效。Java 1.2中新的集合更加完整,但是依旧没有同模板的实现具有相同的效率。

25.垃圾回收意味着Java中内存泄露是很难发生的,但是并非是不可能的。(如果你调用本地方法分配存储空间,这一操作通常无法为垃圾收集器所知。)然而,许多内存泄露和资源泄露可以追踪到一个实现糟糕的finalize()或者是没有在内存或资源分配的块(此处析构函数肯定派的上用场)到头时释放这些资源。垃圾收集器相比于C++来说是一个重大的改善,使得许多程序问题就这样消失不见。这或许使得Java不适合处理那些不能忍受垃圾收集器的小问题,但是垃圾收集器的优势似乎大大超过了这个潜在的不利之处。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值