Java 与 C++ 细节差异 (一)

注释

相比 C++,Java提供了三种注释方式分别为

  • // 单行注释
  • /* ... */ 多行注释
  • /** ... */ 文档注释
    前两种与 C++ 相同,最后一种可以自动将注释内容生成文档。供使用者直接查看。

基本数据类型

整数

Java 存储空间 C++ 存储空间
int 4 字节 int 至少 4 字节,且大于等于 short
short 2 字节 short 至少 2 字节
long 8 字节 long 至少 4 字节,且大于等于 int
byte 1 字节
long long 至少 8 字节,且大于等于 long

Java 提供了 4 种整数类型,与 C++ 相比 Java 的规范更为严格。可以看出 C++ 更在乎效率,而 Java 更在乎可移植性。

十六进制数和八进制数两种语言均可以使用 0x 和 0 为前缀来表示,而 Java 还提供了前缀 0b 来表示二进制数。

浮点数

Java 存储空间 C++ 存储空间
float 4 字节 float 4 字节
double 8 字节 double 8 字节
long double ( Intel ) 16 字节

两者都遵循 IEEE-754 标准

C++ 直接提供了 80 位的扩展精度浮点数,而 Java 没有提供。
Java 没有提供的原因还是对可移植性的考虑,值得注意的是如果 JVM 运行在 Intel 的处理器上时,浮点数的中间运算结果默认是采用扩展精度存储的。这是因为截断会使效率大幅降低,但 Java 也提供了截断的可能性,使用 strictfp 关键字标记的方法(函数)必须严格的对中间结果截断,保证在任何处理器环境的结果的一致性。
例:public static strictfp void main(String[] args)

初始化

Java 禁止使用未初始化的本地变量,C++ 可以。

常量

修饰符不同,Java 使用 final 修饰常量,但 const 也是 Java 的保留字。

Java C++
final type const type

常量可以不在定义出初始化,但必须保证在第一次使用前被初始化,且只初始化一次。


数组

Java 没有 C++ 中在栈区分配到数组,你不可以写出这样的代码

1
int a[10];

所有的数组,都需要使用 new 在堆上分配空间。

Java 提供了两种定义数组的方式

1
2
int[] a = new int[size];
int a[] = new int[size];

如果你没有初始化数组,Java 会帮你做数组的初始化。数字数组将所有元素初始化为 0 ,boolean 数组初始化为 false,对象数组初始化为 null 。

Java 中 []运算符被定义为检查数组边界,而且 Java 没有指针运算,不可以通过 a + 1 得到下一个元素。


命名规则

Java C++
一个以字母开头的由字母或数字组成的序列,字母包括{‘A’ ~ ‘Z’、’a’ ~ ‘z’、’_’、’$’ 或在某种语言中代表字母的任何 Unicode 字符 }。 一个由数字,下划线,小写和大写拉丁字母,和大多数 Unicode 字符组成的任意长度的序列。有效的标识符必须以一个非数字字符(拉丁语字母,下划线或 Unicode 非数字字符)开头。

注:
Java 中在某种语言中代表字母的任何 Unicode 字符,比如德国用户可以用 ä 。可以使用 Character 类的 isJavaIdentifierStart 和 isJavaIdentifierPart 方法检测。

C++ 中大多数 Unicode 字符是指除下表中的字符以外的 Unicode 字符。

代码点 说明
U+0300 - U+036F 组合用抑音符 - 组合用拉丁文小写字母 X
U+1DC0 - U+1DFF 组合用带点抑音符 - 组合用下右箭头尖和向下箭头尖
U+20D0 - U+20FF 组合用上左鱼叉 - 组合用上星号
U+FE20 - U+FE2F 组合用连字左半 - 组合用西里尔文 Titlo 右半

重名问题

在 C++ 中你可以写出这样的代码

1
2
3
4
5
int a;

{
int a;
}

这样进入大括号后,外层的整数 a 就被隐藏了,看不到了无法访问了,出大括号就可以继续访问外层的整数 a 了。

而在 Java 中编译器是不允许你写出这样的代码的。
Java 和 C++ 大体上相同,本地变量的生存期是由其所在的大括号决定的。它们两者的不同之处在于 Java 是完全不允许在一个变量的生存期内出现另一个重名的变量,而 C++ 允许在内层定义新的重名变量隐藏外层变量。

例:

1
2
int a;
int a;

这样的代码在两种语言中都是错误的。

1
2
3
4
5
{
int a;
}

int a;

这样的代码在两种语言中都是正确的。

二者唯一的差别就是我在最开始的那个例子,Java 在外层 a 的生存期还没结束前不可以定义新的重名变量,而 C++ 可以。


String 与 string

String 和 string 分别为 Java 和 C++ 库里的字符串,虽然只是差一个字母大小写,实际上它们有着巨大的差异。
string 更像是 char 的数组,它的每个单位都是可以直接这样 s[index] 访问的,而且可以进行修改。
String 就没有那么方便了,Java 没有运算符重载只能通过 s.charAt( index ) 来转换成 char 再读。注意!String 没有提供写操作的方法。String 在 Java 中是一种不可修改的字符串。

这实际上是效率优化上的不同想法,C++ 中每个 string 的对象都独占一块内存空间,Java 的 String 不可修改就可以将多个相同的字符串变量共享一块内存空间,复制操作效率也变得很高。但这样就要在字符串比较时特别注意,Java 的对象变量都是对象的管理者,且 Java 没有运算符重载,如果你有两个 String 的对象 a 和 b ,a == b 只是在判断它们管理的是不是一块内存空间。Java 相同字符串的共享内存空间的分配方案也不是 100% 的,它只是在合适的情况下共享空间,所以两个内容相同的字符串也不一定指向同一个内存空间。它的比较有时相等有时不相等都是很有可能的,所以不要那么做!
比较操作 a.equals(b) 使用 String 的 equals 方法即可。

那到底怎么修改字符串呢?你可以使用 + 运算符和 substring 方法进行拼接和切割字符串最后再赋值给原字符串。但这会有很大的开销,因为中间结果要生成很多不可改变的 String 对象。可以使用 StringBuilder 或者 StringBuffer。


参考资料

C++ 基础类型标准
C++ 标识符标准
The Java® Language Specification
Java 核心技术 卷I —— Cay S. Horstmann、Gary Cornell
深入理解 Java 虚拟机 —— 周志明

本文标题:Java 与 C++ 细节差异 (一)

文章作者:赵砚潇

发布时间:2018年07月01日 - 23:07

最后更新:2018年07月05日 - 01:07

原始链接:https://blog.zyx.sh/2018/07/01/cpptojava/

许可协议: 署名-非商业性使用-相同方式分享 4.0 国际 转载请保留原文链接及作者。

Donate comment here