java API的概念、
API是Application Programming Interface 的简称,即应用程序编程的接口。java API是JDK中提供的各种类,供程序员使用,用于编写各种应用程序。
String类和StringBuffer类
String类对象中的内容一旦被初始化就不能在改变
StringBuffer类用于封装内容可以改变的字符串,可以通过toString方法转换成String类型。
连接操作符“+”,可以把各种类型的数据转换成字符串,并前后相连,成为一个新的字符串。它的实质是通过StringBuffer类的append方法来实现的,如:
String x="a"+4+"c";编译时等效于:
String x=new StringBuffer().append("a").append(4).append("c").toString();
字符串常量实际上是一种特殊的匿名的String对象,比较下面两种情况的差异:
String s1="hello"; String s2="hello"; s1与s2指向字符串常量,执行s1==s2,返回true,它们指向同一个匿名的String对象。
而对于String s1=new String("hello");String s2=new String("hello");执行s1==s2,返回false。
例子代码:
public class ReadLine {
public static void main(String[] args) {
byte[] buf=new byte[1024];
String strInfo=null;
int pos=0;
int ch=0;
System.out.println("please enter info:");
while(true)
{
try
{
ch=System.in.read();
}
catch(Exception e)
{
e.printStackTrace();
}
switch(ch)
{
case '/r':
break;
case '/n':
strInfo=new String(buf,0,pos);
if(strInfo.equals("bye"))
{
return;
}
else
{
System.out.println(strInfo);
pos=0;
break;
}
default:
buf[pos++]=(byte)ch;
}
}
}
}
注:在windows操作系统中,当按下回车键后,系统会把这个动作当做/r和/n这两个字符输入。
基本数据类型的包装类
编程举例:在屏幕上打印出一个星号(*)组成的矩形,矩形的宽度和高度通过启动程序时传递给main方法的参数指定。
public class TestInteger {
public static void main(String[] args) {
int w=new Integer(args[0]).intValue();
int h=Integer.parseInt(args[1]);
//int h=Integer.valueOf(args[1]).intValue();
//以上为三种将字符串转化为int的方法。
for(int i=0;i<h;i++)
{
StringBuffer strb=new StringBuffer();
for(int j=0;j<w;j++)
{
strb.append("*");
}
System.out.println(strb.toString());
}
}
}
使用上面的Stringbuffer的append方法比用下面的方法更有效率。
String strb=new String();
for(int j=0;j<w;j++)
{
strb=strb+"*";//每次会产生一个String对象
}
集合类
集合类用于存储一组对象,其中的每个对象称之为元素,经常会用到的有Vector、Enumeration、ArrayList、Collection、Iterator、Set、List等集合类和接口。
Vector类和Enumeration接口
如果我们要保存一组数据,而我们又不知道这组数据的大小,这是我们可以选择Vector类。
编程举例:将键盘上输入的一个数字序列中的每位数字存储在Vector对象中,然后在屏幕上打印出每位数字相加的结果,如输入32,打印出5;输入1234,打印10.
import java.util.*;
public class TestVector {
public static void main(String[] args) {
int b=0;
Vector v=new Vector();
System.out.println("please enter number:");
while(true)
{
try
{
b=System.in.read();
}
catch(Exception e)
{
e.printStackTrace();
}
if(b=='/r'||b=='/n')
break;
else
{
int num=b-'0';
v.addElement(new Integer(num));
//加入的是对象
}
}
int sum=0;
Enumeration e=v.elements();
while(e.hasMoreElements())
{
Integer intObj=(Integer)e.nextElement();//返回指示器指向的当前对象
sum+=intObj.intValue();
}
System.out.println(sum);
}
}
Collection接口与Iterator接口
Collection接口的实现类在使用上与Vector类差不多,ArrayList就是一个实现了Vector接口的类。Collection接口需与Iterator接口配合使用。
变成举例:用ArrayList与Iterator接口改写上面的程序:
import java.util.*;
public class TestCollection {
public static void main(String[] args) {
int b=0;
ArrayList v=new ArrayList();
System.out.println("please enter number:");
while(true)
{
try
{
b=System.in.read();
}
catch(Exception e)
{
e.printStackTrace();
}
if(b=='/r'||b=='/n')
break;
else
{
int num=b-'0';
v.add(new Integer(num));
//加入的是对象
}
}
int sum=0;
Iterator e=v.iterator();
while(e.hasNext())
{
Integer intObj=(Integer)e.next();//返回指示器指向的当前对象
sum+=intObj.intValue();
}
System.out.println(sum);
}
}
Vector类中的方法都是线程同步的,如果有两个线程并发地访问Vector对象,是安全的。即使一个线程访问Vector对象时,也存在同步监视器检测的情况,这就需要额外的开销。ArrayList类中的方法是不同步的,如果程序中不存在多线程安全性的问题。Vector的运行效率高些,但如果程序中存在多线程安全性的问题,使用ArrayList编程人员需要对访问ArrayList的代码进行同步处理。
Collection、Set、List的区别
Collection是Set和List这两个接口的父类,Collection的各对象元素之间没有指定的顺序,允许有重复元素和多个null元素对象,即不满足排序
Set各对象元素之间没有指定的顺序,不允许有重复元素,最多允许有一个null元素对象。
List各对象元素之间有指定的顺序,允许有重复元素和多个null元素对象,因此我们对存储在接口实现类中的接口对象进行排序,ArrayList就是一个实现了List接口的类:
import java.util.*;
public class TestSort {
public static void main(String[] args) {
ArrayList al=new ArrayList();
al.add(new Integer(1));
al.add(new Integer(3));
al.add(new Integer(2));
System.out.println(al.toString());
Collections.sort(al);//Collection类提供了各种方法操作集合类对象
System.out.println(al.toString());
}
}
Hashtable类
Hashtable类不仅可以像Vector一样动态存储一系列的对象,而且对存储的每一个对象(称为值)都要安排另一个对象(称为关键字)与之相关联。其put方法有两个参数,第一个指定关键字,第二个为值对象,它们都不能为null。如果某一个put方法中的关键字对象,与前面的某一关键字相同,则该put方法中的值对象会替换原来那个所对应的值对象,这就说明Hashtable中不能有重复的关键字。检索数据时,就要用到get方法,其参数就是关键字对象,返回的就是所对应的值对象。
用作关键字的类必须覆盖Object.hashCodde方法(其返回值为散列码)和Object.equals方法。即使两个值对象内容完全相同,它们从Object类所继承到的hashCodde中得到的返回值是不同的,因此我们若想让两个内容相同的值对象的hashCode方法的返回值相同,就必须覆盖从Object类所继承到的hashCodde方法。
变成举例:使用自定义类作为Hashtable的关键字类:
public class MyKey {
private String name = null;
private int age = 0;
public MyKey(String name, int age) {
this.name=name;
this.age=age;
}
public boolean equals(Object obj) {
if(obj instanceof MyKey)
{
MyKey objTemp=(MyKey)obj;
if(name.equals(objTemp.name)&&age==objTemp.age)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
public int hashCode() {
return name.hashCode()+age;
//String类已经按关键字要求覆盖了hashCode方法,StringBuffer则没有
//如果两个String对象的内容相等,则它们的hashCode返回值也相等
}
public String toString() {
return name+","+age;
}
}
import java.util.*;
public class HashtableTest {
public static void main(String[] args) {
Hashtable numbers=new Hashtable();
numbers.put(new MyKey("zhangsan",18),new Integer(1));
numbers.put(new MyKey("lisi",14),new Integer(2));
numbers.put(new MyKey("wangwu",20),new Integer(3));
Enumeration e=numbers.keys();
//以Enumeration返回所有的关键字对象
while(e.hasMoreElements())
{
MyKey key=(MyKey)e.nextElement();
System.out.print(key+"=");
System.out.println(numbers.get(key));//打印相应的值
}
}
}
Properties类
Properties类是Hashtable的子类,称为属性类,存储一系列关键字和值对的信息。
增加了将Hashtable对象中的关键字和值保存到文件和从文件中读取关键字和值到Hashtable对象中的方法,该类多用于“选项设置”等功能的实现。
如果要用Properties.srore方法存储Properties对象的内容,每个属性的关键字和值都必须是String类型。
变程举例:使用Properties把程序的启动运行次数记录在某个文件中,每次运行时打印出它的运行次数。
import java.util.Properties;
import java.io.*;
public class PropertiesFile {
public static void main(String[] args) {
Properties settings=new Properties();
try
{
settings.load(new FileInputStream("count.txt"));
//从文件中读取属性和值
}
catch(Exception e)
{
settings.setProperty("count",String.valueOf(0));
}
//settings.get("count");从Hashtable中继承,返回Object类型
int c=Integer.parseInt(settings.getProperty("count"))+1;
//返回String类型,count为关键字
System.out.println("这是第"+c+"次运行");
//settings.put("count",new Integer(c).toString());
settings.setProperty("count",new Integer(c).toString());
//仅能接受String类型作为参数
try
{
settings.store(new FileOutputStream("count.txt"),"Programis used:");
//第二个参数为标题信息
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
Syste与Runtime类
System类中的所有成员都是静态的。其中一些重要方法;
exit方法:用于结束虚拟机的运行,如果程序发生了异常,结束运行时可以传递一个非零的值作为参数;若是在正常运行下结束,用户可传入0作为参数。
currentTimeMillis方法:返回自1970年1月1日零点零分零秒起至当前时刻的以毫秒为单位的时间值,long型,此方法可用于检测一个程序运行所花费的时间。
java虚拟机的系统属性:在命令行中键入:java –DXX=x –DAA=a Myclass, 这样就多了两个系统属性:XX,AA。注意,-D与属性名之间不能有空格。
getProperties和setProperites方法:分别用于获取和设置当前java虚拟机的系统属性,其方法的返回值和参数为Properites类的实例,从System类中的getProperites方法获得的属性对象,存储着java虚拟机的所有属性变量和值对。
编程举例:打印出当前java虚拟机的所有属性。
import java.util.*;
public class TestProPerties {
public static void main(String[] args) {
Properties sp=System.getProperties();
Enumeration e=sp.propertyNames();//返回所有属性名
//用Enumeration获取Properties中的元素
while(e.hasMoreElements())
{
String key=(String)e.nextElement();
System.out.println(key+"="+sp.getProperty(key));
}
}
}
Runtime类
Runtime类封装了java虚拟机进程,一个java虚拟机对应一个Runtime实例对象。
我们不能通过new关键字来创建Runtime实例对象,只能通过getRuntime静态方法来获得。由于java虚拟机本身是windows系统的一个进程,它可以启动其他windows运行实例,称之为子进程。java虚拟机通过调用Runtime的exec方法启动子进程,其返回值为代表子进程的Process类对象。
编程实例:在java程序中启动一个Windows记事本程序的运行实例,并在运行实例中打开这个java程序的源文件,启动的记事本程序5秒钟后关闭。
import java.util.*;
public class TestProPerties {
public static void main(String[] args) {
Process p=null;
try{
p=Runtime.getRuntime().exec("notepad.exe TestProPerties.java");
//参数为String类型,notepad.exe为记事本程序,后为文件名。
Thread.sleep(5000);
p.destroy();//关闭所对应的进程
}
catch(Exception ie)
{
ie.printStackTrace();
}
}
}
与日期和时间有关的类
最常用的几个类:Date、DateFormat和Calendar
Date类用于表示日期和时间,它的无参的构造函数会以当前的日期和时间初始化创建一个实例对象。
Calendar类用于日期字段之间(如:年、月、日、时、分、秒等)的相互操作。
Calendar.add方法用于增加若干天(年或小时等)获得一个新的日期。
Calendar.get方法用于获取Calendar日期对象的年、月、日、时、分、秒等字段的值。
Calendar.set方法用于修改Calendar日期对象的年、月、日、时、分、秒等字段的值。
Calendar类是一个抽象基类,需要通过Calendar.getInstance静态方法返回它的一个子类对象。GregorianCalendar是目前JDK中唯一的Calendar的子类,Calendar.getInstance静态方法返回值就是GregorianCalendar的一个实例对象。
编程举例:计算出距当前日期时间315天后的日期时间,并用“XX年XX月XX日XX小时:XX分:XX秒”的格式输出。
import java.util.*;
public class TestCalender {
public static void main(String[] args) {
Calendar cl=Calendar.getInstance();
/*也可用new直接产生GregorianCalendar的实例对象。(可去JDK中的src文件中查看源代码)*/
System.out.println(cl.get(Calendar.YEAR)+ "年"+cl.get(Calendar.MONTH)+"月"+
cl.get(Calendar.DAY_OF_MONTH)+"日 "+ cl.get(Calendar.HOUR)+":"+
cl.get(Calendar.MINUTE)+ ":"+cl.get(Calendar.SECOND));
cl.add(cl.DAY_OF_YEAR,315);
System.out.println(cl.get(Calendar.YEAR)+ "年"+cl.get(Calendar.MONTH)+"月"+
cl.get(Calendar.DAY_OF_MONTH)+"日 "+ cl.get(Calendar.HOUR)+":"+
cl.get(Calendar.MINUTE)+ ":"+cl.get(Calendar.SECOND));
}
}
虽然Calendar类可完全替代Date类,但在某些情况下仍然可以用到Date类,如某些方法的参数类型就可能是Date类型
java.text.DateFormat类可将Date对象中的日期用指定的格式输出,或将一个特定格式的日期字符串转换成Date的实例对象,DateFormat类是一个抽象类,因此使用时要用到其子类,如:java.text.SimpleDateFormat
编程举例:将“2002-03-13”格式的日期字符串转换成“2002年03月15日”的格式。
import java.util.*;
import java.text.SimpleDateFormat;
public class TestCalender {
public static void main(String[] args) {
SimpleDateFormat sdf1=new SimpleDateFormat("yyyy-MM-dd");
/*构造函数的参数,指明日期的格式:每一个y代表年份的数字,而
M为月份上的数字,d为日期上的数字*/
SimpleDateFormat sdf2=new SimpleDateFormat("yyyy年MM月dd日");
Date d=null;
try
{
d=sdf1.parse("2002-03-15");
/*分析字符串参数,将其按照sdf1的构造函数参数所指定的格式,提取出时间
赋值给d*/
}
catch(Exception e)
{
e.printStackTrace();
}
System.out.println(sdf2.format(d));
}
}
Timer与TimerTask类
Timer类中有一个schedule方法,用于指定过多长时间后启动一个任务线程,执行一些代码,或者每隔多长时间定期调用一个任务代码
schedule方法主要有以下几种重载形式:
schedule(TimerTask task,long delay):表示经过delay长时间后,执行task所指的任务代码
schedule(TimerTask task,Date time):指定在什么时间开始执行task所指的任务代码
schedule(TimerTask task,long delay,long period): 指定经过delay长时间后,开始定期执行task所指的任务代码,每隔period时间执行一次。
schedule(TimerTask task,Date firstTime,long period): 指定在什么时间开始定期执行task所指的任务代码,每隔period时间执行一次。
TimerTask类实现了Runnable接口,是一个抽象类,要执行的任务由它里面实现的run方法来完成。如果有每隔一段时间要执行的任务,那么这个run方法中应避免有长时间执行的循环代码。
编程举例:程序启动运行后30秒启动Windows自带的计算其程序。
import java.util.*;
public class Test {
public static void main(String[] args) {
class MyTimerTask extends TimerTask
{
private Timer tm=null;
public MyTimerTask(Timer tm)
{
this.tm=tm;
}
public void run()
{
try
{
Runtime.getRuntime().exec("calc.exe");
}
catch(Exception e)
{
e.printStackTrace();
}
//结束任务线程的代码
tm.cancel();//取消线程
//TimerTask的cancel();仅仅取消任务,而没有取消线程
}
}
Timer tm=new Timer();
//Timer构造函数参数为true时,使得执行Timer的线程变为Daemon(后台)的了
//即使任务代码执行完后,而Timer创造的调度任务的线程也不会立即结束
tm.schedule(new MyTimerTask(tm),3000);
}
}
Math与Random类
Math类包含了所有用于几何和三角运算的方法,都为静态的。
Random类是一个伪随机数产生器,一旦用某个初值产生某个Random 对象,就可以得到一系列的随机数,若每次都用相同的初值来创建某个Random 对象,则每次得到的随机数序列也是相同的,达不到随机效果。因此无参数时,java会用当前的时间值作为种子。