作为一名Java开发者,是选择C还是C++?

11

我已经从事Java职业开发5年了。最近,我不得不深入研究JNI以调用一些Windows特定的函数。

这个经历凸显了我对C(或者也包括C ++)语言的薄弱掌握。我对C的唯一介绍是11年前在高中读过的一本简易书。

我知道这段时间内两种语言都有进步,尤其是C++和标准库。

学习C或C ++是否合适?哪些书最好?

大家还有什么关于Windows编程的推荐吗?我可以通过MSDN阅读足够了解某些API调用,但我感觉在“大局”方面可能会错过一些东西。

谢谢


我发现自己处于某种相似的情况中。当需要时,我想学习Win32 API来增强我的Java应用程序。但是我找不到一个好的C++ Win32 API资源。或者可能只是我,一切看起来与我以前的javadoc非常不同 :( - OscarRyz
Oscar: http://msdn.microsoft.com/en-us/library/aa383749(VS.85).aspx 是你需要的文档。是的,它看起来表面上与javadoc不同,但它同样详细,并且应该告诉你所有你需要知道的。 Casey,你想学习C/C++本身,还是只是调用win32函数? - jalf
11个回答

38

好问题。表面上看来,推荐C++是很明显的选择,因为“它像Java一样是面向对象的”。唯一的问题是,这并不完全正确。C++确实允许OOP,但这只是C++支持的几种范例之一。把C++当作一个面向对象的语言(尤其是把它当作Java)将只会导致挫败感。

问题在于Java和C++实际上没有太多共同点。Java程序员通常认为Java受到了C++的启发,但这只有在你说C++指的是最早期的C++版本时才是真的,那可能更恰当地称为“带类的C”。 从那时起,C++已经完全变成了自己的语言,在处理事物方面也有自己的方式。自那时以来,C++的变化可能比Java还要大。一个Java程序员如果回到过去,仍然能够理解今天的Java代码。但对于C++而言,情况就不一样了。所以我认为,C实际上比“现代C ++”更接近Java。如果你拿走Java的垃圾回收、类概念和其他一些抽象,你就会得到C。要想到达C++,你必须将类似数量的特性添加到我们假想的简化Java中。

此外,C++是一种非常复杂的语言,学习它需要很长时间。如果你没有好好学习它,你会一遍又一遍地自己给自己惹麻烦。

最后,这取决于你的目标。 C++比C更现代化,一旦学会了,就非常富有表现力和强大,令人惊讶的是,它甚至可以非常优雅而简洁。但是,它的学习曲线很陡峭。因此,从长远来看,我会推荐C++而不是C进行本地编程。

但是,如果你的目标主要是与Win32 API(或其他本地API)交互,你将不需要C ++。 Win32和大多数其他API都是用C编写的,而且您可能不需要非常复杂的代码来在Java和API之间进行接口。

关于学习Win32,你说得对,你需要的所有细节都在MSDN上。如果你想了解整体框架,Petzold是该主题的权威书籍。

哇,非常简洁的答案。+1 - Azreal
2
哪个是什么?我不是原帖作者,也不知道他的目标,所以我不能为他做决定。我感觉最好的办法是描述每种语言可能更可取的情况。 - jalf

8

我猜这取决于你的目标。

如果你想更接近机器,那么使用C。

如果你想补充在C之上的OO Java-like层的知识,那么使用C++。

《Accelerated C++》(sanitised Amazon link)是一本很棒的书,可以从C++的角度学习C++,而不仅仅是附加其他部分的C。

而对于学习C,IMHO,《K'n'R C》(sanitised Amazon link)仍然是最好的选择!

顺便说一句,对于C++,请跟随Scott Meyers在《Effective C++》系列书籍中的智慧!以及他的《Effective STL》书籍。

希望有所帮助。

祝好,

Rob


Scott Meyers的推荐非常棒。我认为他的书非常出色。我从未见过《Effective STL》这本书。当它出版时,我已经转向Java了。 - duffymo

5
学习足够的C++,将其用作“更好的C”。你不必尝试将所有内容映射到Java的理解上。你只需要能够使用C ++对象作为抽象数据类型,new和delete等。如果STL也随之而来,那就更好了。
真正的问题是:为什么你认为JNI是如此必不可少?Windows调用会破坏任何保持应用程序可移植性的想法。我旁边坐着一个人,他正在研究使用JNI的Java应用程序。它会随机使服务器崩溃并出现SEG FAULT。他的假设是堆填满了,调用了一个调用malloc在堆上分配空间的JNI调用。一旦没有可用空间,该例程不会检查返回指针是否为空,释放该指针,然后服务器就会崩溃。他仍在努力在本地再现错误,因为它需要在GC启动之前精确计时调用JJNI方法。
您百分之百确定需要使用JNI吗?只是问问而已...

非常同意。你真的想避免C语言最糟糕的部分,比如写int foo();而不是int foo(void);。 - MSalters

4
如果您对Java有很好的理解,我建议从C语言开始学习。如果您直接开始学习C++,它与Java之间有很多不同之处,您可能会不喜欢它。
如果您想认真学习这两种语言,我建议阅读Bjarne Stroustrup的《C++程序设计语言》和Dennis Ritchie的《C程序设计语言》。

3
我认为对于您而言,学习C++比学习C容易得多。
如果您一直使用Java,那么放弃类、异常、引用形式、动态绑定等便利功能以及良好的库可能会很困难。
然而,您应该先学习C,以确保真正了解底层原理,并体验指针及其使用以及在“没有防护装备”的情况下工作的感觉。
一旦掌握了这些技能,再学习C++中的继承机制以及与Java(例如多重继承)的区别。

@Uri,嘿,我相信Joel不会同意你先学习C语言。开个玩笑啦 (-: - Rob Wells
原帖描述听起来像他准备做更多全职的C/C++而不仅仅是JNI。如果你习惯了类,那么在C中模仿它们是毫无意义的。C是一门很棒的语言,但它也有其局限性。 - Uri
但我并不是在建议你不学习C++,我的建议是先从C开始,然后再转向C++,因为它更适合现代项目,并且可以给你一些真正强大的东西,比如模板(boost、stl等)。 - Ismael
Java具有继承、模板和引用,因此这些概念对他来说应该很清楚。学习C++不应该是太大的挑战。 - Curtis Shipley
C++ 的模板更加棘手,它们带有许多关于解析、特化的规则,并且你可以实现编译时继承。 - Ismael
显示剩余7条评论

2
这真的取决于你的优点和缺点。如果你真的喜欢设计模式,那么我建议使用C ++,但如果你只需要在JNI中实现一些简单的方法,那么我建议使用C。在学习C++之前学习C应该会让你更好地理解内存管理,而不必担心C++的某些复杂性(构造函数调用顺序、析构函数和C++与Java之间的其他差异)。
我建议阅读Kernighan和Ritchie的《C程序设计语言》作为学习C的权威手册。http://www.amazon.com/Programming-Language-Dennis-M-Richie/dp/0876925964 如果你在*nix系统上,有大量关于不同函数的man页面文档。例如:

bash$ man malloc


C语言中的设计模式 - 它是最难处理的问题,但也是最好的练习。 - Tom

1
如果你想要一本关于C语言的优秀资源,那么Dennis Ritchie所著的《C程序设计语言》是你必须拥有的书籍。

我推荐K&R第二版。此外,还有盖伊·斯蒂尔的书。 - duffymo

0
如果您打算继续编写JNI代码,我强烈推荐使用C++。
特别是,JNI接口要求您获取(并随后释放)对Java对象的引用。使用C++自动变量,您可以使用“RAII”(资源分配即初始化)技术获取这些引用,从而使内存管理更加简单。

JNI 接口本身是基于 C 语言的。虽然 C++ 的 RAII(资源获取即初始化)机制使 JVM/环境资源更易于管理,但它确实会使问题变得复杂(因为 Java 对象与 C++ 对象非常不同)。 - Tom
我对Java与C对象之间的比较没有发表评论。但是我知道,一些简单的C++包装器可以极大地简化JNI代码,因为我已经做过了。那么,如何使用一个在退出时自动释放并且可以自动转换为(char *)的JNIString呢? - Alnitak

0
“你确定它们是必需的吗?只是问一下……”
“不幸的是,是的。”
“感谢大家的回答。”
“为了回答一些后续问题,我并不是想要转行学习C或C++。我只是想学习基础知识,这样当我需要编写一些代码时就不会感到手足无措了。”

如果你想替换你的Java经验,一定要学习C语言。我喜欢C++,但我认为它主要是专家级别的语言。由于其简单性,学习C作为第二门语言将更加高效。 - Tom

0
特别是,JNI接口要求您获取(并随后释放)对Java对象的引用。使用C++自动变量,您可以使用“RAII”(资源分配即初始化)技术获得这些引用,从而使内存管理变得更加简单。
谢谢,这很有帮助。其中一个让我感到越来越担心的领域是处理与JNI对象相关联的手动内存管理。

我不了解JNI,但是可能看一下boost::shared_ptr<>(请参见http://boost.org/)是个好主意。这会给你引用计数指针,如果对象不再被任何地方引用,它们会自动释放。 - sth
@Kevin - 在Java中,你已经被迫管理资源了-除了内存以外的所有资源。这意味着打开文件、共享内存段、网络连接等等。如果你专注于广义资源管理而不仅仅是内存管理,那么你将比许多Java开发人员更具优势。 - Tom

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