我知道编辑这个网站吗?

给 C++ 开发人员的提示

# 介绍

许多开发人员在开始为斐济开发代码时对 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.Collectionsjava.util.Arrays分别包含对集合和内存进行排序、打乱、过滤或二分搜索的方法。

同样,Java附带了一些有用的类,可以实现优先级队列(自Java 1.5起)等简洁的功能。

“final”并不意味着“const”

在C++中,当队列被声明为const时,其任何边界都不能以任何方式编辑。但在java中,当一个引用队列的变量被声明为final时,只有该变量不能被赋值。 队列(或集合,或任何容器)的任何边界都是可编辑的,并且槽队列本身重新分配。

#约定

类和函数名称

在 C++ 中,常见的风格是对类名和函数名使用下划线,例如gaussian_blur(除非您在 Windows 上进行开发,其中类名通常以大写 C 和驼峰式命名)。

在Java中,平时是使用CamelCase代替下划线,并且类名以大写字母开头,但字段和方法名小写,例如§§§代码0§§§和§§§代码1§§§。