C++程序员常见的Java陷阱/坑点有哪些?

7
作为问题所述,C++程序员转向Java时会面临哪些常见/重要问题?我正在寻找一些广泛的主题名称或示例以及工程师每天需要做出的调整。然后我可以进行深入阅读。
我特别关注那些多年来一直在C++中工作并不得不使用Java的工程师的意见,但其他人的建议甚至是书籍推荐也非常受欢迎。
14个回答

15
  • 在C ++中,您将使用析构函数来清理文件描述符、数据库连接等。天真的等价物是使用终结器。不要。永远不要。

相反,请使用此模式:

OutputStream os;
try {
  os = ... 
  // do stuff
} finally {
  try { os.close(); } catch (Exception e) { }
}

你最终会经常做那样的事情。

  • 如果你没有指定访问修饰符,在Java中,成员默认为包私有的,与C++不同,后者是私有的。包私有是一个令人恼火的访问级别,意味着它是私有的,但在同一包中的任何内容也可以访问它(在我看来这是个愚蠢的默认访问级别);
  • 没有堆栈分离。所有东西都在堆上创建(好吧,严格来说并非如此,但我们假装是的);
  • 没有传引用;
  • 函数指针的等效物是匿名接口。

1
传递引用/值是值得一读的内容:http://www.yoda.arachsys.com/java/passing.html - Dolph
请注意,Java 7具有“try-with-resources”机制,您可以通过实现“AutoCloseable”接口编写与之集成的类。详见:https://www.baeldung.com/java-try-with-resources#custom。 - starball

7
我的最大障碍是从C++转向Java时放弃了过程式编码。我习惯于在过程中将所有对象绑定在一起。在Java中没有过程式代码,我到处都做循环引用。我不得不学习如何在对象之间调用对象而不使它们相互依赖。这是最大的障碍,但也是最容易克服的。
第二个个人问题是文档。JavaDoc很有用,但许多Java项目误认为只需要JavaDoc即可。我在C++项目中看到了更好的文档。这可能只是代码外部文档的个人偏好。
第三点,Java中实际上有指针,只是没有指针算术。在Java中,它们被称为引用。不要认为您可以忽略事物指向的位置,否则会带来巨大的影响。
==和.equals是不相等的。
==将查看指针(引用),而.equals将查看引用指向的值。

你能否解释一下在 C++ 中可以使用但在 Java 中不能使用的循环引用类型? - Miserable Variable
我想表达的是,当我开始使用Java编程时,由于无法进行过程化编码,我开始制作循环引用。至少在我认识的开发人员中,制作循环引用被认为是不好的做法。 - WolfmanDragon

5

当想要创建一个拷贝构造函数时,不小心创建了一个引用:

myClass me = new myClass();
myClass somebodyElse = me; /* A reference, not a value copied into an independent instance! */
somebodyElse.setPhoneNumber(5551234);
/* Hey... how come my phone doesn't work anymore?!?!?  */

我想象中,C程序员是最能理解这个的人之一,因为他们与指针和引用值有着亲密的关系。 - Christian Mann

5

5

既然您提到了书籍推荐,一定要读 Effective Java, 2nd ed. ——它涵盖了大部分答案中列出的陷阱。


同意。这是一本非常棒的小书,旨在回答你所拥有的问题(陷阱、注意事项和最佳实践)。 - James McMahon

4
  • 没有多重继承,每个类都隐式地派生自java.lang.Object(它有许多重要的方法,你一定要知道和理解)
  • 通过实现接口,您可以拥有一种类似于多重继承的功能
  • 除了'+'(用于字符串)之外,没有运算符重载,绝对不允许自己进行运算符重载
  • 没有无符号数字类型,除了char,但char不应该被用作数字类型。如果必须处理无符号类型,则必须进行大量的强制转换和掩码操作。
  • 字符串不是以null结尾的,而是基于char数组且是不可变的。由于这个原因,使用+=在循环中追加长字符串的时间复杂度为O(n^2),所以不要这样做;改用StringBuilder。

加号:对象没有“按值传递”的选项。 - Neil Coffey

3

适应使用垃圾回收器。无法依赖析构函数清理GC未处理的资源。

所有内容都是按值传递,因为传递的是引用而不是对象。

除非需要克隆,否则没有复制构造函数。没有赋值运算符。

默认情况下,所有方法都是虚拟的,这与C ++相反。

明确支持接口 - C ++中的纯虚类。


2

Java中没有对象,只有对对象的引用。例如:

MyClass myClass;   // no object is created unlike C++.

但是:
MyClass myClass = new MyClass();   // Now it is a valid java object reference.

2

这些小小的语法差异让我感到困惑。缺乏析构函数。

另一方面,能够为每个类编写一个主函数(非常有用的测试工具)真的很好;当你适应之后,使用JAR文件的结构和技巧非常方便;而且,语义完全定义(例如,int在任何地方都是相同的)也非常好。


2

我最大的问题是时刻记住内存的所有权。在C++中,这是必须做到的,并且会在开发者的思维中形成一些难以克服的模式。在Java中,我可以忘记它(至少在很高的程度上),这使得一些算法和方法在C++中极其笨拙。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接