第5章 Java核心类库基础副本.docx
《第5章 Java核心类库基础副本.docx》由会员分享,可在线阅读,更多相关《第5章 Java核心类库基础副本.docx(67页珍藏版)》请在冰点文库上搜索。
第5章Java核心类库基础副本
第5章
JAVA核心类库基础
本章要点:
·LANG包
·UTIL包
·I/O包
Java程序是由类的定义组成的,编写Java程序的过程就是设计各种类和确定它们相互作用关系的过程,一旦类及类间关系确定了,程序运行中各种可能的状态和状态转化原则也就确定了。
为了简化面向对象的编程过程,Java系统事先设计并实现了一些体现了常用功能的标准类,如用于数学运算的类,用于输入/输出的类,用于图形用户界面设计的类,用于网络处理的类等。
这些系统标准类根据实现的功能不同,可以划分成不同的集合,每个集合是一个包,合称为类库。
有了类库中的标准类,编写Java程序就不必一切从头做起,而只需使程序中针对特定问题自行编写的类继承某个已经存在的系统标准类,从而使用自己户的类具有标准类所实现的功能。
这样,避免了代码的重复和可能的错误(系统标准类总是正确有效的),也提高了编程的效率。
面向对象编程中的系统标准类和类库类似于面向过程编程中的库函数,都是一种应用程序编程接口,简称为API(ApplicationProgramInterface),Java的类库是系统提供的已实现的标准类的集合,是Java编程的API。
根据功能的不同,Java的类库划分为若干个不同的包,每个包中都有若干个具有特定功能和相互关系的类和接口。
5.1LANG包
java.lang包是Java语言的核心类库,包含了运行Java程序必不可少的系统类,如基本数据类型、基本数学函数、字符串处理、线程、异常处理类等。
每个Java程序运行时,系统都会自动地引入java.lang包,所以这个包的加载是缺省的,不需要用import语句来专门引入。
5.1.1Object类
Object类是Java中所有类的基础,Java的每个类都支持它所定义的方法。
它所提供的只是一些基本的方法,我们在编写自己的类时经常需要覆盖这些方法,一方面是加强功能,另一方面也是为了适应当前的情况。
1、克隆对象
clone()方法创建对象的一个复制拷贝。
被克隆的对象必须支持Cloneable接口。
Cloneable接口本身并不包含任何方法──它只是作为一个指示器用来表示可以进行克隆。
通过在clone方法抛出一个CloneNotSupportedException异常,一个对象可以选择实现Cloneable接口,但仍不支持克隆操作。
clone()方法的格式如下:
Objectclone()
ThrowsCloneNotSupportedException
由于clone()方法仅拷贝原始数据类型和对象的引用,所以有时候我们需要自己创建自己的clone()方法,如例5.1。
【例5.1】探究Object.clone()的复制效果
/*ProgramnameTestClone.java
一个研究clone()方法的例子
*/
publicclassTestCloneimplementsCloneable{
intcount;
TestClonenext;
publicTestClone(intcount){
this.count=count;
if(count>0)
next=newTestClone(count-1);
}
voidadd(){
count++;
if(next!
=null)
next.count++;
}
publicStringtoString(){
Strings=String.valueOf(count)+"";
if(next!
=null)
s+=next.toString();
returns;
}
publicObjectclone(){
Objecto=null;
//如果没有实现cloneable,将会抛出CloneNotSupported异常
try{
o=super.clone();
}
catch(CloneNotSupportedExceptione){
System.err.println("cannotclone");
}
returno;
}
publicstaticvoidmain(String[]args){
TestClonec=newTestClone(5);
System.out.println("c="+c);
TestClonec1=(TestClone)c.clone();
System.out.println("c1="+c1);
c.add();
System.out.println("afteradded\nc="+c+"\nc1="+c1);
}
}
输出结果如图5-1所示。
图5-1【例5.1】的运行结果
最后c1也发生了改变,实际上Object.clone()进行的复制是逐位(bitwise)复制。
对于一个对象中定义的对象,它只是简单的复制这个对象的引用。
这也就是常说的浅层拷贝(shallowcopy),明白了这一点,想要执行深层拷贝(deepcopy)也就不难了。
只需要在TestClonec1=(TestClone)c.clone();后面加上如下一条语句:
c1.next=(TestClone)c.next.clone();
就能得到正确的结果,如下:
c=543210
c1=543210
afteradded
c=653210
c1=543210
2、检测对象相等
Object类中有个方法equals()用来判断两个对象中是否包含相同信息。
我们已经知道,==操作符只告诉我们两个对象是否是相同的对象。
这与检测对象中包含的信息是否相同并不是一回事。
equals()方法的格式为:
booleanequals(Objectobject)
equals方法是怎样判断两个对象是否相等的呢?
先看看该方法的源代码:
publicbooleanequals(Objectobj)
{
return(this==obj);
}
不难看出,它仅仅判断了两个对象的引用是否相等,这在很多情况下并没有太大的实际意义。
【例5.2】测试两个对象是否相等
classTestEqual{
intnumber;
Strings;
publicbooleanequals(ObjectotherObject){
//首先看看这两个对象引用是否相等
if(this==otherObject)
returntrue;
//查看otherObject是为null
if(otherObject==null)
returnfalse;
//如果两个对象所属类型不同,它们不可能相等
if(getClass()!
=otherObject.getClass())
returnfalse;
TestEqualother=(TestEqual)otherObject;
//比较所有字段
returns.equals(otherObject.s)&&number==otherObject.number;
}
}
3、清除没有使用的对象
当一个对象即将被垃圾收集器从内存中删除时,调用finalize()方法。
一般情况下,对象不必重载finalize()方法,但是如果分配了Java虚拟机之外的资源(通常使用本地方法分配),则需要实现一个finalize()方法,一释放这些资源。
finalize()方法的格式为:
voidfinalize()throwsThrowable
例如:
protectedvoidfinalize()throwsThrowable
{
super.finalize();//必须有这一调用以释放外部资源的其它代码
}
注意:
必须在自己的finalize()方法中某处调用super.finalize,否则,由父类所分配的资源将不能被正确释放。
4、对象的字符串表示
Object中的toString()方法是把一个对象打印输出到一个输出流,其格式为:
StringtoString()
toString()的缺省实现打印输出对象的类名和其散列码,几乎每一个类都会重载该方法,以便返回当前状态的正确表示。
toString()方法对于创建对象的字符串表示很方便。
5、wait()和notify()
wait()和notify()方法为相互独立的线程中运行的对象相互通知某些事件提供了一种通信手段。
例如,一个对象可能正在向一个数组中写入信息,而另一个对象可能正在从该数组中读取数据。
读取数据的对象调用wait()方法,等待到写入数据的对象完成写入。
当写入完成时,写入者调用notify()方法,通知读取者它已经写入完毕。
为有效起见,读取者线程应休眠直到它从写入者线程那里接收到通知信号。
需注意的是:
(1)如果在一个对象开始等待前调用了notify()方法,那么这种通知将被忽略。
这可能会引起一个对象无休止地等待一个不可能到来的信号。
例如:
为了解决这一问题,可以设置一个标志,用来指示一个对象是否应该等待。
(2)notify()和wait()必须在同步方法或块中调用。
另外,这些方法不能被运行它的线程以外的其它线程所调用。
(3)由于可以使用异常来中断wait(),所以应该将wait()放在一个while循环中,检查等待标志然后再调用wait()。
wait()方法有三种形式:
finalvoidwait()throwsInterruptedException
该方法将永远等待,直到notify()发出信号。
finalvoidwait(longmilliseconds)throwsInterruptedException
该方法等待notify()发出信号,到milliseconds毫秒时限后返回。
finalvoidwait(longmilliseconds,intnanoseconds)
throwsInterruptedException
该方法等待notify()发出信号,到milliseconds毫秒和nanoseconds毫微妙时限后返回。
notify()方法有两种形式:
finalvoidnotify()
该方法向等待这一对象的线程发送一个通知,如果有多个线程等待,它将向等待时间最长的线程发送通知。
finalvoidnotifyAll()
该方法向所有等待的线程发送通知。
注意:
notify()、notifyAll()及wait()方法必须从同步方法或同步块中调用。
另外,notify()必须从同步于相应的wait()的同一个对象的方法或块中调用。
也就是说,如果某个对象如MyObject调用wait(),另一个对象如AnotherObject调用MyObject.notify(),那么调用块或方法必须与MyObject同步。
如下面的伪代码:
publicclassMyObject{
publicsynchronizedwait(){
wait();
}
}
publicclassAnotherObject{
publicvoidnotifyIt(MyObjectmyObject){
synchronized(myObject){
myObject.notify();
}
}
}
5.1.2Class类
Class封装对象或接口运行时的状态。
Class类包含有描述Java类的信息,Java中的每一个类都有一个相应的Class实例。
当类被加载时,类型Class的对象被自动创建。
不能显式说明一个类(Class)对象。
一般地,可以使用下述三种方式获取Class的一个实例。
(1)在一个对象中使用getClass()方法获取该对象的Class实例。
(2)使用Class中的静态方法forName(),用类的名字获得一个Class实例。
(3)使用一个定制的ClassLoader对象加载一个新类。
由Class定义的一些最常用的方法列在表5-1中。
表5-1由Class定义的一些方法
方法
描述
staticClassforName(Stringname)
throwsClassNotFoundException
返回一个给定全名的Class对象
staticClassforName(Stringname,
Booleanhow,ClassLoaderldr)
throwsClassNotFoundException
返回一个给定全名的Calss对象。
对象由ldr指定的加载程序加载。
如果how为true,对象被初始化,否则它将不被初始化(在Java2中新增加的)
Class[]getClasses()
对每一个公共类和接口,返回一个类(Class)对象。
这些公共类和接口是调用对象的成员
ClassLoadergetClassLoader()
返回一个加载类或接口的ClassLoader对象,类或接口用于实例化调用对象
Constructor[]getConstructors()
throwsSecurityException
对这个类的所有的公共构造函数,返回一个Constructor对象
Constructor[]
getDeclaredConstructors()
throwsSecurityException
对由这个类所声明的所有构造函数,返回一个Constructor对象
Field[]getDeclaredFields()
throwsSecurityException
对由这个类所声明的所有域,返回一个Field对象
Method[]getDeclaredMethods()
throwsSecurityException
对由这个类或接口所声明的所有方法,返回一个Method对象
Field[]getFields()
throwsSecurityException
对于这个类的所有公共域,返回一个Field对象
Class[]getInterfaces()
当调用对象时,这个方法返回一个由该对象的类型实现的接口数组。
当调用接口时,这个方法返回一个由该接口扩展的接口数组
Method[]getMethods()
throwsSecurityException
对这个类中的所有公共方法,返回一个Method对象
StringgetName()
返回调用对象的类或接口的全名
ProtectionDomaingetProtectionDomain()
返回与调用对象有关的保护范围(在Java2中新增加的)
ClassgetSuperclass()
返回调用对象的超类。
如果调用对象是类型Object的,则返回值为空(null)
BooleanisInterface()
如果调用对象是一个接口,则返回true。
否则返回false
ObjectnewInstance()
throwsIllegalAccessException,
InstantiationException
创建一个与调用对象类型相同的新的实例(即一个新对象)。
这相当于对类的默认构造函数使用new。
返回新对象
StringtoString()
返回调用对象或接口的字符串表达式
由Class定义的方法经常用在需要知道对象的运行时类型信息的场合。
如同表5-3中所说明的那样,由Class提供的方法确定关于特定的类的附加信息。
例如它的公共构造函数,域以及方法。
【例5.3】getClass()(从Object继承的)和getSuperclass()方法(从Class继承的)的使用
/*ProgramnameGetClassDemo.java
一个使用getClass()方法的例子
*/
classClass_X{
inta;
floatb;
}
classClass_YextendsClass_X{
doublec;
}
classGetClassDemo{
publicstaticvoidmain(Stringargs[]){
Class_Xx=newClass_X();
Class_Yy=newClass_Y();
Classc_obj;
c_obj=x.getClass();//取得调用对象的Class对象
System.out.println("xisobjectoftype:
"+
c_obj.getName());
c_obj=y.getClass();
System.out.println("yisobjectoftype:
"+
c_obj.getName());
c_obj=c_obj.getSuperclass();//取得调用对象的超类
System.out.println("y'ssuperclassis"+
c_obj.getName());
}
}
程序的输出如图5-2所示。
图5-2【例5.3】的运行结果
5.1.3String类
String类是JavaAPI中最有用的类之一,它可以用来创建和操作字符串。
顾名思义,String是串的意思,这个类是字符串常量的类。
相信使用过C语言进行编程的人都知道字符串是怎么回事,这里就不再进行赘述了。
但有一点要说明的是,Java中的字符串和C语言中的字符串是有区别的。
在C语言中,并没有真正意义上的字符串,C语言中的字符串就是字符数组,使用起来非常的灵活。
而在Java中,字符串常量是一个类——String类,它和字符数组是不同的。
1、创建字符串
String类的构造函数有以下几种:
publicString()
这个构造函数用来创建一个空的字符串常量。
如:
Stringstr=newString();
或:
Stringstr;
str=newString();
publicString(Stringvalue)
这个构造函数用一个已经存在的字符串常量作为参数来创建一个新的字符串常量。
例如:
Stringstr=newString(s);//s是一个String类的对象
Stringstr=newString("Hello,world.");
另外值得注意的是,Java会为每个用双引号"…"括起来的字符串常量创建一个String类的对象。
如:
Stringh="Hello";Java会为"Hello"创建一个String类的对象,然后把这个对象赋值给h。
等同于:
Stringtemp=newString("Hello");
Stringh=temp;
publicString(char[]value)
这个构造函数用一个字符数组作为参数来创建一个新的字符串常量。
例如:
charz[]={'w','o','r','l','d'};
Stringstr=newString(z);//此时str中的内容为"world"
publicString(charvalue[],intoffset,intcount)
这个构造函数是对上一个的扩充,用一句话来说,就是用字符数组value,从第offset个字符起取count个字符来创建一个String类的对象。
例如:
charw[]={'w’,'o','r','l','d'};
Stringstr=newString(w,1,2);//此时str中的内容为"or"
注意:
数组中,下标0表示第一个元素,1表示第二个元素……。
若offset或count越界,将会产生StringIndexOutOfBoundsException异常。
publicString(StringBufferbuffer)
这个构造函数用一个StringBuffer类的对象作为参数来创建一个新的字符串常量。
String类是字符串常量,是不可更改的常量。
而StringBuffer是字符串变量,它的对象是可以扩充和修改的。
例如:
StringBufferstrBuffer=newStringBuffer();
StrBuffer.append("Hello");
StrBuffer.append("World");
Stringstr=newString(strBuffer);//str的内容为HelloWorld
String类还提供了一些静态方法,用于从其它对象创建字符串。
下面的valueOf()方法从一个原始数据类型创建了一个字符串表示:
publicstaticStringvalueOf(booleanb)
publicstaticStringvalueOf(charc)
publicstaticStringvalueOf(inti)
publicstaticStringvalueOf(longl)
publicstaticStringvalueOf(floatf)
publicstaticStringvalueOf(doubled)
以上6个方法可将boolean、char、int、long、float和double6种类型的变量转换为String类的对象。
例如:
Stringstr1=String.valueOf(true);//str1的值为"true"
Stringstr2=String.valueOf('c');//str2的值为"c"
floatf=3.1415926;
Stringstr3=String.valueOf(f);//str3的值为"3.1415926"
2、字符串长度
publicintlength()
这个方法返回字符串常量的长度,这是最常用的一个方法。
例如:
Strings="abcd";
intlen=s.length();//len的值为4
3、提取部分字符串
String类提供了一些从一个字符串中提取部分字符串的方法。
publiccharcharAt(intindex)
这个方法用来获取字符串常量中的一个字符。
参数index指定从字符串中返回第几个字符,这个方法返回一个字符型变量。
例如:
Stringstr="hello";
charc=str.charAt(0);//c的值为'h'
publicchar[]toCharArray()
这个方法将当前字符串常量转换为字符数组,并返回。
例如:
Stringstr="hello";
charz[]=str.toCharArray();//数组z的值为"hello"
pu