Java学习(五).API基础
Java语言的强大功能主要体现在Java语言完备丰富、功能强大的Java API上。本章介绍Java API的基本结构以及语言包和实用包中的常用类。
1、Java API 综述
Java语言的内核非常小,Java语言的强大功能主要体现在Java语言完备丰富、功能强大的Java API上。
Java API(Java Application Programming Interface,Java应用程序接口),是Java语言提供的组织成包结构的许多类和接口的集合。Java API为用户编写应用程序提供了极大的便利。Java API包含在JDK中,因此用户只要按照1.3节介绍的方法安装了JDK运行环境就可以使用了。
Java API按照内容分别组织和存放在不同的包中,Java API中的包及其主要功能按字母顺序说明如下:
java.accessibility 接口组件和助手技术的类和接口
java.applet Applet所需的类和接口
java.awt 图形用户界面所需的类和接口
java.beans Java bean所需的类和接口
java.io 系统输入/输出所需的类和接口
java.lang Java语言编程的基础类和接口
java.math 支持任意精度整数和任意精度小数的类和接口
java.naming 访问命名服务的类和接口
java.net 网络应用的类和接口
java.rmi 远程调用(RMI)的类和接口
java.security 用于安全框架的类和接口
java.sql 访问和处理数据源中数据的类和接口
java.text 支持按与语言无关方式处理文本、数据、数字和消息的类和接口
java.util 集合框架、事件模型、日期和时间机制、国际化等的类和接口
javax.rmi 支持RMI-IIOP的类和接口
javax.serverlet 支持serverlet编程的类和接口
javax.sound 支持音频设备数字接口(MIDI)的类和接口
javax.swing 扩充和增强基本图形用户界面功能的类和接口
javax.transaction 包含有几个关于事务上下文异常的类
org.omg.CORBA 支持OMG CORBA API到Java语言映射的类和接口
上述大部分的包都又按内容组织成子包形式,关于各包的子包这里就不再赘述。
Java语言在不断发展,这表现在JDK运行环境的版本在不断提高。因此,读者学习本书时,可能Java API中又包含了新的包,或某些包中又增加了新的子包。
打开JDK的帮助文档,可以看到Java API的详细说明文档。
Java API包含的内容很多,本章主要讨论其中两个最基本的包中的主要类:
(1)语言包(java.lang)。主要讨论的类有:Object类、Class类、Runtime类、Float类、String类和Math类。
(2)实用包(java.util)。主要讨论的类和接口有:Arrays类、Vector 类、Data 类和Enumeration接口。
2、语言包(java.lang)简介
java.lang包中包含了Java程序设计语言最基础的类。本节讨论的java.lang包中的类有Object类、System类、Class类、Runtime类、String类、Math类和Float类。
java.lang包是Java语言编程使用最频繁的包。为了简化编程,系统固定地默认导入了java.lang包,所以使用java.lang包中的类时可以不用import语句导入。
1、Object类
Object类是Java中所有类的根,所有其他的类都是由Object类派生出来的,因此,根据继承的特点,在Object类中定义的成员变量和方法,在其他类中都可以使用。
Object类常用方法有:
equals(Object obj) 比较两个对象是否相等
getClass() 获取对象的运行时类
toString() 把对象转换为字符串
Object类中还有一组关于线程同步的方法:wait()方法和notify()方法。
equals(Object obj)方法与Java运算符"=="的含义相同,但用法不同。当两个值比较、对象或变量与值比较、两个变量比较时,使用运算符"==";当比较两个对象时,使用equals()方法。该方法调用返回true时表示两个对象相等(或称相同),返回false时表示两个对象不相等。
【例5.1】equals()方法应用举例。
public class EqualsTest
{
public static void main(String args[])
{
char ch='A';
if ((ch=='A') || (ch=='a')) //变量与值比较
System.out.println("true");
String str1="abc",str2=null;
if (str1!=null) //对象与值比较
System.out.println(str1.equals(str2)); //两个对象比较
}
}
程序运行显示结果如下:
true
false
2、System类
System类提供了许多获取或重新设置系统资源的静态方法。
System类的常用方法有:
static Properties getProperty() 获取系统属性
static Properties getProperty(String key) 获取由key指定的系统属性
static void setProperty(Properties props) 设置由props指定的系统属性
static void load(String fileName) 加载本地文件系统中由文件名fileName指定的动态库
static void exit(int status) 中断当前运行的Java虚拟机,status为状态码,非0的状态码表示不正常中断
其中,获取系统属性方法的返回值类型为Properties,Properties是java语言包中定义的一个类。该类定义了系统属性集合,每个属性用字符串表示,其常用的几个属性值以及含义如下:
java.version java运行时环境版本
java.vm.version java虚拟机实现的版本
java.class.path java类的路径
os.version 操作系统的版本
user.name 用户名
user.dir 用户路径
user.home 用户HOME路径
【例5.2】用System类获得当前系统属性示例。
public class SystemTest
{
public static void main(String args[])
{
String str;
//java运行时环境版本
str = System.getProperty("java.version");
System.out.println("java.version: " + str);
//java虚拟机实现的版本
str = System.getProperty("java.vm.version");
System.out.println("java.vm.version: " + str);
//java类的路径
str = System.getProperty("java.class.path");
System.out.println("java.class.path: " + str);
//操作系统的版本
str = System.getProperty("os.version");
System.out.println("os.version: " + str);
//用户名
str = System.getProperty("user.name");
System.out.println("user.name: " + str);
//用户路径
str = System.getProperty("user.dir");
System.out.println("user.dir: " + str);
//用户HOME路径
str = System.getProperty("user.home");
System.out.println("user.home: " + str);
}
}
程序的运行结果为:
java.version: 1.4.1_02
java.vm.version: 1.4.1_02-b06
java.class.path: D:\JBuilder9\jdk1.4\lib;D:\;.;
os.version: 5.0
user.name: administrator
user.dir: E:\Java\chapt5
user.home: C:\Documents and Settings\Administrator.ZXB
另外,System类中定义了三个和输入输出流有关的静态成员变量in、out和err。
3、Class类
Class类的实例代表一个正在运行的Java应用程序的类或接口。Java的基本数据类型(boolean,byte,char,shart,int,long,float,double)以及数组和关键字void都是由Class对象来表达。
Class类没有公共的构造方法,Class对象由Java虚拟机自动构造。
Class类的常用方法有:
String static getName() 返回对象的类名
class static forName(String ClassName) 使用ClassName指定的、与类或接口相联系的class对象
class static forName(String name,boolean initialize,ClassLoader loader) 使用loader指定的类装载器Class类的forName()方法可用于安装驱动程序。
例如,安装JDBC-ODBC驱动程序,可以使用下面语句:
Class.forName("sun.jdbc.odbc.JdbcOdcDriver");
要安装Oracle Jdbc驱动程序,可以使用下面语句:
Class.forName("oracle.jdbc.driver.OracleDriver");
4、Runtime类
每一个Java应用程序都有一个Runtime类的实例,从而允许应用程序与其运行的环境进行交互。可利用Runtime类直接访问运行时环境资源。
Runtime类常用方法有:
static Runtime getRuntime() 返回与当前应用程序相联系的运行时环境
void exit(int status) 中断当前运行的Java虚拟机,status为状态码,非0的状态码表示不正常中断
native void traceInstructions(Boolean on) 设置对指令的追踪,如果参数on为 true,则Java虚拟机对于其上执行的每一条指令都发出调试信息
native void traceMethodCalls(Boolean on) 设置对调用方法的追踪,如果参数on为 true,则支持指令的追踪
totalMemory() 返回系统的内存总数
freeMemory() 返回系统当前内存的剩余空间总数
gc () 运行垃圾回收程序
【例5.3】用Runtime类获得当前系统运行状况示例。
public class RuntimeTest
{
public static void main(String args[])
{
Runtime rtime = Runtime.getRuntime();
long totalMemory = rtime.totalMemory()/1024;
long freeMemory = rtime.freeMemory()/1024;
System.out.println("totalMemory: " + totalMemory + "k");
System.out.println("freeMemory: " + freeMemory+ "k");
}
}
程序运行结果为:
totalMemory: 1984k
freeMemory: 1734k
5、Float类
为了方便学习过C语言的人员学习Java语言,Java语言也像C语言一样,有数据类型的概念。但数据类型与类不等同。Java是一种纯面向对象程序设计语言,为了达到这个目标,语言包中提供了8个称为数据类型包装类的类,专门完成把Java语言的8个基本数据类型包装为相应的类。
Java语言中的8种基本数据类型是:byte、short、int、long、float、double、char、boolean,对应的8个数据类型包装类是:Byte、Short、Integer、Long、Float、Double、Character、Boolean。这里仅介绍Float类,其余的相似。
Float类的几个构造方法如下:
Float (double value) 以double类型的参数value创建一个对象
Float (float value) 以float类型的参数value创建一个对象
Float (String s) 以String类型的参数s创建一个对象
Float类的几个方法如下:
compareTo(Float anotherF) 比较两个对象的大小,大于返回1,相等返回0,小于返回-1
floatValue() 返回对象的float数据类型的数值
doubleValue() 返回对象的double数据类型的数值
intValue() 返回对象的int数据类型的数值,小数部分丢掉
6、String类
我们说过,定义字符串变量所使用的String不是一个基本数据类型,而是Java API中提供的类。
String类的构造方法和常用方法有:
String() 构造方法,初始化创建一个字符为空的String对象
String(byte[] bytes) 构造方法,初始化创建一个string对象,其值由指定bytes转换而来
compareTo(String anotherString) 比较字符串,返回两者之间的差值
length() 获取字符串的长度
substring(int beginIndex) 返回当前字符串的由beginIndex开始到结尾的子串
substring(int beginIndex,int endIndex) 返回当前字符串的由beginIndex开始到endIndex结尾的子串
toLowerCase() 返回小写字符串,即返回的对象中所有的字符均为小写字符
toUpperCase() 返回大写字符串,即返回的对象中所有的字符均为大写字符
【例5.4】String类应用举例。
要求:在程序中进行字符串的连接(+)、取子串等操作。
public class StringTest
{
public static void main(String args[])
{
System.out.println("abc");
String cde = "cde";
System.out.println("abc" + cde);
String c = "abc";
c = c.substring(2,3);
System.out.println("c = " + c);
String d = cde.substring(1, 2);
System.out.println("d = " + d);
}
}
程序运行显示结果如下:
abc
abccde
c = c
d = d
7、Math类
Math类包含了一组基本的数学运算的方法和常数。如求绝对值的abs()方法,计算三角函数的sin()方法和cos()方法,求两个数中的较小值和较大值的min()方法和max()方法,求随机数的random()方法等。Math类中的所有方法都定义为静态的。另外,Math类还把E和PI定义为类的静态成员变量,其中,E和PI代表数学上的相应常数。
Math类是最终类(final),所以不能从Math类中派生其他的新类。
Math类的几个常用方法如下:
double abs(double a) 求a的绝对值
float abs(float a) 求a的绝对值
int abs(int a) 求a的绝对值
long abs(long a) 求a的绝对值
double random() 返回一个(0.0,1.0)区间的随机数
abs()方法有4个,包括了4种基本的数值类型(double,float,int,long),其他方法(如sin()方法 等)类同,为节省篇幅,这里不再列出。
random()方法是非常有用的方法。把random()的返回值乘上一个整数,可以得到任意区间的、double类型的随机数;把random()的返回值乘上一个整数再转换成int类型,可以得到任意区间的、int类型的随机数。
【例5.5】求10个数中的最小数。
要求:用Math类的random()方法产生随机数来给数组赋值。
程序设计如下:
public class Exam5_6
{
public static void main(String args[])
{
final int SIZE = 10; //常量
int i, min;
int a[] = new int[SIZE];
for(i = 0; i < a.length; i++)
a[i] = (int)(Math.random() * 100); //产生随机数并赋值
System.out.print("数组元素为:"); //输出一维数组
for(i = 0; i < a.length; i++)
System.out.print(" " + a[i]);
min = a[0];
for(i = 1; i < a.length; i++)
if(a[i] < min) min = a[i]; //寻找最小数
System.out.println("\n最小数为:" + min);
}
}
程序运行结果如下:
数组元素为: 64 99 44 94 28 82 39 19 6 41
最小数为:6
3、实用包(java.util)简介
java.util包主要包含集合框架、事件模型、日期和时间机制、国际化等的类和接口。本节介绍的java.util包的类和接口有Arrays类、Vector类、Data类和Enumeration接口。
1、 Arrays类
Arrays类中包含有数组操作的一些常用方法(如排序和查找),这可以大大简化程序设计人员的设计过程。
Arrays类的常用方法有:
static void sort(byte[] a)
把byte类型的数组a中的元素按升序排序
static void sort(byte[] a,int fromIndex,int toIndex)
把byte类型的数组a中的、从fromIndex到toIndex的元素按升序排序
static void sort(int[] a)
把int类型的数组a中的元素按升序排序
static void sort(int[] a,int fromIndex,int toIndex)
把int类型的数组a中的、从fromIndex到toIndex的元素按升序排序
static void sort(double[] a)
把double类型的数组a中的元素按升序排序
static void sort(double[] a,int fromIndex,int toIndex)
把double类型的数组a中的、从fromIndex到toIndex的元素按升序排序
static int binarySearch(byte[] a,byte key)
在byte类型的数组a 中、使用折半查找算法查找指定元素key是否存在,若存在返回该元素的数组下标;若不存在返回-1
static int binarySearch(int[] a,int key)
在int类型的数组a 中、使用折半查找算法查找指定元素key是否存在,若存在返回该元素的数组下标;若不存在返回-1
static int binarySearch(double[] a,double key)
在double类型的数组a 中、使用折半查找算法查找指定元素key是否存在,若存在返回该元素的数组下标;若不存在返回-1
说明:
(1)除了上面列出的sort()方法和binarySearch()外,还有char、float、long、Object等类型的sort()方法和binarySearch(),这里不再列出。
(2)在使用binarySearch()时,要求数组a中的元素已经有序排列,否则返回值未定义。
2、Vector 类
Vector类称作向量类,它实现了动态的数组,使用于元素数量变化的对象数组。像数组一样,Vector类也用从0开始的下标表示元素的位置;但和数组不同的是,当Vector对象创建后,数组的元素个数会随着Vector对象元素个数的增大和缩小变化。
Vector类的成员变量有:
elementData 存放对象元素的数组
elementCount 当前对象元素的个数
capacityIncreament 元素个数变大时自动增大数组空间的个数
Vector类的构造方法有:
Vector ()
创建元素为空的对象,且elementCount=10,capacityIncreament=0
Vector (int initialC)
创建元素为空的对象,且elementCount= initialC,capacityIncreament=0
Vector (int initialC,int capacityI)
创建元素为空的对象,且elementCount= initialC,capacityIncreament= capacityI
Vector类的常用方法有:
void add( int index,Object elem)
在Vector对象的index下标处插入元素elem,index下标以后的元素依次后移
boolean add(Object elem)
在Vector对象的尾部添加元素elem,添加成功返回true,失败返回false
boolean addAll(Collection c)
在Vector对象的尾部、依次添加集合对象c中的所有元素,添加成功返回true,失败返回false
void addElement(Object obj)
在Vector对象的尾部、增加对象obj,且对象的元素个数加1
boolean removeElement(Object obj)
如果对象非空,则删除Vector对象obj第一次出现的元素
copyInto(Object[] anArray)
把Vector对象指针所指位置的成分复制给数组anArray,要求数组anArray要足够大,否则会抛出异常
Enumeration elements()
返回对象的序列化元素
int size()
返回对象的元素个数
和Arrays类相比,Vector类的最主要特点是长度可随对象成分个数的增加或减少任意变化。
3、Data 类和Calendar类
Data 类提供了获取当前精确到毫秒时间的方法,并提供了许多方法截取当前时间的年、月、日等数值。
Data 类的构造方法有:
Data () 创建一个可精确到毫秒的当前时间的对象
Data (long date) 创建一个可精确到毫秒的参数date指定时间的对象,date表示从GMT(格林威治)时间1970-1-1 00:00:00开始至某时刻的毫秒数。
Calendar类定义了许多如YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、DAY_OF_WEEK等成员变量,Calendar类的get()方法可以获取这些成员变量的数值。
【例5.6】设计程序获取本地计算机上的当前时间并显示。
程序设计如下:
import java.util.*;
public class MyDate
{
public static void main(String args[])
{
Date date = new Date(); //创建对象,其值为当前时间
System.out.println(date); //输出显示当前时间
//分项输出显示当前时间
Calendar now = Calendar.getInstance(); //获得当前时间
int year =now.get(Calendar.YEAR); //年份
int month=now.get(Calendar.MONTH)+1; //月份
int day = now.get(Calendar.DATE); //日期
System.out.print(year+"年"+month+"月"+day+"日 ");
int hour = now.get(Calendar.HOUR); //时
int minute = now.get(Calendar.MINUTE); //分
int second = now.get(Calendar.SECOND); //秒
System.out.print(hour+"时"+minute+"分"+second+"秒 ");
int week = now.get(Calendar.DAY_OF_WEEK); //星期1~7
String str = "日一二三四五六";
int i=2*(week-1); //对应中文的下标
System.out.println("星期"+str.substring(i,i+2));
}
}
程序运行结果如下:
Tue Sep 28 10:32:29 CST 2004
2004年9月28日 10时32分29秒 星期二
4、Enumeration接口
Enumeration接口主要用于集合类对象的序列化。一个集合类对象中包含有许多元素,所谓对象是序列化的,就是说可以依次取出该对象中的元素。
Enumeration接口定义如下:
public interface Enumeration
{
Object nextElement(); //返回后续元素
boolean hasMoreElements(); //是否还有后续元素
}
nextElement()方法返回后续元素;hasMoreElements()方法判断是否还有后续元素。
任何一个类,只要实现了Enumeration接口,其对象就是序列化的。所谓对象是序列化的,就是说若连续调用nextElement()方法,每次将返回该集合对象当前元素的后续元素。
例如,Vector类是一个集合类,Vector类就实现了Enumeration接口。因此,若要输出一个Vector类的对象v中的所有元素,就可以编写如下代码:
Enumeration e = v.elements();
while (e.hasMoreElements())
{
System.out.println(e.nextElement());
}
4、综合应用举例
为了让读者更好地理解Java API的使用方法,本节给出两个简单的Java API的应用例子。
【例5.7】把10个数按从小到大的次序排序。
要求:用 Arrays类的sort()方法实现排序。
程序设计如下:
import java.util.*;
public class Exam5_7
{
public static void main(String args[])
{
final int SIZE = 10; //常量
int i, min;
int a[] = new int[SIZE];
for(i = 0; i < a.length; i++)
a[i] = (int)(Math.random() * 100); //产生随机数并赋值
System.out.println("排序前数组元素为:");
for(i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
Arrays.sort(a); //排序
System.out.println("\n排序后数组元素为:");
for(i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
}
}
程序运行结果如下:
排序前数组元素为:
40 96 31 20 85 58 40 89 18 18
排序后数组元素为:
18 18 20 31 40 40 58 85 89 96
【例5.8】使用Vector类和Integer类求解约瑟夫环问题。
约瑟夫环(Josephus)问题:古代某法官要判决N个犯人的死刑,他有一条荒唐的法律,将犯人站成一个圆圈,从第S个人开始数起,每数到第D个犯人,就拉出来处决,然后再数D个,数到的人再处决,……,直到剩下的最后一个可赦免。
当N=5,S=0,D=2时,约瑟夫环问题执行过程示意图如下图所示。
设计:
1.初始化,创建一个Vector类的向量对象v,调用v的add()方法依次将N个人的序号添加到v中。由于v的元素类型为Object,所以add()的参数必须使用new Integer(i+1)将int值转化为Integer对象。
2.设current为当前欲删除元素的下标,如果从第1个人开始数起,则current的初值应该设置为第1个人的前一个位置,即current=S-1。
3.循环,当v中元素多于一个时(v.size()>0),调用v.remove()方法删除下标为current的元素。current的值一直在增加,但既不能超出数组下标范围,又要实现环形结构,所以current的变化规律是current=(current + 1) % v.size(),其中v.size()是v的实际元素个数,每删除一个元素,v.size()的值少1。
4.为了更好地了解向量中的元素情况,每次循环都输出了向量中的全部元素值,调用(Integer)v.get(i))方法将获得的下标为i的Object类元素转化为Integer类对象,再调用Integer类的intValue()方法输出相应的int值。
5.当循环停止时,向量v中只剩下一个元素,这就是我们要找的最后一个人。
程序如下:
import java.util.*;
public class Josephus //使用Vector类求解约瑟夫环问题
{
public static void main(String args[])
{
int n=5,s=0,d=2;
Vector v = new Vector(n); //创建向量对象v
for(int i = 0; i < n; i++)
v.add(new Integer(i+1)); //向量对象v中添加Integer对象
int current = s - 1; //设置当前元素下标current的初值
while (v.size()>1) //向量对象v中多于一个元素时循环
{
System.out.print("Vector: ");
for(int i = 0; i < v.size(); i++)//输出向量对象v中全部元素值
System.out.print(((Integer)v.get(i)).intValue() + " ");
int j=0;
while (j<d) //计数
{
current = (current + 1) % v.size();
j++;
}
System.out.println("\tcurrent = " + current + " ");
v.remove(current); //删除向量v中下标为current的元素
}
System.out.println("赦免者是" +((Integer)v.get(0)).intValue());
}
}
程序运行结果如下:
Vector: 1 2 3 4 5 current = 1
Vector: 1 3 4 5 current = 3
Vector: 1 3 4 current = 2
Vector: 1 3 current = 0
赦免者是3