
3.3 Java程序开发介绍
下面通过一个简单的Java应用程序例子,来理解一下它的主要概念。
/** *一个简单的Java演示程序 */ package sample; // 第一步(step 1) import java.io.*; // 第二步(step 2) public class FirstJavaProgram { //第三步(step 3) //数据部分(Data or Fields),第四步(step 4) private String name; private int age; /* 方法部分(Methods),第五步(step 5) 一种特殊方法——构造方法/函数(constructor)*/ public FirstJavaProgram(String aName, int aAge){ name = aName; age = aAge; } //数据读取方法(Accessor Method) public String getName() { return name;} public void setName(String aName){ name = aName; } //运行入口方法(Main Method) public static void main(String[] args) { //创建对象,第六步(step 6) FirstJavaProgram fjp = new FirstJavaProgram("Zhang", 24); System.out.println("Name is: " + fjp.getName()); } }
3.3.1 定义Java程序的基本元素
首先我们介绍一下Java的基本元素。Java程序由程序块、分隔符、空白分隔符、标识符、关键字、变量、运算符及注释组成。
1.程序块
我们看到,整个类FirstJavaProgram的定义(包括其所有成员)都位于一对花括号({})之间;同样,方法或方法的一部分也都包含在一对花括号({})之间。这些就叫做程序块(Block),代表一段相对独立的逻辑单元。注意,对于左花括号({),一定要有右花括号(})与之对应,并且保持对齐,在使用很多对花括号({})时尤为重要。
2.分隔符(Separators)
上面的Java程序块是由许多语句组成的,这些语句以分号(;)作为分隔符,例如:private String name;。在Java中,还有一些其他字符被当做分隔符使用,如表3-1所示是常用的分隔符。
表3-1 常用的分隔符

3.空白分隔符(Whitespace)
Java是一种形式自由的语言,这意味着不需要遵循任何特殊的缩进书写规范。不过通过使用空白分隔符,可以体现良好的书写格式。例如,虽然例子程序的所有代码都可以在一行上,但也可以按自己喜欢的方式输入程序代码,前提是必须在已经被运算符或分隔符描述的标记之间至少留出一个空白分隔符。在Java中,空白分隔符可以是空格、Tab跳格键或者换行符。在我们的实例中,在语句段之间适当采用空行,另外,数据和方法部分都使用了空白分隔符的缩进,方法体内使用了下一级缩进,这样就很好地体现了类中的层次结构,便于阅读,一目了然。
4.标识符(Identifiers)
标识符是赋给类、方法或者变量的名字。例如,本程序使用了FirstJavaProgram,name,age,getName,setName这些标识符。一个标识符可以是大写和小写字母、数字、下画线、美元符号的任意顺序组合,但不能以一个数字开始。另外,Java是区分大小写的,abc和Abc是两个不同的标识符。
5.Java关键字
Java关键字与运算符和分隔符一起构成Java语言的定义。关键字不能作为变量名、类名或方法名。本程序中使用了package,import,public,class,private,static,void等关键字。
6.注释(Comments)
在本程序中,除了Java代码外,还有许多注释。例如,程序的开始处就出现了以下注释。
/** *一个简单的Java演示程序 */
使用注释是一个非常好的编程习惯。注释中的内容将被编译器忽略,但它能很好地帮助程序员了解程序的功能。我们要记住这句话:“程序是给人看的,而不是给机器读的”。事实上,注释是为了给任何阅读源代码程序的人提供说明或解释程序的。在真正的应用中,注释通常用来解释程序的某些部分如何工作或者某部分的特殊功能。
Java支持3种类型的注释。第1种是多行注释(Multiline Comment)。这类注释开始于“/*”,结束于“*/”,这两个注释符间的任何内容都将被编译器忽略。顾名思义,一个多行注释可以包含若干行文字。
第2种类型的注释是单行注释(Single-line Comment)。例如:
//数据部分(Data or Fields)
单行注释始于“//”,在该行的末尾结束。在通常情况下,对于较长的注释使用多行注释,而对于简短的、一行一行的注释则使用单行注释。
第3种类型的注释被称为文档注释(Documentation Comment)。文档注释以“/**”开始,以“*/”结束。文档注释是我们推荐使用的类型,以此格式写的注释会由JDK命令javadoc调入并且以HTML文件的形式为你的程序生成文档。
7.Java类库
在这个示例程序中用到了Java的一个内置方法:println()。这个方法是System类的成员,它已经被Java预定义且自动地包括在程序中。Java环境依靠几个内置的类库,这些类库包含许多内置的方法,用以提供对诸如输入/输出(I/O)、字符串处理、网络、图形的支持。标准的类还提供对窗口输出的支持。因此,作为一个整体,Java是Java语言本身和它的标准类库的组合体。Java类库提供了Java的许多功能。毫无疑问,要成为一个Java程序员,其中的一部分工作就是学会使用标准的Java类。在本书后面的内容中,我们会对常用的标准类库和方法进行介绍。
3.3.2 类和对象基本概念
介绍完Java的基本元素,下面我们要重点讲解Java面向对象的编程概念。
Java程序结构可以分为6个部分(或者叫做开发的6个步骤)。
(1)package语句:零个或多个,必须放在文件开头。
(2)import语句:零个或多个,必须放在所有类定义之前。
(3)class定义:至少一个。
(4)数据定义(Data Definition):零个或多个。
(5)方法定义(Method Definition):零个或多个。
(6)对象创建与引用:零个或多个。
下面我们具体来看每一个步骤。
1.程序包(package)
由于Java编译器为每个类生成一个字节码文件,并且文件名与类名相同,因此同名的类有可能发生冲突。为了解决这一问题,Java用包来管理类名空间。程序包相当于文件系统里的文件夹或目录,而类相当于文件。
Java用package语句将一个Java源文件中的类放入一个包里。package语句作为Java源文件的第一条语句,指明该文件中定义的类所在的包(若缺省该语句,则指定为无名包)。package语句的格式为:
package pkg1[.pkg2[.pkg3…]];
Java编译器把包对应于文件系统的目录管理,在package语句中,用“.”来指明目录的层次。
例如:
package com.ascenttech.graphics; class Square {…;} class Circle {…;} class Triangle {…;}
其中,“package com.ascenttech.graphics;”这条语句指定这个包中的文件存储在目录 %classpath%/com/ascenttech/graphics下。包层次的根目录classpath是由环境变量CLASSPATH确定的。
2.import语句
为了能使用Java中已提供的类,我们需要用import语句引入所需要的类。
import package1[.package2…]. (classname |*);
例如:
import com.ascenttech.graphics.*; import java.io.*;
3.class定义
用关键字class来定义名为FirstJavaProgram的新类,FirstJavaProgram是新类的名称,它必须是一个有效的标识符(有效标识符定义请见第4章)。类名的第一个字母一般大写。我们还要了解Java的一些规范,例如类的个数:一个Java文件中至少应有一个类,但最多只能有一个public类;若有public类,源文件必须按该类命名。
类的说明包括数据说明和成员方法说明,都放在类后面的大括号里面。其中数据部分可以被方法使用,而方法可以处理数据。数据和方法从属于类,不能脱离类而独立存在,这与传统的面向过程语言截然不同。在面向过程语言中,函数或者方法是中心;而在面向对象语言中,类或对象是中心。
一般类定义如下:
class类名称{数据定义;方法定义;}
4.数据定义
类的数据部分又叫做属性。变量名的第一个字母一般小写。在前面的程序中,我们使用了关键字private(私有),这样这些数据就成为这个类的私有成员,其他类不能直接操作这些数据了,这就是封装的概念。相关的关键字有private,protected和friend。private表示只能被本类访问,protected表示只能被子类访问,friend是缺省的访问权限,表示能被本包(package)中的任意类访问,对于其他包中的类是不可访问的。
5.方法定义
类的方法部分又叫做行为。它们为类提供了功能,其他类或对象可以使用或调用这些方法。方法名的第一个字母一般小写。类一般会提供一种特殊方法:构造方法,它的作用是对数据部分进行初始化,为类的每个对象提供自己独特的属性。我们还经常遇到数据读取方法(Accessor Method)。上面提到封装特性,即其他类不能直接操作某个类的私有成员,但可以通过数据读取方法这个接口达到类似目的。类中最重要的方法叫做业务方法(Business Method),它们为每个类提供独特的逻辑处理功能。
另外,如果一个程序想独立运行,那么它需要一个main()方法作为运行应用程序的入口点(以前叫做函数)。它的完整签名(方法签名和实现等概念后面还要详细介绍)是public static void main(String[] args)。其中,public是一个表示访问权限的关键字,表示此成员方法是公有的,可以被其他类直接调用,包括Java解释器。static表示main成员方法在类的所有对象中是唯一的,因此如果本程序生成另一个类对象,调用的main方法将是同一个方法。void表示main方法没有返回值,如果有返回值,则可加上int或boolean等返回值类型说明。对于有返回值的方法,其方法实体的最后应加上return语句。
6.对象创建与引用
之前我们涉及的都是类的概念,而我们一直在谈“面向对象”,那么对象在哪里呢?
例如:main方法中的“FirstJavaProgram fjp = new FirstJavaProgram("Zhang", 24);”。这里涉及了3个概念:类、对象和引用。其中,FirstJavaProgram是我们定义的类;通过new运算符和构造方法可以创建对象,也就是类的实例。那么fjp是什么呢?我们把它称为对象的引用,它实际上是指向对象的地址。对对象的操作都是通过引用进行的,例如,通过引用调用对象中的getName方法,完成获取名字值的功能。
fjp.getName()
最后,System.out.println向屏幕输出结果,相当于C中的printf()。简单地说,System是一个预定义的可访问系统的类,out是连接到控制台的输出流。
3.3.3 编译和运行Java应用程序
上面的程序可以通过任何文本编辑器(例如:Notepad等)或集成开发环境工具(例如:本书附录中介绍的Eclipse)编辑或编写完成。我们称这时的代码为源代码,它还不能被计算机所理解,需要编译为字节码(Bytecode)才能运行。
1.Java程序的编译
我们在前面介绍过,Java程序的编译程序是javac.exe。javac命令将Java程序编译成字节码,然后即可用Java解释器java命令来解释执行这些Java字节码。Java程序源码必须存放在后缀为.java的文件里。对于Java程序里的每一个类,javac都将生成与类名称相同但后缀为.class的文件。编译器把.class文件放在.java文件的同一个目录里,除非使用了-d选项。
当引用到某些自己定义的类时,必须指明它们的存放目录,这就需要利用环境变量CLASSPATH。环境变量CLASSPATH由一些被分号隔开的路径名组成。
2.Java程序的执行
编译过的Java程序通过java这个命令来解释执行。java命令的基本语法如下:
java [ options ] classname <args>
java命令用来执行由Java编译器javac输出的Java字节码。classname参数是要执行的类名称。注意,在类名称后的任意参数都将传递给要执行类的main方法。Java执行完main方法后退出,除非main方法创建了一个或多个线程。如果main方法创建了其他线程,那么java总是等到最后一个线程退出后才退出。
在FirstJavaProgram实例中,我们需要进行以下操作。
(1)编辑及保存FirstJavaProgram.java。注意,文件名和公共类名(用public声明,这里是FirstJavaProgram)要一致。
(2)编译程序。我们在程序中使用了包,所以需要编译和生成包。
第一种方式:进入包的上一级目录,运行javac sample\FirstJavaProgram.java。
第二种方式:在类所在目录下,运行javac -d . FirstJavaProgram.java,编译器会自动在当前目录下建立一个子目录sample,并将生成的.class文件都放到sample中。当然,除了当前目录外,也可以指明其他目录来存放包和类。
(3)运行程序:java sample.FirstJavaProgram。
运行结果为:
Name is: Zhang
下面我们再举一个Java应用程序的实例,同时补充说明一下main()方法命令行参数的使用。
Java应用程序(Java Application)是可以独立运行的程序。它可以有一个main()方法,也就是应用程序的入口方法,这与标准C中main()函数的地位是一样的。一个应用程序有且只有一个main()方法,main()方法必须包含在一个类中,该类即为应用程序的外部入口标志。另外,main()仅是解释器开始工作的地方。一个复杂的程序可能包含几十个类,但这些类仅需要一个main()方法以供解释器开始工作。
前面已经介绍过,main()是Java程序开始时调用的方法。请记住,Java是区分大小写的,因此,main与Main是不同的。Java编译器也可以编译不包含main()方法的类,但是Java解释程序没有办法运行这些类。因此,如果你输入了Main而不是main,编译器仍将编译这个程序,但Java解释程序将报告一个错误,因为它找不到main()方法。
要传递给方法的所有信息由方法名后面括号中指定的变量接收,这些变量被称为参数(Parameters)。即使一个方法不需要参数,但仍然需要在方法名后面放置一对空括号。在main()中,只有一个参数,即String[] args,它声明了一个叫做args的参数,该参数是String类的一个实例数组(注:数组是简单对象或数据的集合,后面会详细讲解)。字符串类型的对象可以存储多个字符。
下面的实例说明了命令行参数的使用方法。
package sample; public class MainArg { public static void main(String args[]) { //显示命令行参数 int i; if( args.length > 0 ) //有参数存在 { for( i=0; i<args.length; i++ ) { System.out.println("arg["+i+"] = "+args[i]); } } else //没有参数存在 { System.out.println("No arguments!"); } } }
(1)编译程序:javac sample\MainArg.java。
(2)运行程序(通过命令行参数获取):java sample.MainArg first second third。
(3)运行结果如下:
arg[0] = first arg[1] = second arg[2] = third
3.3.4 应用小程序
上面我们介绍的实例也叫做Java应用程序(Java Application),和它对应的另一类程序叫做Java应用小程序(Java Applet)。在问世的头几年里,Java之所以如此热门,其根本原因还在于Java具有“让Internet动起来”的能力。具体地说,就是Java能创建一种特殊类型的程序(通常称为“应用小程序”或者Applet),具备Java支持(Java-enabled)的Web浏览器可以从网上下载这种程序,然后运行。我们在这里介绍一下Java应用小程序。
Java应用小程序不能直接执行和使用,必须嵌套在HTML页面中(通过<applet>标签)在浏览器中执行,或者使用JDK工具appletviewer调用。Java应用小程序具有以下几个生命周期方法。
init()方法:初始化,自动调用,只执行一次。
start()方法:初始化后,将自动调用Applet的主体,在其中可以执行一些任务或启动相关的线程来执行任务,如paint()方法等。
stop()方法:离开Applet所在页面时调用,以停止消耗系统资源。
如果需要画图,还可以调用paint()方法,而在Applet中,与屏幕输出有关的操作通过Graphics对象来实现。
下面我们看一个实例。
package sample; import java.applet.*; import java.awt.*; public class HelloApplet extends Applet { public String s; public void init() { s = new String("Hello World!"); } public void paint(Graphics g) { g.drawString(s,25,25); } }
(1)编辑并存盘。文件名和主类名一致。
(2)编译代码:javac sample\HelloApplet.java。
(3)编写HTML文件:HelloApplet.html。
<HTML> <HEAD> <TITLE>Hello World</TITLE> </HEAD> <applet codebase=".." code="sample/HelloApplet.class" width=300 height= 300> </applet> </HTML>
(4)运行Applet程序。
进入sample文件夹:cd sample。
appletviewer HelloApplet.html。
(5)运行结果如下:
Hello World!
我们再看一个实例。
package sample; import java.util.*; import java.awt.*; import java.applet.*; import java.text.*; public class MyTest extends Applet { String s1,s2,s3,s4; public void init() { s1 = getParameter("p1"); s2 = getParameter("p2"); s3 = getParameter("p3"); s4 = getParameter("p4"); } public void paint(Graphics g) { g.drawString(s1,10,10); g.drawString(s2,10,30); g.drawString(s3,10,50); g.drawString(s4,10,70); } }
(1)编辑并存盘。文件名和主类名一致。
(2)编译代码:javac sample\MyTest.java。
(3)编写HTML文件:MyTest.html。
<HTML> <HEAD> <TITLE>Applet Parameter Test</TITLE> </HEAD> <applet codebase=".." code="sample/MyTest.class" width=300 height=300> <param name=p1 value="111111"> <param name=p2 value="222222"> <param name=p3 value="333333"> <param name=p4 value="444444"> </applet> </HTML>
(4)运行Applet程序。
进入sample文件夹:cd sample。
appletviewer MyTest.html。
(5)运行结果如下:
111111 222222 333333 444444
理解程序:
(1)从页面中获取Applet参数:s1 = getParameter("p1");。
(2)在页面中设置Applet参数:<param name=p1 value="1111111">。