# 介绍
许多开发人员在开始为斐济开发代码时对 C++ 比对 Java 更熟悉一些。在使用 Java 编码并习惯使用 C++ 时,存在常见的陷阱,本页面试图帮助您避免这些陷阱。
一般差异
编译时间
在C++中,所有的优化都是在编译时进行的。特别是对于C++模板来说,这可能需要很长时间,甚至可能存在无限循环。由于C++以自己编写的代码为目标,因此以后尝试对代码进行升级优化是没有意义的。
在 Java 中,编译器仅由 Java 时解释和/或即时编译运行的字节码生成。当某些字节码被多次运行时,即时编译器实际上会尝试更加努力地优化,因此 Java 的编译时间实际上实现为将 .java 文件编译为 .class 文件。
模板与泛型
Java的泛型是使用泛型来实现的,这意味着泛型有助于捕获由于编译时检查而产生的错误,但编译后的类实际上会忘记泛型参数。特别是,你不能使用泛型参数来实例化类,即这不行:
public<T> T create() { return new T(); } // does _not_ work
这种限制的好处是您永远不会像使用 C++ 那样收到神秘的多页长错误消息。
反过来是Java编译器无法像C++对模板那样优化泛型,这也是因为Java不会重新编译泛型的基类,这与C++对模板所做的恰恰相反。但是,由于compile time在模糊的,Java可以在即时编译器中进行很多优化,特别是当你明智地使用final关键字时;标记为Final的方法不能在子类中因而是即时优化的主要候选者。
Java没有指针
在C++中,你经常会发现如下结构:
const char *string = "Hello, World!";
some_func(string + 7);
这在 Java 中是不可能的。相反,您必须使用 String 的 substring() 方法。
本着同样的精神,不可能realloc()记忆。如果您需要更大的流程图,则必须分配它,可以使用方法System.arraycopy()将现有数据复制到其中。
需要this->
在Java中,可以在没有远端this.的情况下访问成员变量和方法,认为跳过这个不必要的远端因此更好。但这也意味着您的代码必须以另一种方式明确哪些变量是本地变量。
陷阱
Java 只知道通过引用
每当您将对象传递给方法时,Java都会通过引用来执行此操作。这使得编写来回复制大量内存的低效代码变得更加困难,但是当您习惯使用C++时,需要注意这一点:将对象传递给修改成员的方法时,调用者将看到更改。
##您不能使用==比较字符串
Java中没有运算符重载,因此运算符 == 指的是引用正好,而不是引用对象正好。因此,您必须使用 equals() 方法。
对象默认不实例化
当像这样声明一个指标时:
ImagePlus image;
Java 不会自动初始化变量。请记住,对象是通过引用传递的,后续阶段 image 只是对 ImagePlus 的未初始化引用。
Java 不知道解析构造函数
虽然Java进行自动垃圾收集很方便,但很容易忘记对对象的每次引用都会阻止它被释放。更糟糕的是,有时垃圾收集没有及时启动,因此你必须显式调用 System.gc(); ,甚至可能多次。
Java本质上是多线程的
当来自 C++ 时,经常尝试避免多线程,因为在 C++ 中以可移植的方式使用线程是人们很痛苦的。
在Java中,习惯线程非常简单。而且便携。但这并不意味着编写多线程程序很容易。人类太线性时间进程,无法考虑多线程代码的所有可能的反应,或者考虑使代码块“同步”的需要(即确保某些代码块不会在多个线程中同时执行)。
然而,最臭名昭著的错误是多线程代码中的错误,因为它们真的非常难以调试。当调试消息引入到代码中时,多线程错误消失的情况并不罕见。
当然,多线程程序的优点是多核系统将立即从该代码中受益。
没有使用Java的语法
许多C++程序员将Java视为C++的方言,而忘记了Java具有方便的语法结构。例如,您经常会发现类似这样的代码
for (int i = 0; i < array.length; i++) {
String string = array[i];
// do something
}
甚至更糟糕:
Iterator<String> iter = list.iterator();
while (iter.hasNext()) {
String string = iter.next();
// do something
}
而不是使用Java语法(自Java 1.5起可用):
for (String string : array)
// do something
没有使用Java的标准库
来自C++的开发人员通常倾向于自己实现所有内容,即使算法已经实现。例如,java.util.Collections和java.util.Arrays分别包含对集合和内存进行排序、打乱、过滤或二分搜索的方法。
同样,Java附带了一些有用的类,可以实现优先级队列(自Java 1.5起)等简洁的功能。
“final”并不意味着“const”
在C++中,当队列被声明为const时,其任何边界都不能以任何方式编辑。但在java中,当一个引用队列的变量被声明为final时,只有该变量不能被赋值。 队列(或集合,或任何容器)的任何边界都是可编辑的,并且槽队列本身重新分配。
#约定
类和函数名称
在 C++ 中,常见的风格是对类名和函数名使用下划线,例如gaussian_blur(除非您在 Windows 上进行开发,其中类名通常以大写 C 和驼峰式命名)。
在Java中,平时是使用CamelCase代替下划线,并且类名以大写字母开头,但字段和方法名小写,例如§§§代码0§§§和§§§代码1§§§。