爪哇编程语言的历史

爪哇

 Java 是一种面向对象的编程语言,由 James Gosling 及其同事在 1990 年代初期在 Sun Microsystems 开发。与通常设计为编译为本地(机器)代码或在运行时从源代码解释的传统语言不同,Java 旨在编译为字节码,然后由 Java 运行(通常使用 JIT 编译)虚拟机。

该语言本身从 C 和 C++ 中借用了很多语法,但具有更简单的对象模型和更少的低级设施。 Java 与 JavaScript 只是远亲,尽管它们具有相似的名称并共享类似 C 的语法。

历史

Java 由 James Gosling 于 1991 年 6 月作为一个名为“Oak”的项目启动。Gosling 的目标是实现一个虚拟机和一种语言,该语言具有熟悉的类似 C 的符号,但比 C/C++ 具有更大的统一性和简单性。第一个公开实现是 1995 年的 Java 1.0。它承诺“一次编写,随处运行”,并在流行平台上提供免费运行时。它相当安全,其安全性是可配置的,允许限制网络和文件访问。主要的 Web 浏览器很快将其合并到安全“小程序”配置中的标准配置中。流行很快。随着“Java 2”的出现,很快就为大型和小型平台(J2EE 和 J2ME)设计了新版本。 Sun 还没有宣布任何关于“Java 3”的计划。

1997 年,Sun 与 ISO/IEC JTC1 标准机构以及后来的 Ecma International 接触以正式化 Java,但很快就退出了该过程。 Java 仍然是通过 Java Community Process 控制的专有事实标准。 Sun 免费提供大部分 Java 实现,收入来自 Java Enterprise System 等专门产品。 Sun 区分其软件开发工具包 (SDK) 和运行时环境 (JRE),后者是 SDK 的一个子集,主要区别在于 JRE 中不存在编译器。

哲学


Java 语言的创建有五个主要目标:


1. 应该使用面向对象的编程方法。

2. 应该允许同一个程序在多个操作系统上执行。

3. 它应该包含对使用计算机网络的内置支持。

4. 它应该被设计为安全地执行来自远程源的代码。

5. 通过选择被认为是其他面向对象语言的优点的部分,它应该易于使用。


为了实现网络支持和远程代码执行目标,爪哇 程序员有时会发现有必要使用诸如 CORBA、互联网 通信引擎或 OSGi 之类的扩展。


面向对象

第一个特征,面向对象(“OO”),指的是一种编程和语言设计方法。尽管对 OO 有多种解释,但一个主要的区别思想是设计软件,使其操作的各种类型的数据与其相关操作结合在一起。因此,数据和代码被组合成称为对象的实体。一个对象可以被认为是一个自包含的行为(代码)和状态(数据)包。原则是将变化的事物与保持不变的事物分开;通常,对某些数据结构的更改需要对操作该数据的代码进行相应的更改,反之亦然。这种分离成连贯的对象为软件系统的设计提供了更稳定的基础。其目的是使大型软件项目更易于管理,从而提高质量并减少失败项目的数量。

OO 编程的另一个主要目标是开发更多通用对象,以便软件可以在项目之间变得更可重用。例如,一个通用的“客户”对象应该在不同的软件项目之间具有大致相同的基本行为集,尤其是当这些项目在某些基本层面上重叠时,就像它们在大型组织中经常做的那样。从这个意义上说,软件对象有望更多地被视为可插拔组件,帮助软件行业从现有的和经过良好测试的部分构建项目,从而大大减少开发时间。软件可重用性的实际结果参差不齐,主要有两个困难:对真正通用对象的设计知之甚少,缺乏广泛交流重用机会的方法论。一些开源社区希望通过为作者提供传播关于一般可重用对象和对象库的信息的方法来帮助缓解重用问题。

平台独立性

第二个特性,平台独立性,意味着用 Java 语言编写的程序必须在不同的硬件上以类似的方式运行。人们应该能够编写一次程序并在任何地方运行它。

这是大多数 Java 编译器通过将 Java 语言代码“中途”编译为字节码(特别是 Java 字节码)——特定于 Java 平台的简化机器指令来实现的。然后代码在虚拟机 (VM) 上运行,这是一个在主机硬件上用本机代码编写的程序,用于解释和执行通用 Java 字节码。此外,提供标准化库以允许以统一方式访问主机的功能(例如图形、线程和网络)。请注意,尽管存在显式编译阶段,但在某些时候,JIT 编译器会解释 Java 字节码或将其转换为本地机器指令。

还有一些 Java 编译器的实现可以编译为本地目标代码,例如 GCJ,移除了中间字节码阶段,但这些编译器的输出只能在单一架构上运行。

Sun 的 Java 许可证坚持所有实现都是“兼容的”。在 Sun 声称 Microsoft 实现不支持 RMI 和 JNI 接口并添加了自己的特定于平台的功能之后,这导致了与 Microsoft 的法律纠纷。作为回应,Microsoft 不再随 Windows 一起提供 Java,并且在最新版本的 Windows 中,Internet Explorer 无法在没有第三方插件的情况下支持 Java 小程序。但是,Sun 和其他公司已经免费为这些和其他版本的 Windows 提供了可用的 Java 运行时系统。

该语言的第一个实现使用解释型虚拟机来实现可移植性。这些实现产生的程序比编译为本地可执行文件的程序运行得更慢,例如,用 C 或 C++ 编写的程序,因此该语言因性能不佳而声名狼藉。使用多种技术,最近的 JVM 实现产生的程序运行速度比以前快得多。

第一种技术是像更传统的编译器一样简单地直接编译为本机代码,完全跳过字节码。这实现了良好的性能,但以牺牲可移植性为代价。另一种称为即时编译 (JIT) 的技术在程序运行时将 Java 字节码转换为本机代码,这导致程序执行速度比解释代码快,并在执行期间产生编译开销。更复杂的 VM 使用动态重新编译,其中 VM 可以分析正在运行的程序的行为,并有选择地重新编译和优化程序的关键部分。动态重新编译可以实现优于静态编译的优化,因为动态编译器可以基于有关运行时环境和加载类集的知识进行优化。 JIT 编译和动态重新编译允许 Java 程序利用本机代码的速度而不会失去可移植性。

可移植性是一个技术上难以实现的目标,Java 在这个目标上的成功有好有坏。尽管确实可以为 Java 平台编写在许多主机平台上表现一致的程序,但大量可用平台的小错误或不一致导致一些人模仿 Sun 的“一次编写,随处运行”的口号为“编写一次,调试到处”。

然而,独立于平台的 Java 在服务器端应用程序(例如 Web 服务、servlet 和 Enterprise JavaBeans)以及基于 OSGi 的嵌入式系统中非常成​​功,使用嵌入式 Java 环境。

自动垃圾收集

Java 的自动内存管理模型背后的一个想法是程序员应该免于必须执行手动内存管理的负担。在某些语言中,程序员分配内存以创建存储在堆上的任何对象,并负责稍后手动释放该内存以删除任何此类对象。如果程序员忘记释放内存或编写未能及时释放内存的代码,则可能发生内存泄漏:程序将消耗潜在的任意大量内存。此外,如果一个内存区域被释放两次,程序会变得不稳定并可能崩溃。最后,在非垃圾收集环境中,跟踪和完成分配的用户代码存在一定程度的开销和复杂性。

在 Java 中,自动垃圾收集避免了这个潜在的问题。程序员确定何时创建对象,Java 运行时负责管理对象的生命周期。程序或其他对象可以通过持有一个对象的引用来引用它(从低级的角度来看,它是它在堆上的地址)。当没有对对象的引用时,Java 垃圾收集器会自动删除无法访问的对象,从而释放内存并防止内存泄漏。如果程序员的代码持有对不再需要的对象的引用,则仍然可能发生内存泄漏——换句话说,它们仍然可能发生,但发生在更高的概念级别。

在语言中使用垃圾收集也会影响编程范式。例如,如果开发人员假设内存分配/回收的成本很低,他们可能会选择更自由地构造对象,而不是预先初始化、持有和重用它们。由于潜在的性能损失(大型/复杂对象的内部循环构造)的成本很小,这有助于线程隔离(无需同步,因为不同的线程在不同的对象实例上工作)和数据隐藏。瞬态不可变值对象的使用最大限度地减少了副作用编程。

比较 Java 和 C++,在 C++ 中可以实现类似的功能(例如,可以在 C++ 中设计特定类的内存管理模型,以显着提高速度并减少内存碎片),但可能会花费额外的开发时间和一些应用程序复杂性。在 Java 中,垃圾收集是内置的,开发人员几乎不可见。也就是说,开发人员可能不知道垃圾收集何时发生,因为它可能不一定与他们编写的代码显式执行的任何操作相关联。根据预期的应用程序,这可能是有益的,也可能是不利的:程序员无需执行低级任务,但同时失去了编写低级代码的选择权。


句法

Java 的语法很大程度上源自 C++。 然而,与结合了结构化、泛型和面向对象编程的语法的 C++ 不同,Java 是从头开始构建的,几乎完全面向对象:Java 中的一切都是对象,原子数据类型(序数 和实数、布尔值和字符),Java 中的所有内容都写在一个类中。

小程序

Java 小程序是嵌入在其他应用程序中的程序,通常嵌入在 Web 浏览器中显示的网页中。

// Hello.java
import java.applet.Applet;
import java.awt.Graphics;

public class Hello extends Applet {
public void paint(Graphics gc) {
gc.drawString("Hello, world!", 65, 95);
}
}

这个小程序将简单地绘制字符串“Hello, world!” 在小程序将在其中运行的矩形中。 这是使用 Java 的 OO 特性的一个稍微好一点的例子,因为该类显式扩展了基本的“Applet”类,它覆盖了“paint”方法并使用了 import 语句。


<!-- Hello.html -->
<html>
<head>
<title>Hello World Applet</title>
</head>
<body>
<applet code="Hello" width="200" height="200">
</applet>
</body>
</html>

使用 <applet> HTML 元素将小程序放置在 HTML 文档中。 applet 标签设置了三个属性:code="Hello" 指定了 Applet 类的名称,width="200" height="200" 设置了小程序的像素宽度和高度。 (Applet 也可以使用 object 或 embed 元素嵌入到 HTML 中,尽管 Web 浏览器对这些元素的支持不一致。

小服务程序

Java servlet 是服务器端 Java EE 组件,可生成对来自客户端的请求的响应。

/ Hello.java
import java.io.*;
import javax.servlet.*;

public class Hello extends GenericServlet {
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException
{
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
pw.println("Hello, world!");
pw.close();
}
}

import 语句指示 Java 编译器包含来自 java.io 和 java.lang 的所有公共类和接口。 servlet 包在编译中。 Hello 类扩展了 GenericServlet 类; GenericServlet 类为服务器提供接口,将请求转发到 servlet 并控制 servlet 的生命周期。

Hello 类覆盖了 Servlet 接口定义的 service(ServletRequest, ServletResponse) 方法,为服务请求处理程序提供代码。 service() 方法传递一个包含客户端请求的 ServletRequest 对象和一个用于创建返回给客户端的响应的 ServletResponse 对象。 service() 方法声明,如果问题阻止它响应请求,它将抛出异常 ServletException 和 IOException。

调用响应对象中的 setContentType(String) 方法将返回数据的 MIME 内容类型设置为“text/HTML”。响应中的 getWriter() 方法返回一个 PrintWriter 对象,该对象用于写入发送到客户端的数据。调用 println(String) 方法来编写“Hello, world!” string 到响应,然后调用 close() 方法关闭打印写入器,这会导致已写入流的数据返回给客户端。


摇摆应用

Swing 是 Java SE 平台的高级图形用户界面库。

// Hello.java
import javax.swing.*;

public class Hello extends JFrame {
Hello() {
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
add(new JLabel("Hello, world!"));
pack();
}

public static void main(String[] args) {
new Hello().setVisible(true);
}
}

import 语句指示 Java 编译器包含 java 中的所有公共类和接口。编译中的swing包。 Hello 类扩展了 JFrame 类; JFrame 类实现了一个带有关闭控制的标题栏的窗口。

Hello() 构造函数通过首先调用继承自 JFrame 的 setDefaultCloseOperation(int) 方法来初始化框架,以设置选择标题栏上的关闭控件时的默认操作为 WindowConstants.DISPOSE_ON_CLOSE——这会导致 JFrame 在框架被关闭(而不是仅仅隐藏),这允许 JVM 退出并终止程序。接下来,为字符串“Hello, world!”创建一个新的 JLabel。并调用继承自Container超类的add(Component)方法将标签添加到框架中。调用继承自 Window 超类的 pack() 方法来调整窗口大小并布置其内容。

main() 方法在程序启动时被 JVM 调用。它实例化一个新的 Hello 框架,并通过调用继承自 Component 超类的 setVisible(boolean) 方法以布尔参数 true 显示它。请注意,一旦显示了框架,退出 main 方法不会导致程序终止,因为 AWT 事件分派线程一直保持活动状态,直到所有 Swing 顶级窗口都被处理掉。

外观和感觉

使用 Swing 工具包用 Java 编写的 GUI 应用程序的默认外观与本机应用程序非常不同。可以通过 Swing 的可插入外观和感觉系统指定不同的外观和感觉。 Windows、GTK 和 Motif 的克隆由 Sun 提供。 Apple 还为 Mac OS X 提供了 Aqua 外观。虽然这些外观的先前实现被认为是缺乏的,但 Java SE 6 中的 Swing 通过使用底层平台的更多原生小部件绘制例程解决了这个问题。或者,可以使用第三方工具包(例如 wx4j 或 SWT)来增加与本机窗口系统的集成。

缺乏 OO 纯度和设施

Java 的原始类型不是对象。原始类型将它们的值保存在堆栈中,而不是对值的引用。这是 Java 设计者出于性能原因的一个有意识的决定。因此,Java 不被认为是一种纯粹的面向对象的编程语言。但是,从 Java 5.0 开始,自动装箱使程序员能够将基本类型视为其包装类进行编写,并在它们之间自由交换以提高灵活性。 Java 设计人员决定不实现其他 OO 语言中存在的某些功能,包括:

* 多重继承

* 运算符重载

* 类属性

* 元组

Java运行时环境

Java 运行时环境或 JRE 是运行部署在 Java 平台上的任何应用程序所需的软件。 最终用户通常在软件包和 Web 浏览器插件中使用 JRE。 Sun 还分发了一个称为 Java 2 SDK(通常称为 JDK)的 JRE 超集,其中包括 Java 编译器、Javadoc 和调试器等开发工具。