浅谈Java与C++的关系和区别

  在TIOBE榜单中常年霸榜的两门老牌热门语言JavaC++因为有很多相似之处所以经常被拿出来作比较,这两门语言的编程风格很相似,不过主要用途、特性和技术栈有些不同。通过这些不同之处可以间接看到软件技术的发展历程,所以有必要了解一下它们的关系和差异。

  在了解JavaC++的关系之前,我们先熟悉一下这两门语言的概况:

C++ Java
创始人 Bjarne Stroustrup James Gosling
发布时间 1983 1995
定位 高级语言 高级语言
基础 C C++
特点 灵活、高效
接近底层
简洁、严谨
跨平台
严格面向对象
应用领域 系统编程
大型应用
嵌入式
高性能场景
游戏
企业级应用
Web应用
Android
大数据
技术栈 计算机原理
操作系统
计算机网络
数据库
数据结构与算法
面向对象技术
计算机网络
数据库
面向对象技术
高并发
分布式
Web技术栈

  JavaC++之间的关系很有渊源,甚至可以说这两门语言是血亲。

  C++: 从名字就能看出来C++是C的延续和扩展,最大的扩展就是支持了面向对象。由于C++和C的兼容性非常好而且经常以混合编程的形式出现,所以经常会把这两门语言统一称为C/C++

C++和C有非常亲密的关系和很好的兼容性,但并不意味着C++代码可以无差别兼容C代码。

  • C++独有的特性C不能使用,这毋庸置疑。

  • C和C++在编译和语法上也会有一些差别,C++的语法更严格,混合编程需要注意这些差别带来的影响。最常见的一个例子——C和C++同名函数的编译结果不一致(诱因是C++支持重载机制)。

  • 由于C++的语法比C更严格,C的一些编程技巧对C++不适用。相比而言,C++特性更多功能更强大,C代码更灵活、更简洁。

  Java:在设计Java之前,高司令(James Gosling)试图修改、扩展C++解决当时遇到的的问题,不过后来放弃了这种思路,而直接创造了一门新语言Oak(1995年之前叫Oak,后更名为Java)。所以我们会发现Java和C++无论是语法风格还是编程思想上都有很多相似之处,可以说Java是C++的 “精简+加强” 形态。


相同点

  既然JavaC++有如此密切的关系,那他们之间一定少不了共同点:

  • 都是静态、强类型语言;
  • 都支持面向对象技术;
  • 有很多相似的特性,如泛型、lambda、foreach等;
  • 语法风格相似;

不同点

  前面提到Java可以看成是C++的“精简+加强”形态,具体是如何“精简+加强”的呢?

  • 精简
  • 基本数据类型
  • 指针
  • 重载操作符
  • 多重继承
  • 加强
  • 垃圾回收
  • 内存模型
  • 严格面向对象
  • 模板 --> 泛型

  上面列举的是Java和C++在使用和语法特性上的一些主要差异,那么为什么会存在这些差异?难道只是为了让Java特立独行,为了证明Java与C++不一样?真正的程序员不会这么无聊,开发编程语言的大牛程序员更不会这么无聊。所以到底是为什么呢?这要从Java和C++两门语言本身的设计说起,语言本身的差异主要体现在三个方面

  • 运行环境
  • 内存管理方式
  • 对面向对象技术的支持形式

运行环境

  C++和Java代码的编译、执行过程如下:

  • C++ --> 机器码 --> 计算机。 代码被编译成二进制形式的机器码,直接在CPU执行。
  • Java -> 字节码 --> 虚拟机 --> 计算机。 代码被编译成Java字节码,在Java虚拟机上执行。

  可以看到Java和C++的运行环境存在很大不同,忽略编译过程,C++代码是直接在CPU上运行的,而Java代码则运行在JVM上。JVM的设计原理比较复杂,这里可以把JVM简单理解为一个解释器软件,它可以把Java字节码翻译成CPU能执行的控制命令,所以Java代码只要有JVM就能运行而不关心硬件。而C++编译生成的机器码直接和硬件交互。

  也正是因为JVM的存在,让Java拥有了一些C++不具备的优秀特性,如可移植性、垃圾回收等等;同时也因为JVM的存在,让Java很难支持C++的一些强大特性,如操作内存。

内存管理方式

  Java和C++的内存模型中都存在常量区的概念,不过它们在对象的内存分配方式内存释放两方面存在很大的区别。

  对象的内存分配方式:Java中的对象只能在上分配内存;C++中的对象可以在 或者 静态区分配内存。

  • Java中创建对象的方式主要有new操作符反射反序列化几种方式,无论通过哪种方式创建对象,都需要在堆区申请内存分配给对象;所以在Java中,栈区一般只存放基本数据类型的变量和对象引用。
  • C++中创建对象的方式非常灵活:直接定义变量new操作符在给定内存上初始化对象。第一种方式,直接定义变量,在静态区或栈区为对象申请内存(全局变量的内存在静态区、局部变量的内存在栈区);第二种方式,new操作符创建对象,在堆区申请内存;至于第三种方式,内存可以是指定的任意位置内存,详情参考placement new的用法。

  内存释放:Java有垃圾回收机制,不需要手动释放申请的堆内存;C++中需要手动释放申请的堆内存;

  • Java的垃圾回收机制来自于它强大的运行环境——JVM,而不是它自身的语法特性;JVM提供了一个清洁工,我们在使用Java编程的时候可以随便制造“垃圾”并且可以完全不用管理垃圾该怎么处理,因为“清洁工”会帮我们管理。
  • C++没有垃圾回收机制,需要手动释放申请的堆内存;有一些编程技巧可以帮我们更方便地管理内存,甚至达到类似Java那样不用关心“垃圾”的效果,比如智能指针RAII等技术。

对面向对象技术的支持形式

  Java和C++虽然都支持面向对象,但是它们对面向对象的支持程度、支持方式和一些技术细节有些不一样

  • 支持形式不同。Java是严格的面向对象语言;C++支持面向对象,也仍然保留面向过程的语法。

  • 继承技术不同。Java不支持多重继承、有接口的概念;C++支持多重继承,没有接口的概念;

  在Java中类是用关键字class定义的,接口是用关键字interface定义的;接口的作用是定义行为、限制类型。因为多重继承存在一些弊端如菱形继承问题,Java取消了多重继承这种特性引入接口的概念,就是为了解决这些问题


  除前面列举的典型差距外,Java和C++在语法和某些技术的实现上也有一些不同,这也能体现出两种语言在编程理念上的细微差异。

基本数据类型

  C++有7种基本数据类型,外加4个类型修饰符;Java有8种基本数据类型,外加引用类型;

  • C++的数据类型分为有符号和无符号两种,Java只有有符号的数值类型;
  • C++的某些数值类型的宽度在不同机器上是不一样的(如long int),Java的各种数值类型的宽度是固定的;

泛型技术的原理

  Java和C++编码都支持泛型的概念,不过在C++中称为模板而不叫泛型,其实在了解C++和Java支持泛型的原理后就能理解为什么在C++叫做模板而不是泛型了。

  • C++的模板是定义了一个类或函数的模板,在编译阶段会根据这个模板生成一个或多个同名的重载函数,至于具体生成多少个同名函数要根据调用方来确定,调用方的入参类型每多种,编译时就会多生成一个形参列表不一样的同名函数。

  这也解释了为什么模板类或模板函数必须定义在头文件里,而且多次包含头文件相当于多次定义了类或函数,但编译期间不会报重复定义的错误,因为编译后就已经不是同一个函数了。

  • Java泛型用的是类型擦除技术,泛型类内部操作数据时会擦除入参对象的类型,把对象当做Object来操作。

  所以基本数据类型不能作为泛型的类型参数,而必须要用对应的封装类型。

你可能感兴趣的:(C++,java)