简单性
我们希望构建一个无须深奥的专业训练就可以进行编程的系统,并且要符合当今的标准惯例。因此,尽管我们发现C++不太适用,但在设计Java的时候还是尽可能地接近C++,以便系统更易于理解。Java剔除了C++中许多很少使用、难以理解、容易混淆地特性。在我们看来,这些特性带来地麻烦远远多于它们地好处。
的确,Java地语法是C++的一个“纯净”版本。这里没有头文件、指针运算(甚至指针语法)、结构、联合、操作符重载、虚基类等。然而,设计者并没有试图清除C++中所有不适当的特性。例如,switch语句的语法在Java中就没有改变。
“简单”的另一个方面是小。Java的目标之一是支持开发能够在小型机器上独立运行的软件。基本的解释器以及类支持大约仅为40KB,再加上基础的标准类库和线程的支持(基本上是一个自包含的微内核),大约需要增加175KB。
面向对象
简单地讲,面向对象设计是一种程序设计技术。它讲重点放在数据(即对象)和对象地接口上。用木匠打一个比方:一个“面向对象的“木匠始终首先关注的是所制作的椅子,其次才是所使用的工具;一个”非面向对象的“木匠主要考虑的是所用的工具。再本质上,Java的面向对象能力与C++是一样的。
开发Java时面向对象技术已经相当成熟。Java的面向对象特性与C++旗鼓相当。Java与C++的主要不同点在于多重继承,在Java中,取而代之的时简单的接口概念。与C++相比,Java提供了更丰富的运行时自省功能。
分布式
Java是一个丰富的例程库,用于处理像HTTP和FTP之类的TCP/IP协议。
Java应用程序能够通过URL打开和访问网络上的对象,其便捷程度就像访问本地文件一样。
健壮性
Java的设计目标之一在于使得Java编写的程序具有多方面的可靠性。Java非常强调进行早期的问题检测、后期动态的(运行时)检测,以及消除容易出错的情况————Java与C/C++最大的不同在于Java采用的指针模型可以消除重写内存和损坏数据的可能性。
Java编译器能够检测许多在其他语言中仅在运行时才能够检测出来的问题。至于第二点,对于曾经花费几个小时来检查由于指针bug而引起内存冲突的人来说,一定很喜欢Java的这一特性。
安全性
Java要适用于网路/分布式环境。为了实现这个目标,安全性颇受重视。使用Java可以构建防病毒、防篡改的系统。
从一开始 ,Java就设计成能够防范各种攻击,其中包括:
原先,Java对下载代码的态度是“尽管来吧!”。不可信代码在一个沙箱环境中运行,在这里它不会影响主系统。用户可以确信不会发生不好的事情,因为Java代码不论来自哪里,都不能脱离沙箱。
不过,Java的安全模型非常复杂,Java开发包(Java Development Kit,JDK)的第一版发布后不久,普林斯顿大学的一些安全专家就发现一些小bug会允许不可信的代码攻击主系统。
最初,安全bug可以快速修复。遗憾的是,经过一段时间之后,黑客已经很擅长找出安全体系结构实现中的小漏洞。Sun以及之后的Oracle为不断修复bug经历了一段很是艰难的日子。
遭遇多次高调攻击之后,浏览器开发商和Oracle开始越来越谨慎。Java浏览器插件不再信任远程代码,除非代码有数字签名而且用户同意执行这个代码。
注释:现在看来,尽管Java安全模型没有原先预想的那么成功,但Java在那个时代,确实相当超前。微软提供了一种与之竞争的代码交付机制,其安全性完全依赖于数字签名。显然这是不够的,因为微软自身产品的任何用户都可以证实,一些知名开发商的程序确实崩溃并对系统产生危害。
体系结构中立
编译器生成一个体系结构中立的目标文件格式,这是一种编译过的代码,只要Java运行时系统,这些编译后的代码可以i在许多处理器上运行。Java编译器通过生成与特定的计算机体系结构无关的字节码指令来实现这一特性。精心设计的字节码不仅可以很容易地在任何机器上解释执行,而且还可以动态地转换本地机器代码。
当时,为“虚拟机”生成代码并不是一个新思路。诸如Lisp、Smalltalk和Pascal等编程语言多年前就已经采用了这种技术。
当然,解释型虚拟机指令肯定会比全速运行机器指令慢很多。不过,虚拟机有一个选项,可以将执行最频繁的字节码序列转换成机器码,这一过程称为即时编译。
Java虚拟机还有一些其他优点。它可以检查指令序列的行为,从而增强其安全性。
可移植性
与C和C++不同,Java规范中没有“依赖具体实现”的地方。基本数据类型的大小以及有关运算的行为都有明确的说明。
例如,Java中的int永远为32位的整数,而在C/C++中,int可能是16位整数、32位整数,也可能是编译器开发商指定的任何其他大小。唯一的限制只是int的字节数不能低于short int,并且不能高于long int。在Java中,数值类型有固定的字节数,这消除了代码移植时一个令人头痛的主要问题。二进制数据以固定的格式进行存储和传输,消除了字节顺序的困扰。字符串则采用标准的Unicode格式存储。
解释型
Java解释器可以在任何移植了解释器的机器上直接执行Java字节码。由于连接是一个增量式且轻量级的过程,所以,开发过程也变得更加快捷,更加具有探索性。
高性能
尽管对解释后的字节码性能已经比较满意,但在有些场合下还需要更高的性能。字节码可以(在运行时)动态的转换成对应运行这个应用的特定CPU的机器码。
使用Java的头几年,许多用户不同意“对性能已经比较满意”的说法。不过,现在的即时编译器已经非常出色,可以与传统编译器相媲美,而且在某些情况下甚至超越了传统编译器,原因是它们有更多的可用信息。例如,即时编译器可以监控哪些代码频繁执行,并优化这些代码以提高速度。更为复杂的优化是消除函数调用(即“内联”)。即时编译器知道哪些类已经加载。基于当前加载的类集合,如果一个特定的函数不会被覆盖,就可以使用内联。必要时,以后还可以撤销这种优化。
多线程
多线程可以带来更快的交互响应和实时行为。
并发程序设计绝非易事,不过Java在这方面表现很出色,可以很好的管理这个工作。
动态性
从很多方面来看,Java与C或C++相比更加具有动态性。它能够适应不断发展的环境。库中可以自由的添加新方法和实例变量,而对客户端却没有任何影响。在Java中找出运行时类型信息十分简单。
当需要为正在运行的程序增加代码时,动态性将是一个非常重要的特性。一个很好的例子:从Internet下载代码,然后在浏览器上运行。如果使用C或C++,这确实难度很大,不过Java设计者很清楚动态语言可以很容易的实现运行程序的演进。最终,他们将这一特性引入这个主流程序设计语言中。
版本 | 年份 | 新语言的特性 | 类与接口的数量 |
---|---|---|---|
1.0 | 1996 | 语言本身 | 211 |
1.1 | 1997 | 内部类 | 477 |
1.2 | 1998 | strictfp修饰符 | 1524 |
1.3 | 2000 | 无 | 1840 |
1.4 | 2002 | 断言 | 2723 |
5.0 | 2004 | 泛型类、“for each”循环、可变元参数、自动装箱、元数据、枚举、静态导入 | 3279 |
6 | 2006 | 无 | 3793 |
7 | 2011 | 基于字符串的选择语句、菱形运算符、二进制字面量、异常处理增强 | 4024 |
8 | 2014 | lambda表达式、包含默认方法的接口、流和日期/时间库 | 4240 |
9 | 2017 | 模块、其他的语言和类库增强 | 6005 |
Java术语
术语名 | 缩写 | 解释 |
---|---|---|
Java Development Kit(Java开发工具包) | JDK | 编写Java程序的程序员使用的软件 |
Java Runtime Environment(Java运行时环境) | JRE | 运行Java程序的用户使用的软件 |
Server JRE(服务器JRE) | —— | 在服务器上运行Java程序的软件 |
Standard Edition(标准版) | SE | 用于桌面或简单服务器应用的Java平台 |
Enterprise Edition(企业版) | EE | 用于复杂服务器应用的Java平台 |
Micro Edition(微型版) | ME | 用于小型设备的Java平台 |
Java FX | —— | 用于图形化用户界面的一个备选工具包,在Java11之前的某些Java SE发布版本中提供。 |
OpenJDK | J2 | 一个过时的术语,用于描述1998~2006年之间的Java版本 |
Software Development Kit(软件开发工具包 | SDK | 一个过时的术语,用于描述1998~2006年之间的JDK |
Update | u | Oracle公司的术语,表示Java 8 之前的bug修正版本 |
NetBeans | —— | Oracle公司的集成开发环境 |
已经看到,JDK 是Java Development Kit的缩写。有点混乱的是:这个工具包的版本1.2~版本1.4被称为Java SDK。在某种场合下,还可以看到这个过时的术语。在Java10之前,还有一个术语是Java运行环境(JRE),它只包括虚拟机。这并不是开发人员想要的,只是专门为不需要编译器的用户提供。
接下来,你会看到大量的JavaSE,相对于JavaEE和JavaME,JavaSE是Java标准版。
Java2这种提法始于1998年。当时Sun公司的销售人员感觉以增加小数点后面数值的方式改变版本号并没有反映出JDK1.2的重大改进。但是,由于在发布之后才意识到这个问题,所以他们决定开发工具包的版本号仍然沿用1.2,接下来的版本是1.3、1.4和5.0。不过,Java平台被重新命名为Java2。因此,就有了Java2 Standard Edition Software Development Kit(Java2 标准版软件开发包)5.0版,即 J2SE SDK 5.0。
幸运的是,2006年版本号得到简化。Java标准版的下一个版本取名为 JavaSE 6 ,后来,又有了Java SE 7 和Java SE 8。
不过,”内部“版本号却分别是1.6.0、1.7.0和1.8.0。到了Java SE 9,这种混乱终于终结,版本号变为9,以及后来的9.0.1.(为什么没有使用9.0.0作为初始版本呢?为了保留一点兴奋感,版本号规范要求在主版本和第一次安全更新之间的短暂间隔中删除版本号末尾的零。)
在Java9之前,有32位和64位两个版本的Java开发工具包。现在Oracle公司不再开发32位版本。要使用 OracleSDK,你需要有一个64位的操作系统。
对于Linux,还可以在RPM文件和**.taz.gz文件**之间做出选择。我们建议使用后者,这样可以在你希望的任何位置直接解压缩这个压缩包。
下载JDK之后,需要安装这个开发工具包并明确要在哪里安装,后面还会需要这个信息。
解释:安装目录用jdk表示。例如,谈到jdk/bin 目录时,是指 /opt/jdk-11.0.4/bin 或者 C:\Java\jdk-11.0.4\bin 目录。
在Windows或Linux上安装JDK时,还需要另外完成一个步骤:将jdk/bin 目录添加到可执行路径中——可执行路径是操作系统查找可执行文件时所遍历的目录列表。
在Linux中,需要在 ~/.bashrc 或 ~/.bash_profile 文件的最后增加这样一行:
export PATH=jdk/bin:$PATH # 一定要使用JDK的正确路径,如:/opt/jdk-11.0.4。
在Windows10中,在 Windows Settings(Windows设置)的搜索栏中键入 environment(环境),选择 Edit environment variables for your account(编辑账户的环境变量,参图 2-1)。会出现一个Environment Variables(环境变量)对话框。(它可能隐藏在Windows设置对话框后面。如果实在找不到,可以同时按住Windows和R键打开Run(运行)对话框,从这个对话框运行 system.cpl,然后选择Advanced(高级)标签页,再点击Environment Variables(环境变量)按钮。)在User Variables(用户变量)列表中找到并选择一个名为Path的变量。点解Edit(编辑)按钮,再点击New(新建)按钮,增加一个变量,值为jdk\bin 目录(参考图2-2)。
保存所做的设置。之后新打开的所有命令提示窗口都会正确的路径。
可以按如下方式测试是否正确:打开一个终端窗口,键入(参考图2-3)
javac -version
如果得到诸如”javac: command not found“(javac:命令未找到)或”The name specified is not recoginzed as an internal or external command,operable program or batch file“(指定名不是一个内部或外部命令、可执行的程序或批文件)的信息,就需要退回去反复检查你的安装。
mkdir javasrc
cd javasrc
jar xvf jdk/lib/src.zip
cd ..
提示: src.zip文件中包含了所有公共类库的源代码。要想获得更多的源代码(例如编译器、虚拟机、原生方法以及私有辅助类),请访问网站 http://openjdk.java.net。
文档包含一个压缩文件中,它是一个独立于JDK的压缩文件。可以直接从网站 **http://www.oracle.com/technetwork/java/javase/downloads**下载这个文档。步骤如下:
jar xvf Downloads/jdk-11.0.x_doc-all.zip
mv docs jdk-11-docs
还要安装的程序案例。可以从 http://hostmann.com/corejava 下载示例。这些程序打包在一个 zip文件 corejava.zip中。可以将程序解压缩到你的主目录。它们会放在目录 corejava中。如果愿意,可以从命令行完成这个工作:
jar xvf Downloads/corejava.zip
如果以前有过使用 Microsoft Visual Studio等开发环境编程的经验,你可能会习惯于有一个内置文本编辑器、用于编译和启动程序的菜单以及调试工具的系统。JDK完全没有这些功能。所有工作都要在终端窗口中键入命令来完成。这听起来很麻烦,不过确实是一个基本技能。第一次安装Java时,你可能希望在安装开发环境之前检查Java的安装是否正确。另外,通过自己执行这些基本步骤,你可以更好的理解开发环境的后台工作。
不过,掌握了编译和运行Java程序的基本步骤之后,你可能就会希望使用专业的开发环境。
首先介绍比较难的方法:从命令行编译并运行Java程序。
1、打开一个终端窗口。
2、进入 corejava/v1ch02/Welcome目录(corejava是安装示例源代码的目录中,请参看2.1.3节的解释)。
3、键入下面的命令:
javac Welcome.java
java Welcome
然后,将会在终端窗口中看到图2-3 所示的输出。
祝贺你!你已经编译并运行了第一个Java程序。
那么,刚才发生了什么?javac程序是一个Java编译器,它将文件Welcome.java编译成Welcome.class。java 程序启动Java虚拟机,虚拟机执行编译器编译到类文件中得字节码。
Welcome程序非常简单,它只是向终端输出了一条信息。你可能想查看程序清单2-1的程序代码。
程序清单 2-1 Welcome/Welcome.java
/**
* This program displays a greeting for the reader.
* @version 1.30 2014-02-27
* @author Cay Hostman
*/
public class Welcome{
public static void main(String[] args){
String greeting = "Welcome to Core Java!";
System.out.println(greeting);
for(int i = 0;i < greeting.lenght() ; i++){
System.out.print("=");
}
System.out.println();
}
}
在使用集成开发环境的年代,许多程序员对于在终端窗口中运行程序已经很生疏了。常常会出现很多错误,最终导致令人沮丧的结果。
一定要注意以下几点:
在Linux环境下,检查 Welcome.java 是否正确的大写字母开头。
在Windows环境下,使用命令 dir,而不要使用图形浏览器工具。有些文本编辑器(特别是Notepad)会在每个文件后面添加扩展名 .txt。如果使用Notepad编辑Welcme.java ,实际上会把它保存为 Welcome.java.txt。如果采用默认的Windows设置,浏览器会与Notepad“勾结”,隐藏 .txt扩展名,因为这属于 “已知的文件类型”。对于这种情况,需要使用命令 ren 重新命名这个文件,或是另存一次,在文件名两边加上一对双引号,如:“Welcome.java”。
如果收到关于 welcome(w为小写)地错误信息,就应该重新执行命令:java Welcome(W为大写)。记住,Java区分大小写。
如果收到有关 Welcome/java地错误信息 这说明你错误地键入了 java Welcome.java应该重新执行命令 java Welcome。
提示:在http://docs.oracle.com/javase/tutorial/getStarted/cupojava/ 上有一个很好的教程,其中提到了初学者经常范的一些错误。
注释:在JDK11中,单个源文件不再需要javac命令。这个特性是为了支持“shebang”(#!)行(#!/path/to/java) 开头的 shell脚本。
这个 Welcome程序没有太大的意思。接下来再来尝试一个图形化应用。这个程序是一个简单的图像文件查看器,可以加载和显示一个图像。与前面一样,从命令行编译和运行这个程序。
javac ImageViewer.java
java ImageViewer
会弹出一个新的程序窗口(ImageViewer应用)。现在选择 File -> Open,找到一个要打开的图像文件。(这个目录下有两个示例文件。)然后会显示这个文件(参见图2-4)。要关闭这个程序,可以点击标题上的关闭扭,或者从菜单选择 File - > Exit。
可以简单浏览这个源代码(代码清单 2-2)。这个程序比第一个程序长多了,不过只要想一想用C或C++编写类似功能的应用程序所需要的代码量,就不会觉得它复杂了。
代码清单 2-2 ImageViewer.java
import javax.swing.*;
import java.awt.*;
import java.io.File;
/**
* A program for viewing images.(用于查看图像的程序。)
*
* @author JUCFF
*/
public class ImageViewer {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
ImageViewerFrame frame = new ImageViewerFrame();
frame.setTitle("ImageViewer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
});
}
}
/**
* A frame with a label to show an image(带有标签的框架以显示图像)
*
* @author JUCFF
*/
class ImageViewerFrame extends JFrame {
private static final int DEFAULT_WIDTH = 1024;
private static final int DEFAULT_HEIGHT = 1024;
public ImageViewerFrame() {
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
//user a label to display the images(用户一个标签来显示图像)
JLabel label = new JLabel();
add(label);
//set up the file chooser(设置文件选择器)
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new File("."));
//set up the menu bar(设置菜单栏)
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
JMenu menu = new JMenu("File");
menuBar.add(menu);
JMenuItem openItem = new JMenuItem("Open");
menu.add(openItem);
openItem.addActionListener(event -> {
//show file chooser dialog(显示文件选择器对话框)
int result = chooser.showOpenDialog(null);
//if file selected,set it as icon of the label(如果选择了文件,请将其设置为标签的图标)
if (result == JFileChooser.APPROVE_OPTION) {
String name = chooser.getSelectedFile().getPath();
label.setIcon(new ImageIcon(name));
}
});
JMenuItem exitItem = new JMenuItem("Exit");
menu.add(exitItem);
exitItem.addActionListener(event -> System.exit(0));
}
}
上一节中,已经了解了如何从命令行编译和运行一个Java程序。这是一个很有用的排错技能,不过对于大多数日常工作来说,还是应当使用集成开发环境。这些环境非常强大,非常方便,不使用这些集成环境简直有些不合理。我们可以免费得到一些很棒的开发环境,如Eclpse、IntelliJ
IDEA 和 NetBeans。
首先从网站 http://eclipse.org/downloads 下载Eclipse。Eclipse 已经有面向 Linux、Mac OSX 和 Windows 版本。运行安装程序,并选择
“Ecplipse IDE for Java Developers”。
下面是用Eclipse编写的一般步骤:
启动Eclipse之后,从菜单选择File -> New -> Project。
从向导对话框中选择 Java Project(如图2-5所示)。
3.点击 Next 按钮,不选中“User default location”复选框。点击 Browse 导航到 corejava/v1ch02/Welcome目录(图2-6)。
4.点击 Finish 按钮。,这个工程已经创建完成了。
5.点击工程窗口左边窗格中的三角,知道找到Welcome.java 并双击这个文件。现在应该看到一个包含程序代码的窗格(如图2-7所示)。
6.用鼠标右键点击左侧窗格中的工程名(Welcome),选择 Run -> Run As -> Java Application。程序输出会显示在控制台窗格中。
之前假定这个程序没有输入错误或 bug (毕竟,这段代码只有几行)。为了说明问题,假设在代码中不小心出现了录入错误(或者甚至语法错误)。试着讲原来的程序修改一下,让它包含一些录入错误,例如,将 String 的大小写弄错:
string greeting = "Welcome to Core Java!";
注意 string 下面的波浪线。点击源代码下标签页中的 Problems ,展开小三角,直到看到一个错误信息指出有一个未知的 string 类型(见图2-8)。点击这个错误信息。光标会移到编辑窗格中相应的代码行,可以在这里纠正错误。利用这个特性可以快速地修正错误。
提示:通常,Eclipse 错误报告会伴有一个灯泡图标。点击这个图标可以得到解决这个错误地建议方案列表。
Java 9 引入了另一种使用Java地方法。JShell 程序提供了一个”读取—计算—打印循环“(Read-Evaluate-Print Loop,REPL)。键入一个Java表达式;JShell 会评估你地输入,打印结果,等待你的下一个输入。
要启动 JShell ,只需要在终端窗口键入 jshell(参加图2-9)。
JShell 首先向你显示一个问候语,后面是一个提示符:
| Welcome to JShell -- Version 9.0.1
| For an introduction type: /help intro
jshell>
现在键入一个表达式,如下:
"Core Java".lenght()
JShell 会回应一个结果——在这里就是字符串”Core Java“ 中的字符个数。
$1 ==> 9
注意,你并没有键入 System.out.println。JShell 会自动打印你输入的每一个表达式的值。输出中的 $1表示这个结果可以用于将来的计算。例如,如果你键入:
5 * $1 - 3
$2 ==> 42
如果需要多次使用一个变量,可以给它指定一个容易记忆的名字。不过,一定要遵循 Java 语法,需要同时指定类型和变量名。例如:
jshell> int answer = 6 * 7
answer ==> 42
另一个有用的特性是”tab 补全“。如果键入:
Math.
然后再按一次Tab键。你会得到可以在 generator变量上调用的所有方法的一个列表(参见图 2-9):
现在键入 l,然后再按一次 Tab 键。方法名会自动补全为 log,现在你会得到一个比较小的列表:
jshell> Math.log
log( log10( log1p(
接下来你可以手工填入其余的部分:
jshell> Math.log10(0.001)
$3 ==> -3.0
要重复运行一个命令,可以连续按 ⬆ 键,直到看到想要重新运行或编辑的命令行。可以用 ⬅ 和 ➡ 键移动命令行中的光标位置,然后增加或删除字符。编辑完命令后再按回车。例如,把命令行中的0.001替换为1000,然后按回车:
jshell> Math.log10(1000)
$4 ==> 3.0
JShell 会让Java语言和类库的学习变得轻松而有趣,他不要求你启动一个庞大的开发环境,不会让你再为 public static void main 而困扰。
public class FirstSample{
public static void main(String[] args){
System.out.println("We will not use 'Hello World!'");
}
}
public
称为访问修饰符(access modifier),这些修饰符用于控制程序地其他部分对这端代码地访问级别。关键字class
表明Java程序中地全部内容包含在类中。尽管我们会在下一章用大量的篇幅介绍Java类,不过现在只需要将类作为程序逻辑的一个容器,程序逻辑定义了应用程序的行为。Java应用程序中全部内容都必须放置在类中。class
后面紧跟类名。Java中定义类名的规则很宽松。名字必须以字母开头,后面可以跟字母和数字的任意组合。长度基本上没有限制。但是不能使用Java保留字(例如,public
和class
)作为类名。java FirstSample
(请记住,不要添加 .class 扩展名。)程序执行之后,控制台将会显示 "We will not use 'Hello World'!"
。java ClassName
运行已编译地程序时,Java 虚拟机总是从指定类中地main
方法的代码开始执行(这里的”方法“ 就是Java中的”函数“),因此为了代码能够执行,在类的源文件中必须包含一个main
方法。当然,也可以将用户自定义的方法添加到类中,并在main
方法中调用这些方法。注释: 根据Java语言规范,
main
方法必须声明为public
(Java语言规范是描述Java语言的官方文档。可以从网站http://docs.oracle.com/javase/specs)上阅读或下载。
不过,当main
方法不是public
时,有些版本的Java 解释器也可以执行Java应用程序。一个程序员报告了这个bug
。如果感兴趣的话,可以在网站http://bugs.java.com/bugdatabase/index.jsp 上输入bug
号码 4252539 查看。1999年这个bug
被标记为”关闭,不予修复。“(Closed,Will not be fixed.)Sun公司的一个工程师解释说:Java虚拟机规范(在 http://docs.oracle.com/javase/specs/jvms/se8/html) 并没有强制要求main
方法一定是公有的(public
),并且”修复了这个bug
有可能带来其他的隐患“。好在,这个问题最终得到了解决。在Java 1.4 及以后的版本中强制main
方法必须是public
。
从上面这段话可以发现几个有趣的方面。一方面,让质量保证工程师关于bug
报告做出决定不仅让人生疑,也让他们自己很头疼,因为他们的工作量大,并且工程师对Java的所有细节也未必了解得很清楚。另一方面,Sun公司在Java开源很久以前就把bug
报告及其解决方案放在网站上让所有人监督检查,这是一种非常了不起得举动。某些情况下,Sun公司甚至允许程序员为他们最厌恶得bug
投票,并用投票结果来决定发布的下一个JDK版本将修复哪些bug
。
{}
。在Java中,像C/C++中一样,用大括号划分程序的各个部分(通常称为块)。Java 中任何方法的代码都用{
开始,用}
结束。main
方法,其声明格式如下所示:public class ClassName{
public static void main(String[] args){
program statements
}
}
C++ 注释: 作为一名 C++ 程序员,一定知道类的概念。Java 的类与 C++ 很相似,但有些差异还是会使人感到困惑。例如,Java 中的所有函数都是某个类的方法(标准术语将其称为方法,而不是成员函数)。因此,Java 中的
main
方法必须有一个外壳(shell
)类。读者,有可能对 C++ 中的静态成员函数(static member function)十分熟悉。这些成员函数定义在类的内部,并且不对对象进行操作。Java 中的main
方法必须是静态的。最后,与 C/C++ 一样。关键字void
表示这个方法没有返回值,所不同的是main
方法没有为操作系统返回“退出码”。如果main
方法正常退出,那么由 Java 应用程序的退出码为 0,表示成功地运行了程序。如果希望在终止程序时返回其他地退出码,那就需要使用Syetem.exit
方法。
接下来研究一下代码:
{
System.out.println("We will not use 'Hello World!'");
}
一对大括号表示方法体地开始与结束,在这个方法中只包含一条语句。与大多数程序设计语言一样,可以将 Java 语句看成是语言中的句子。在 Java 中,每个句子必须使用分号结束。特别需要说明,回车不是语句的结束标志,因此,如果需要可以将一条句子写在多行上。
在上面这个main
方法体中只包含了一条语句,其功能是将一个文本行输出到控制台上。
在这里,我们使用 System.out
对象并调用了它的 println()
方法。注意,点号(.)用于调用方法。Java 使用通用语法是:object.method(parameters)
这等价于函数调用。
在这个示例中,调用了 println()
方法并传递给它一个字符串参数。这个方法将传递给它的字符串参数显示在控制台上。然后,终止这个输出行,使得每次调用println()
方法都会在新的一行上显示输出。需要注意一点,Java 与 C/C++ 一样,都采用双引号界定字符串。
与其他程序设计语言中的函数一样,Java 中的方法可以没有参数,也可以有一个或多个参数(有的程序员把参数叫做实参)。即使一个方法没有参数,也需要使用空括号。例如,不带参数的println()
方法只打印一个空行。使用下面的语句来调用:
System.out.println()
注释:
System.out
还有一个print()
方法,它不在输出之后增加换行符。例如,System.out.print("Hello");
打印“Hello”之后不换行,后面的输出紧跟在字母“o”之后。
//
,其注释内容从//
开始到本行结尾。System.out.println("We will not use 'Hello World!'");//is this too cute?
//
,也可以使用/*
和*/
注释界定符将一段比较长的注释括起来。/**
开始,以*/
结束。程序清单 3-1 FirstSample/FirstSample.java
/**
* This is the first sample program in Core Java Chapter 3
* @version 1.01 1997-03-22
* @author Gray Cornell
*/
public class FirstSample{
public static void main(String[] args){
System.out.println("We will not use 'Hello World!'");
}
}
**⚠警告:**在 Java中,
/* */
注释不能嵌套。也就是说,不能简单地把代码用/*
和*/
括起来作为注释,因为这段代码本身可能也包含一个*/
界定符。
char
(用于表示 Unicode 编码的代码单元)和1种用于表示真值的boolean
类型。注释: Java 有一个能够表示任意精度的算术包,通常称为“大数”(big number)。虽然被称为大数,但它并不是一种基本 Java 类型,而是一个 Java 对象。
int
类型最常用。但如果想要表示整个地球的居住人口,就需要使用long
类型了。byte
和short
类型主要用于特定的应用场合,例如,底层的文件处理或者存储空间很宝贵时的大数组。0x
或 0X
(如0xCAFE)。八进制有一个前缀0,例如,010对应十进制中的8。很显然,八进制表示比较容易混淆,所以建议最好不要使用八进制常数。0b
或 0B
就可以写二进制数。例如,0b1001
就是9。另外,同样是从 Java 7 开始,还可以为数字字面量加下划线,如1_000_000
(或0b1111_0100_0010_0000
)表示100万。这些下划线只是为了让人更易读。Java 编译器会去除这些下划线。C++ 注释: 在 C 和 C++ 中,
int
和long
等类型的大小与目标平台相关。在 8086 这样的16位处理器上整数占2个字节;不过,在32位处理器(比如 Pentium 或 SPARC)上,整数则为4个字节。类似地,在32位处理器上long
值为4字节,在64位处理器上则为8字节。由于存在这些差别,这对编写跨平台程序带来了很大难度。在 Java 中,所有地数值类型所占据的字节数与平台无关。
注意: Java 没有任何无符号(unsigned)形式的int
、long
、short
或byte
类型。
注释: 如果要使用不可能为负的整数值而且确实需要额外的一位(bit),也可以把有符号整数值解释为无符号数,但是要非常仔细。例如,一个
byte
值 b 可以不表示范围-128~127
,如果想表示0~255
的范围,也可以存储在一个byte
中。基于二进制算术运算的性质,只要不溢出,加法、减法和乘法都能正常计算。但对于其他运算,需要调用Byte.toUnsignedInt(b)
来得到一个0~255
的int
值,然后处理这个整数值,再把它转换回byte
。Integer
和Long
类都提供了处理无符号除法和求余数的方法。