作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
盖高洁的人
验证专家 在工程

Timothy是一位经验丰富的软件架构师,他用c++创建了多个游戏引擎, 包括在100多个标题中使用的一个. 从Android游戏和应用程序开发到亚马逊的行业经验,他都有广泛的Java背景, 为AWS AppStream服务构建Android客户端. 在他的职业生涯中,他使用了20多种编程语言, 其中有几个是他为满足特定需求而定制的.

专业知识

以前在

亚马逊
分享

无数文章比较了c++和Java的技术特性, 但哪些差异是最需要考虑的? 当比较显示, 例如, Java不支持多重继承,而c++支持, 这是什么意思?? 这是一件好事吗? 有些人认为这是Java的优势,而其他人则认为这是一个问题.

让我们探讨一下开发人员应该选择c++的情况, Java, 或者是另一种语言, 更重要的是, 为什么 决定很重要.

检查基础:语言构建和生态系统

c++于1985年作为C编译器的前端发布,类似于TypeScript编译成JavaScript的方式. 现代 C++ 编译器 通常编译为本机机器码. 尽管有些人声称c++的编译器降低了它的可移植性, 它们确实需要为新的目标架构进行重建, c++代码几乎可以在所有处理器平台上运行.

Java于1995年首次发布,它不能直接构建到本机代码. 而不是, Java构建字节码, 在Java虚拟机(JVM)上运行的中间二进制表示. 换句话说,Java编译器的输出需要特定于平台的本机可执行文件才能运行.

c++和Java都属于类C语言家族, 因为它们的语法与C语言相似. 最显著的区别是它们的生态系统:c++可以无缝地调用基于C或c++的库, 或者操作系统的API, Java最适合基于Java的库. 类来访问Java中的C库 Java本机接口 (JNI) API,但它容易出错,并且需要一些C或c++代码. c++还比Java更容易与硬件交互,因为c++是一种低级语言.

详细的权衡:泛型、内存等等

我们可以从多个角度比较c++和Java. 在某些情况下,c++和Java之间的选择是很明确的. 原生Android应用通常应该使用Java,除非它是一款游戏. Most game developers should opt for C++ or another language for the smoothest possible real-time animation; Java’s memory management often causes lag during gameplay.

非游戏的跨平台应用不在此讨论范围之内. 在这种情况下,c++和Java都不是理想的选择,因为它们对于高效的GUI开发来说过于冗长. 对于高性能应用程序, 最好创建c++模块来完成繁重的工作, 并为GUI使用更高效的开发人员语言.

非游戏的跨平台应用不在此讨论范围之内. 在这种情况下,c++和Java都不是理想的选择,因为它们对于高效的GUI开发来说过于冗长.

对于一些项目,选择可能并不明确,所以让我们进一步比较:

功能C++Java
系统No是的
运行时性能最好的
延迟可预测的不可预测的
引用计数智能指针是的No
全局标记-清除垃圾收集No要求
堆栈内存分配是的No
编译为本机可执行文件是的No
编译成Java字节码No是的
与低级操作系统api的直接交互是的需要C代码
直接与C库交互是的需要C代码
与Java库的直接交互通过JNI是的
标准化的构建和包管理NoMaven


除了表中比较的特征, 我们还将关注面向对象编程(OOP)特性,如多重继承, 泛型/模板, 和反射. 注意,这两种语言都支持OOP: Java强制这样做, 而c++支持OOP以及全局函数和静态数据.

多重继承

在OOP中,继承是指子类从父类继承属性和方法. 一个标准的例子是a 矩形 类继承自更泛型的 形状 类:

//注意,我们在一个c++文件中
类形状 {
    / /位置
    Int x, y;
  公众:
    //子类必须重写这个纯虚函数
    虚拟虚空draw() = 0;
};
 
类矩形:公共形状{
    //宽度和高度
    Int w, h;
  公众:
    空白画();
};

多重继承是指子类从多个父类继承. 下面是一个例子 矩形形状 类和额外的 可点击的 类:

//不推荐
类形状 {...};
类矩形:公共形状{...};
 
类可点击的 {
    int xClick, yClick;
  公众:
    虚拟void click() = 0;
};
 
类可点击的矩形:公共矩形,公共可点击的 {
    无效点击();
};

在这种情况下,我们有两个基本类型: 形状 的基本类型 矩形), 可点击的. 可点击的矩形 从两者继承以组成两个对象类型.

C++ supports multiple inheritance; Java does not. 多重继承在某些极端情况下很有用,例如:

  • 创建高级领域特定语言(DSL).
  • 在编译时执行复杂的计算.
  • 以Java中根本不可能的方式改进项目类型安全.

但是,通常不鼓励使用多重继承. 它可能会使代码复杂化并影响性能,除非与模板元编程结合使用——最好只使用模板元编程 最有经验的c++程序员.

泛型和模板

使用任何数据类型的类的泛型版本对于代码重用是实用的. 两种语言都提供这种支持——java通过泛型提供, c++通过模板——但是c++模板的灵活性可以使高级编程更安全、更健壮. 每次在模板中使用不同的类型时,c++编译器都会创建新的自定义类或函数. 此外, c++模板可以根据顶层函数的参数类型调用自定义函数, 允许特定的数据类型具有专门的代码. 这叫做 模板特殊化. Java没有类似的特性.

与此形成鲜明对比的是, 使用泛型时, Java编译器通过称为类型擦除的过程创建没有类型的一般对象. Java在编译期间执行类型检查, 但是程序员不能根据泛型类或方法的类型参数修改其行为. 为了更好地理解这一点,让我们看一个通用的快速示例 std::字符串 格式(std::字符串 fmt, T1 item1, T2 第二条) 使用模板的函数, template,从我创建的c++库:

std::字符串 firstParameter = "字符串";
int secondParameter = 123;
//将打印输出设置为8个字符宽的字符串和十六进制值
格式("%8s %x", firstParameter, secondParameter);
//将打印输出格式化为两个8字符宽的字符串
格式("%8s %8s", firstParameter, secondParameter);

c++会生成 格式 函数作为 Std::字符串格式(Std::字符串 fmt, Std::字符串 item1, int 第二条),而Java将在没有特定的 字符串int 对象类型 item1第二条. 在本例中,c++模板知道最后一个传入形参是an int 因此可以执行必要的 std:: to_字符串 第二种转换 格式 呼叫. 没有模板,一个c++ printf 语句尝试像第二个语句一样将数字打印为字符串 格式 调用将具有未定义的行为,并可能使应用程序崩溃或打印垃圾. Java函数在第一个函数中只能将数字视为字符串 格式 调用并不直接将其格式化为十六进制整数. 这是一个微不足道的例子, 但它展示了c++选择专用模板来处理任意类对象而不修改其类或对象的能力 格式 函数. 我们可以在Java中使用反射而不是泛型正确地生成输出, 尽管这种方法的可扩展性较差,而且更容易出错.

反射

在Java中, 可以(在运行时)找出结构细节,例如在类或类类型中哪些成员可用. 这种特性称为反射, 大概是因为这就像拿着一面镜子对着物体看里面是什么. (更多信息可以在Oracle的 反映文档.)

c++没有完整的反射,但是现代c++提供了 运行时类型信息 (RTTI). RTTI允许对特定对象类型进行运行时检测, 尽管它不能像对象的成员那样访问信息.

内存管理

c++和Java之间的另一个关键区别是内存管理, 主要有两种方法: manual, where developers must keep track of 和 release memory manually; 和 自动的,软件跟踪哪些对象仍在使用,以回收未使用的内存. 在Java中,一个示例是 垃圾收集.

Java需要垃圾回收内存, 提供比手动方法更容易的内存管理,并消除通常会导致安全漏洞的内存释放错误. c++本身不提供自动内存管理, 但是它确实支持一种叫做 智能指针. 智能指针使用引用计数,如果正确使用,它是安全和高性能的. c++还提供了析构函数,用于在对象销毁时清理或释放资源.

Java只提供堆分配,而c++同时支持堆分配(使用 删除 还是老一点的C malloc 函数)和堆栈分配. 堆栈分配可能比堆分配更快、更安全,因为堆栈是线性数据结构,而堆是基于树的, 因此,堆栈内存的分配和释放要简单得多.

c++与堆栈分配相关的另一个优点是一种称为资源获取即初始化(RAII)的编程技术。. In RAII, resources such as references tie to the life cycle of their controlling object; the resources will be destroyed at the end of that object’s life cycle. RAII是c++智能指针在没有手动解引用的情况下工作的方式——在函数顶部引用的智能指针在退出函数时自动解引用. 如果这是对智能指针的最后一次引用,所连接的内存也会被释放. 尽管Java提供了类似的模式, 这会更尴尬 而不是c++的RAII,特别是当您需要在同一代码块中创建多个资源时.

运行时性能

Java具有可靠的运行时性能, 但是c++仍然是最好的,因为对于实际应用程序来说,手动内存管理比垃圾收集要快. 虽然Java在某些特殊情况下可以胜过c++,因为 JIT编译, c++赢得了大多数重要案例.

特别是, 与c++对堆分配的减少使用相比,Java的标准内存库的分配会使垃圾收集器过度工作. 然而, Java仍然相对较快,应该是可以接受的,除非延迟是最主要的问题——例如, 在具有实时限制的游戏或应用中.

构建和包管理

Java在性能上的不足,在易用性上得到了弥补. 影响开发人员效率的一个组件是构建和包管理——我们如何构建项目并将外部依赖项引入应用程序. 在Java中,有一个工具叫做 Maven 将此过程简化为几个简单的步骤,并集成了许多ide,例如 IntelliJ IDEA.

然而,在c++中,不存在标准化的包存储库. 在应用程序中构建c++代码甚至没有标准化的方法:一些开发人员更喜欢Visual Studio, 而其他人则使用CMake或其他自定义工具集. 进一步增加了复杂性, 某些商业c++库是二进制格式的, 并且没有一致的方法将这些库集成到构建过程中. 此外, 构建设置或编译器版本的变化可能会导致二进制库无法正常工作.

Beginner-friendliness

构建和包管理的摩擦并不是c++远不如Java对初学者友好的唯一原因. 程序员可能很难安全地调试和使用c++,除非他们熟悉C, 汇编语言, 或者是计算机的低级工作. 把c++想象成一个强大的工具:它可以完成很多工作,但如果滥用它是危险的.

Java前面提到的内存管理方法也使其比c++更易于访问. Java程序员 不必担心释放对象内存,因为语言会自动处理这个问题.

决策时间:c++或Java?

左上角有一个深蓝色的“开始”气泡,最终连接到它下面七个浅蓝色的结论框之一的流程图, 通过一系列白色的决策节点和深蓝色的分支表示“是”和其他选项, 浅蓝色的树枝代表“不”.第一个是“跨平台GUI应用程序”?"是"则指向结论, “选择一个跨平台开发环境并使用其主要语言.“否”表示“原生Android应用程序”?,回答“是”就会引出第二个问题:“这是游戏吗??从第二个问题开始, “否”指向结论, 使用Java(或Kotlin),而“是”则指向不同的结论, “选择一个跨平台游戏引擎,并使用它推荐的语言.来自“原生Android应用程序”?的问题,“否”表示“本机Windows应用程序”?,回答“是”就会引出第二个问题:“这是游戏吗??从第二个问题开始, “是”指向结论, “选择一个跨平台游戏引擎,并使用它推荐的语言,而“不”则指向不同的结论, “选择一个Windows GUI环境并使用其主要语言(通常是c++或c#)。.来自“本机Windows应用程序”?,“否”表示“服务器应用程序”?,回答“是”就会引出第二个问题:“开发人员类型。?从第二个问题开始, “中等技能”决策指向结论, 使用Java(或c#或TypeScript),而“熟练”的决策则指向第三个问题, “首要任务?从第三个问题开始, “开发人员生产力”决策指向结论, 使用Java(或c#或TypeScript),而“绩效”决策则指向不同的结论, 使用c++(或Rust).,来自“服务器”应用程序?问题,“否”指向第二个问题,“驱动程序开发”?从第二个问题开始, “是”意味着一个结论, 使用c++(或Rust),而“否”则指向第三个问题, “物联网发展?从第三个问题开始, “是”指向结论, 使用c++(或Rust),而“否”则表示第四元问题, “高速交易?从第四题开始, “是”指向结论, 使用c++(或Rust),而“否”则表示最后的结论, “询问熟悉你目标领域的人."
为各种项目类型选择最佳语言的扩展指南.

既然我们已经深入探讨了c++和Java之间的差异, 我们回到最初的问题:c++还是Java? 即使对这两种语言有深入的了解,也没有一个放之四海而皆准的答案.

不熟悉低级编程概念的软件工程师在限制在c++或Java之间选择时,最好选择Java, 除了像游戏这样的实时环境. 另一方面,希望扩展视野的开发人员可以通过选择c++学到更多.

然而,c++和Java之间的技术差异可能只是决定的一个小因素. 某些类型的产品需要特殊的选择. 如果你还不确定, 您可以参考流程图,但请记住,它最终可能会指向第三种语言.

了解基本知识

  • c++和Java哪个更强大?

    c++通常优于Java,并且可以访问Java所缺乏的较低级别的特性, 但每种语言都有其优势.

  • Java比c++更有用吗?

    Java和c++有不同的优势. Deciding which is more useful for your project depends on your goals; 例如, 如果初学者友好是最重要的, Java是最佳选择.

  • c++和Java有什么不同?

    你可以把它想象成两个城市之间的差异. 在一些城市,骑自行车更容易,但乘坐地铁就更难了. 关于如何从一个地方到另一个地方的说明各不相同. c++和Java之间的一般区别包括编译器输出, 兼容库, 生产力特征.

  • Java和c++相关吗?

    c++和Java都是C族语言,这意味着它们的语法与C有一些共同的元素. Java的最初设计是模仿c++的,这就解释了它们有很多相似之处.

标签

聘请Toptal这方面的专家.
现在雇佣
盖高洁的人

盖高洁的人

验证专家 在工程

拉斐特,科罗拉多州,美国

2020年8月5日成为会员

作者简介

Timothy是一位经验丰富的软件架构师,他用c++创建了多个游戏引擎, 包括在100多个标题中使用的一个. 从Android游戏和应用程序开发到亚马逊的行业经验,他都有广泛的Java背景, 为AWS AppStream服务构建Android客户端. 在他的职业生涯中,他使用了20多种编程语言, 其中有几个是他为满足特定需求而定制的.

作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

专业知识

以前在

亚马逊

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

世界级的文章,每周发一次.

输入您的电子邮件,即表示您同意我们的 隐私政策.

Toptal开发者

加入总冠军® 社区.