`
softstone
  • 浏览: 480776 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

跳入JAVA

阅读更多

跳入JAVA

透明 译

我看到,很多人在问:我是否应该学习JAVA;我看到,很多人在问:JAVA和C++哪个更好?

 我想我没有资格回答这些问题。但我想CUJ有资格。本文出自CUJ的import.java.*专栏 ——以CUJ而开设JAVA专栏,这本身已经证明广大C++程序员对JAVA的重视程度。究竟哪个好?好在何处?是否应该学?应该怎样学?应该学什么?……太多的问题。希望本文能起抛砖引玉之效。希望本文的读者能亲自看看这些专家指点,从而形成自己的判断。

 本文作者Chuck Allison对程序设计有丰富的经验,并且有多年使用C++的历史。而我也是一个C++的狂热爱好者。因此,我想这篇文章应该很对你——C++开发者——的胃口。

一次JAVA旅游的质量取决于本次旅游的向导。我们是幸运的,Chuck Allison是一个经验丰富的向导,无论对于C++还是对于JAVA都是。

--------------------------------------------------------------------------------

 再一次向你问好。“import java.*”欢迎你们——C/C++程序员们——来学习JAVA。在你以前的案例中,你可能有很多理由想要这样做。JAVA远不止是一种增强WEB页面的机制。它是一种用途广泛的面向对象程序设计语言,它建立在对软件工程工业的许多需求之上。当你开始学习JAVA之后,你将成为一个更好的C/C++程序员,因为JAVA的语法与C++非常相似。并且,如果你是一个喜欢面向对象编程原则的C++程序员,你将感到象是回到了自己的家。就如同很多C程序员选择了C++一样,许多C++程序员正在寻找自然转向JAVA的途径。

 我将分析JAVA所有的特征:语言、库、以及思想,但是从C/C++的视角。这意味着我不是一个JAVA的盲目信仰者(可能是一个狂热爱好者,但不是一个盲目信仰者:-))。实际上,我对C++的掌握和爱好可能在某些时候让我偏向另一个方向。这也意味着我将可能做一些坏不堪言的事情:我将比较这两种语言并尝试说明一些有用的东西。在这篇文章中,我只提供对JAVA的一个大概的观察,而把具体的教学留在将来的部分中。但首先,我让你看一点背景。

关于“骗局”的一些话

 在1984年与Apple MacIntosh的联系中,我第一次听到了“面向对象”这个术语。当我问“面向对象是什么意思”时,他们胡乱说了一通关于屏幕上的图形对象的话。这就是一个神话:图形化用户接口让某些东西变得面向对象。

 在20世纪80年代中期,“面向对象”这个术语被滥用,以至于刺穿这个骗局唯一的方法就是:找到一种毫无疑义的面向对象编程语言并使用它。当我在1987年发现LISP时,我开始领悟面向对象的思想,并对“语言对封装、继承和多态的支持”有了第一手的经验。

 在那一年的晚些时候,我参加了某个关系数据库管理系统(relational DBMS)厂商的现场销售演示会。我已经非常精通他们的产品,并且我是我们公司内的“专家”。在演示会的过程中我听到这样的说法:“<产品X>是面向对象的。”我跑到前面问那位演示者:“你说<产品X>是面向对象的,这是什么意思?”然后我在整个演示会中再也不说一句话。其后的讨论表明,<产品X>根本不是面向对象的——它只是他们经常说的一种东西:骗局。

 你也许知道,70年代的时髦词汇是“结构化设计”,它最终在80年代的工业中得到了很好的应用;80年代的骗局是“面向对象”,而它正是今天的正统。那么,今天的骗局是什么?模式,我猜;以及,是的,JAVA。

基础 vs. 骗局

 C++的声望在没有任何推销的情况下如此爆炸性的增长,这是件有趣的事。在1982年,C++的设计者Bjarn Stroustrup面临一个困难的选择:对“C with Classes”(后来被命名为C++)的用户的支持吞噬掉了他一大半的时间,但还没有足够的用户让他有资金成立一个正式机构。对于这种情况,Bjarne说:

 “我看只有两种脱离困境的办法:

1. 停止支持C with Classes。
2. 开发一种更好的新语言,使它拥有足够多的用户,以获得足够的资金来支持和发展一个机构。当时我估计至少需要5000个工业用户。

 第三种选择——通过推销(骗局)来增加用户数量——从来没有在我的脑海中出现过[1]。”

 在1991年,C with Classes诞生后的第12年,C++的用户数量已经达到了四十万,而且这个数量每7.5个月就翻一番[2]。(一点点数学知识告诉我:如果这个增长率一直保持下去,到2000年时地球上的每个人都将是C++开发者——一个真正可怕的Y2K问题!)

 因为没有计划周密的销售计划,而且,因为C++是如此“复杂的语言”(也许我们曾经听到过这种说法),我们可以相当有把握的说:C++只靠它的技术优势成为了面向对象开发工具的领袖。就和以前的C语言一样,C++从基础做起,它满足开发者的热情,它不断增强自己的能力以满足更多的需要。

 但是,C++快速成长的故事与JAVA的故事没有任何相似之处。

JAVA人

 在Bruce Eckel——著名的作者和教授——的JAVA公开讨论会上,他送给每个与会者一件T-shirt。当你穿上它时,在你的左胸上有一个图案:一个原始人正为生活而奔波。Bruce将这个人叫做“JAVA人”,因为他正代表着你和我和大多数现代计算机工业的从业者——我们正试图跟上JAVA的浪潮。稍微浏览一下JAVA库,你就会看到这个浪潮发展的速度。当太阳微系统公司(SUN)在1995年中期推出JDK(JAVA开发包)版本1.0时,它的库里有212个类和接口。其后1997年的1.1版有504个。现在的1.2版JDK库中有1592个类和接口(以及13635个方法),而且它还在beta测试阶段中!而且,好象几个新增加的语言特性(内嵌类、新的事件模型、Swing组件、可插入VM体系等等)还不足以让我们的脑子和手指忙乱似的,JAVA的每个版本还都会反对以前的许多类和方法——我们还必须忘掉他们。

 美国公司在应用新技术方面都有略微保守的传统。我所工作过的三家大公司都只首先选用ANSI标准定义过的编程语言。这就是我在1978年我的第一份工作中仍然使用Fortran的原因。直到1986年,我才偷偷在我的工作中引入了C语言——C语言的标准化在几年之后才完成,但它当时已经有16年的历史、而且非常稳定。我第一次能正式在工作中使用C++是在1994年——在它被发明之后的第15年、公开之后的第9年、标准化之后的第5年。一般来说,IT公司只使用那些“得到验证的技术。”

 那么,为什么几乎所有主要的软件厂商都不顾新的JAVA语言的不稳定性而飞快的提供了JAVA工具来跟上需要呢?为什么JAVA能对这么多通常谨小慎微的大公司造成如此的影响呢?相关的事件还包括:我在这个春天向一家非常保守的公司传授JAVA的知识,这样他们可以用JAVA来重写他们的国内记帐系统。这是为什么?

 当然,答案很简单:Internet。当访问Internet已经成为家庭日常时,JAVA来了。“自由发布”当然没有错,但正是Internet让“自由发布”切实可行。添加applet的能力是无可争议的。applet让静态的页面活动起来,这从我国的CFO们手中诱惑出了无数的美圆。

 所以,骗局——呃,我是指,推销——是答案中理所当然的一部分。在1996年我与Bjarn Stroustrup的一次会见中,我问他对“JAVA革命”有什么想法。他回答我:

 “如果我没有兼容C语言的约束,我肯定也不会设计出JAVA这样的语言。可是,SUN能靠它获得如此多的美圆,这让我感到惊讶。这是不会被忘记的一课,并且这将是单个程序员、小公司和学院的恶兆。如果人们坚持要对C++和JAVA进行比较——看起来他们正在这样做——我建议他们看看D&E(The Design and Evolution of C++),看看C++为什么是现在这个样子,并考虑这两种语言在设计标准中的效果。C++和JAVA的差异不止是表面上的,并且不可能有哪个语言拥有所有的优点。[3]

牛肉在哪里?

 推销可能可以吸引我们的注意力,但不能保证持续的成功。尽管JAVA革命仍在继续,但现在Javascript和GIF动画已经做了我们以前用applet做的大多数工作。JAVA获得持续的成功,那是因为在骗局的背后它有自己的价值。JAVA对程序员有吸引力,因为它是一种干净的、设计良好的软件开发工具,并且学习它不是“太困难”。JAVA对开发投资者有吸引力,因为它强调对象和包,还因为它的虚拟机体系,因为它支持可控的、划算的、(通常)安全的应用程序建造、发布途径。除了操作系统厂商之外,所有人都喜欢“编写一次,到处运行”的概念。而且JAVA对网络编程举世无双的支持让它在电子商务领域中获胜。让我们面对这样一个事实:JAVA很酷!

 但是,不要就这样把你的C++编译器搁置起来。JAVA不可能做所有事。这也就是它支持JNI(JAVA固有接口)的原因。在运行速度确实重要的地方,C++仍然是胜利者(至少现在是)。而且,尽管SUN已经发布了嵌入式JAVA的规范,你仍然可以肯定:JAVA取代C作为嵌入式编程混合语言还需要一段时间。

 另外,JAVA并不象你想象的那么容易学习。在我前面提到过的为某公司进行的教学的第四天,相当数量的学生带着疲惫的表情说:“伙计,这并不象我想象的那么容易!”(在我的记忆中,那天我们在谈论对象克隆、反射和I/O。)我想Larry O'Brien做出了最好的总结,他说:“说‘JAVA比C++简单’,就好象说‘2000年比珠穆朗玛峰短’一样。”JAVA是复杂的,但复杂的方式与C++不同。它是否真的更简单,这取决于你和你的需要。解决实际问题从来不会容易,不管你使用什么工具。

缺少了什么?

 JAVA来自Oak,一种剥除了C++的一些特性以用于嵌入式系统的语言。虽然你现在从JDK里得到的JAVA比Oak大(并且不再适用于嵌入式应用),但JAVA还是不支持C++的下列特性:

 显式指针和引用
 delete运算符
 析构子
 默认参数
 模板
 全局函数和数据
 局部静态数据
 宏
 算符重载
 多继承
 声明和定义分离

 前两个条目看起来似乎是JAVA的一个大卖点。指针是最难掌握的概念之一,而“赶走指针”正是C/C++从业者共同的愿望。但是,你仍然必须理解“间接使用”的基础,否则你还是无法使用JAVA的对象(那么你也就无法使用JAVA了)。所有的JAVA对象都是动态的,并且存在于堆空间中。你使用new运算符来创建一个JAVA对象。

Foo f = new Foo();

 f实际上还是一个指针,它指向堆空间中真正的Foo对象,但你只能把f作为访问对象的工具来使用;比如说,你不能对f做算术运算。为了让事情对我们这些C/C++程序员更简单,我们需要用“指针”或“引用”之外的一个术语来表示f。“句柄”看起来是个不错的术语。然后,为了访问一个类成员,你可以在句柄上使用普通的成员选择算符,例如f.x。如果你把一个对象当作参数传递给一个函数,实际上是句柄的一个拷贝被传递。就象C一样,所有的参数都是按值传递的,所以JAVA没有与C++的引用等价的东西。

 这意味着你不能写一个函数来有效的交换它的两个参数,但函数可以修改参数对象的数据成员。举个例子,假设我定义了Foo类,它有一个int型成员x:

class Foo {
    public int x;
}

 那么下列的swap函数将交换其参数对象的x成员值:

public static void
swap(Foo f1, Foo f2) {
    int temp = f1.x;
    f1.x = f2.x;
    f2.x = temp;
}

 这样的行为和下列的C函数本质上是相同的:

void
swap(struct Foo* f1,
    struct Foo* f2) {
    int temp = f1->x;
    f1->x = f2->x;
    f2->x = temp;
}

 现在看看上面这个列表的第二项。什么?没有delete算符?多么不负责任!不,不是的。程序员不需要将使用过的内存返回到堆空间中,因为JAVA拥有垃圾收集机制,它将自动回收所有不被引用的存储空间。好消息是:你不必担心内存泄漏。坏消息是:你不会知道垃圾收集将在何时运行、哪些对象将在何时被回收。这使你不可能通过垃圾收集来控制资源的回收,这也就是JAVA没有析构子的原因之一。如果你希望在某个特定时间点释放某些资源,你必须显式释放。

有什么?

 我们讲了那么多JAVA没有的东西。它拥有的是对类和对象的牢固的支持,以及一个特点丰富的库——这个库能满足你能想象到的任何编程任务。C++程序员在学习JAVA时将发现下列重要的项目:

 所有东西都属于某个类。(记住,没有全局的东西。)
 你不必担心内存泄漏。
 字符按照Unicode编码。
 异常不是可选的。(做好处理异常的准备吧。)
 库支持线程和网络编程。
 内建(基本)类型在所有平台上的大小都一样。

 为了说明第一点,我在这里给出了一个完整的“交换”的程序:

// Swap.java
class Foo {
    public int x;
}

public class Swap {
    public static void swap(Foo f1, Foo f2) {
        int temp = f1.x;
        f1.x = f2.x;
        f2.x = temp;
    }
    public static void
    main(String[] args) {
        Foo f1 = new Foo();
        f1.x = 1;
        Foo f2 = new Foo();
        f2.x = 2;
        swap(f1, f2);
        System.out.println(f1.x);  // 2
        System.out.println(f2.x);  // 1
    }
}

 请注意,这里没有任何类似delete算符的东西。

 正如这个列表所提到的,JAVA程序完全由类组成,每个类都包含字段(数据成员)和/或方法(成员函数)。这个简单的组织,再加上我将在以后的文章中介绍的方便的库包装机制,为大规模应用的管理提供了一种实用的规范。

 为了使用JDK编译这个程序,我在命令行中做如下输入:

C:> javac Swap.java

 JAVA源代码的文件扩展名是.java。每个文件中必须至少有一个public类,这个类的名字必须与文件名(不包括.java)相同。javac命令为每个选定的.java文件生成一个.class文件。.class文件包含字节码,字节码将由你的JVM(JAVA虚拟机)来执行。java命令会装载JVM,并指示JVM开始执行.class文件——首先翻译main方法中的字节码,就象这样

C:> java Swap
2
1

 Swap类自己不包含数据,并且它所有的方法都是static的,这意味着它们不需要一个Swap对象就可以执行(就象在C++里一样)。实际上,Swap类的存在只是提供一个地方来安置swap方法和main方法。System.out就是JAVA中等价于stdout的东西,而println方法将把参数转换成字符串然后输出。

 一个真正工作的JAVA程序通常包括多个.class文件。当一个类需要调用其他类的服务时,JVM搜索后者相应的.class文件。因为JAVA中的每个函数都是某个类的方法,所以在一个程序中有多个main方法也不会造成冲突。实际上,通常我们会出于测试的目的在每个public类中都放一个main方法。不存在唯一的程序级的main方法也就意味着main方法不会返回什么结果给操作系统,但JAVA为这个目的提供了一个特殊的方法,类似于C的exit函数。

 正是虚拟机体系给了JAVA“编写一次,到处运行”的可移植性。只要一个平台支持JVM,它就可以运行来自任何平台的字节码。但是,因为JVM是一个解释器,在与纯编译语言的比较中,它也表现出了速度上的劣势。为了部分的补偿这一点,JDK现在使用了“即时”(JIT)编译器,它在类第一次被装载时将字节码编译成固有代码。这样代码只需要被解释一次,而不是每次被调用时都需要解释。你还可以使用其他的商用JIT编译器和纯固有代码编译器。

总结

 正如你能看到的,JAVA的语法几乎与C++完全一样——语句以分号结尾,大括号内的复合语句。但是请注意,类的定义不以分号结尾。此外,JAVA中没有struct关键字(这不会让任何人烦恼)。你还必须为每个字段或方法定义单独指定访问级(public/private/protected),这逼迫我们更多的敲打键盘。也许最大的文化冲突是格式化I/O 。比如说,JAVA没有等价于scanf或printf的东西,这使JAVA的命令行I/O成为了对潜在的C/C++移居者纯粹的打击。但是,这种命令行I/O在今天这个图形化用户界面的世界里变得越来越不重要,并且我在今后的文章中将展示JAVA的I/O包中的一些非常完善的特性。

 这就是所有了吗?不,这只是我的系列文章的开头。我在第一部分里的目的是为这个系列做一些铺垫,并稍微吊吊你的胃口。在后续的部分中,我将从基本数据类型、运算符和控制结构(简单的材料)开始,对JAVA语言做深入的观察。如果你对这个主题的书感兴趣,你最好浏览CUJ网站(www.cuj.com)的“编辑角”,那里有一个“基本读物列表”。我推荐下列两本最好的书:

1. Arnold & Gosling. The Java Programming Language, Second Edition (Addison-Wesley, 1998)。由JAVA的发明者所著的一本庄重、简练的语言介绍。
2. Bruce Eckel. Thinking in Java (Prentice-Hall, 1998) 。市面上能买到的最友好、最全面的JAVA书籍。

请开始享受你的JAVA之旅吧。

参考书目

[1] Bjarne Stroustrup. The Design and Evolution of C++ (Addison-Wesley, 1994), p. 63.
[2] Bjarne Stroustrup. The Design and Evolution of C++, p. 163-164.
[3] Chuck Allison. "C++: The Making of a Standard," C/C++ Users Journal, October 1996.

分享到:
评论

相关推荐

    java_应该这么学【板书】

    标题和描述中提到的"java_应该这么学",强调了学习Java时应注重基础知识的掌握,而非直接跳入高级框架的使用。首先,我们需要理解Java的核心概念,这包括面向对象编程、设计模式以及Java的高级特性。 面向对象编程...

    Java基础加强Java基础加强

    Eclipse还支持快捷键配置,如Alt+/用于内容提示,Ctrl+1进行快速修复,Ctrl+Shift+O自动导入所需包,Ctrl+Shift+F格式化代码,Ctrl+Shift+/和Ctrl+Shift+\分别用于添加和移除注释,F5、F6、F7用于程序调试时的跳入、...

    JAVA 推箱子游戏源码

    游戏是java实现的推箱子游戏源码,共三关,成功自动跳入第二关。

    Java eclipse 快捷键 大全

    - **F5/F6/F7/F8**:单步跳入/跳过/跳出/继续执行。这些快捷键是调试过程中常用的命令,有助于逐行检查代码执行流程。 - **Ctrl+H**:打开搜索窗口。可用于在项目中查找特定的字符串或代码片段。 - **Ctrl+Shift+S**...

    Java超经典笔记(初学最好的资料).pdf

    在调试Java程序时,可以使用IDE提供的单步执行功能,如F5(单步跳入)和F6(单步跳过)来逐行执行代码。如果在代码中发现错误或缺陷,这通常被称为“bug”,解决这些问题的过程称为“debug”。 Java数组的声明和...

    Java基础加强演示文稿

    - **F5 (跳入)**: 当调试时,遇到函数调用会进入该函数内部继续跟踪执行。 - **F6 (跳过)**: 继续执行代码直到当前函数调用结束。 - **F7 (跳出)**: 跳出当前函数调用栈。 **1.5 快捷键配置** - **内容提示**: `...

    Java软件开发实战 Java基础与案例开发详解 3-9 MyEclipse工具介绍 共13页.pdf

    - **F5**:单步跳入。进入本行代码中执行。 - **F6**:单步跳过。执行本行代码,跳到下一行。 - **F7**:单步返回。跳出方法。 - **F8**:继续。执行到下一个断点,如果没有断点了,就执行到结束。 - **Ctrl+R**:...

    JAVA学习方法与数组

    - **单步跳入(F5)**:进入当前方法体执行。 - **恢复执行(F8)**:继续执行直到下一个断点或程序结束。 - **常用快捷键**: - **格式化代码(CTRL+SHIFT+F)**:自动格式化选中的代码或整个文件。 - **快速...

    java学习详细PPT

    我们可以从这些描述中抽取对象的特征,比如它们的生活环境、习性等,以及它们的行为,如狗的"摇尾巴"和"旺旺叫",猫的"喵喵叫"和"咕噜咕噜"声,以及青蛙的"呱呱呱"和"扑通跳入水中"。这些行为可以视为对象的方法,而...

    Java学习笔记

    - **调试快捷键**:`F6`(单步跳过)、`F5`(单步跳入)、`Ctrl+F11`(运行)、`F11`(调试)。 - **项目创建与运行步骤**: 1. 创建Java项目(一级目录)。 2. 在二级目录`src`与`bin`中创建程序包。 3. 编写...

    韩顺平 java基础加强笔记整理

    - **F5**: 跳入,即进入函数内部执行,适合于深入分析函数内部逻辑。 - **F6**: 跳过,即在当前层级上逐行执行代码,不进入函数内部,适用于快速浏览代码流程。 - **F7**: 跳出,即退出当前正在执行的函数,返回...

    Java Eclipse进行断点调试.docx

    在Java开发过程中,Eclipse作为一款强大的集成开发环境(IDE),提供了丰富的调试功能,使得开发者能够有效地定位和修复代码中的问题。以下是如何在Eclipse中进行Java程序的断点调试的详细步骤和相关知识点: 1. **...

    java-web分析与设计

    有时,开发者可能会过于急躁,直接跳入编码,但这可能导致缺乏结构和方向。即使计划是立即开始编码,也应该设定目标和里程碑,以保持对进度的控制。 阶段1是需求分析和系统规格定义。需求分析是明确项目目标,确保...

    java web myeclipse 快捷键

    Java Web MyEclipse 快捷键 Java Web MyEclipse 提供了多种快捷键,以提高开发者的工作效率。下面是一些常用的快捷键: 编辑器 *Ctrl+/:显示所有快捷键 *Ctrl+A:全选 *Ctrl+C:复制 *Ctrl+X:剪切 *Ctrl+V:...

    小崔java经验系列之eclipse手册

    8. **运行与调试**:单步返回使用`F7`,单步跳过用`F6`,单步跳入用`F5`,单步跳入选择使用`Ctrl+F5`,调试上次启动用`F11`,继续执行用`F8`,添加/去除断点用`Ctrl+Shift+B`,运行上次启动用`Ctrl+F11`,运行至行用...

    java_web笔记大全免费下载.doc

    - `F5` 跳入方法内部,`F6` 执行当前行,`F7` 退出当前方法,`Resume` 继续运行至下一个断点。 - 使用源码调试可以帮助理解程序执行过程。 4. **JUnit单元测试**: - 使用`@Test`注解标记公共的无参方法进行单元...

    【java源代码】病人挂号系统网站(完整前后端+mysql+说明文档+LW).zip

    功能说明: ... ... ... 4.医生可以收到针对自己科室所挂号的患者挂号时所发送的提醒邮件。 5.医生可以对自己所在科室的信息...开发语言:Java JDK版本:JDK1.8 数据库:mysql 5.7 数据库工具:Navicat11 开发软件:eclipse/idea

    Java Eclipse进行断点调试的方法

    在调试过程中,使用快捷键可以提高效率,例如单步返回F7,全局单步跳过F6,全局单步跳入F5等。 七、执行完程序 当程序执行完毕后,可以通过Variables查看所有变量的值,並可以更改变量的值。 八、添加反编译插件 ...

Global site tag (gtag.js) - Google Analytics