Java API(Java Application Programming Interface)是Java应用程序编程接口的缩写。Java中的API,就是JDK提供的具有各种功能的Java类,灵活使用Java API能够大大提高使用Java语言编写程序的效率。
Java API的帮助文档可到 http://docs.oracle.com/javase/8/docs/api/ 下载,灵活使用Java API能够提高使用Java语言编写程序的效率,下面对Java中提供的最常用的包进行介绍,对这些包中的常用类先有一个总体了解,后文将对重要的、常见的方法进行介绍。
java.lang包中的常用类
Boolean |
Object |
Error |
Byte |
String |
Throwable |
Character |
StringBuffer |
Exception |
Double |
StringBuilder |
ClassNotFoundException |
Float |
System |
NullPointerException |
Integer |
Math |
NumberFormatException |
Long |
Runnable(接口) |
RuntimeException |
Short |
Thread |
ArithmeticException |
java.util包中的常用类
Collection(接口) |
Arrays |
Calendar |
Iterator(接口) |
Set(接口) |
Date |
ListIterator(接口) |
HashSet |
Random |
List(接口) |
TreeSet |
Scanner |
ArrayList |
Map(接口) |
Collections |
LinkedList |
HashMap |
|
Vector |
Hashtable |
|
Stack |
TreeMap |
java.io包中的常用类
BufferedInputStream |
FileReader |
PrintWriter |
BufferedOutputStream |
FileWriter |
Reader |
BufferedReader |
InputStream |
Writer |
BufferedWriter |
InputStreamReader |
Serializable(接口) |
DataInputStream |
OutputStream |
Externalizable接口) |
DataOutputStream |
OutputStreamWriter |
IOException |
File |
ObjectInputStream |
FileNotFoundException |
FileInputStream |
ObjectOutputStream |
InvalidClassException |
FileOutputStream |
PrintStream |
java.net包中的常用类
ServerSocket |
Socket |
UnknownHostException |
在Java中,有这样一个类,它是所有类的祖先类,也就是说,任何类都是其子孙类,它就是java.lang.Object。如果一个类没有显式地指明其父类,那么它的父类就是Object,也就是说,下面两条语句的作用是一样的:
public class ClassName{…}
等价于
public class ClassName extends Object{…}
如同我们称自己为炎黄子孙一样,所有的类都是Object类的子类,Object类中定义的方法被遗传到所有其它类中。同时,Object类也是Java语言中唯一一个没有父类的类。
做为一个超级祖先类,Object类为子类提供了一些public修饰的方法,便于子类覆盖来实现子类自己特定的功能,下面我们要详细介绍其中的equals()方法、hashCode()方法和toString()方法。
该方法在Object类中的作用是:比较两个引用所指向的对象是否是同一个对象,即两个引用所指向对象的地址是否相等。
注意,通常情况下,所有的类中equals()方法默认是比较地址,但是,Object的任何子类均可以按照自己的需要对equals()方法进行覆盖,以改变此方法的操作细节,实现使用自定义的方法判断两个对象是否为同一个对象或者两个对象是否具有可互相替代性。
【例】 定义公民类Citizen,覆盖该类的equals()方法,该方法的定义为:如果两个公民的身份id相同,则为同一个公民,但是不用考虑这两个对象是否具有相同的地址。
public class Citizen{
private int id;
private String name;
public Citizen(int id, String name) {
this.id = id;
this.name = name;
}
//覆盖父类的equals()方法
public boolean equals(Object o) {
Citizen c = (Citizen) o;
if (c.id == this.id) {
return true;
} else {
return false;
}
}
//主方法,测试equals()方法
public static void main(String args[]) {
Citizen xiaoming = new Citizen(21000, "xiaoming");
Citizen mingming = new Citizen(21000, "mingming");
System.out.println(xiaoming.equals(mingming));
}
}
//程序运行结果:true
程序分析:上例定义了一个Citizen类,此类包含了公民的两个属性id和name,同时覆盖了equals()方法,该方法实现为:当传入对象的id和当前对象的id相等时,返回true,否则返回false。所以在main()方法最后一行调用equals()方法时,调用的实际上是Citizen类的equals()方法,xiaoming和mingming对象的id都为21000,所以程序运行结果为true。而假设如果Citizen类没有覆盖equals()方法,则在最后一行调用equals()方法时,实际调用的Object类的equals()方法,该方法比较两个对象是否指向同一块地址,所以肯定返回false,读者可自行验证。
"=="运算符和equals()方法的区别:"=="是比较运算符,既能用于比较两个基本数据类型,也能用于比较两个引用数据类型,当比较基本数据类型时,判断两个基本数据类型的字面量是否相等,当比较两个引用数据类型时,判断两个"地址"的值是否相等,也就是两个"引用"是否指向同一个对象。而equals()方法只能用于比较引用数据类型(也就是所有以Object类为父类的类型),Object类的equals()方法默认比较两个对象引用的值是否相等,但equals()方法通常都会被子类覆盖,所以子类中equals()方法的含义,就要看子类中的具体实现了。
【例】 == 和 equals()方法在String类中的区别
String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
程序运行结果:
false
true
程序分析:因为String是引用数据类型,使用"=="运算符比较两个引用地址是否相同,第二行使用关键字new重新生成了一个String对象,所以第三行输出为false。在String类中,覆盖了Object的equals()方法,该方法判断两个String对象的内容是否相等,所以第4行输出为true。
该方法返回对象的哈希码。任何一个对象的默认的哈希码是将对象的内存地址通过某种转换得到的,所以不同对象会有不同的哈希码。
哈希码是一个代表对象的十六进制整数,好比对象的身份证号。在程序运行期间,每次调用同一个对象的hashCode()方法,返回的哈希码必定相同。但是Java应用程序需要的内存由操作系统提供,所以多次执行同一个程序,因操作系统的运行情况不一样,内存使用情况也不一样,程序所获得的内存不同,这就导致同一个对象的哈希码也不一定相同。
在Java中有个规定:如果equals()方法返回两个对象是相等的,那这两个对象上调用hashCode()返回的整数必须相等,否则在使用Hash类型集合时就会产生错误,所以在我们覆盖equals()方法同时,建议覆盖hashCode()方法。需要说明,如果equals()返回两个对象不等,它们的hashCode()也可以返回相同的整数,但是最好让它们的hashCode()返回不同的整数,这有利于提高Hash类型集合的性能。那么重写equals()方法时,一定要重写hashcode()方法吗?先说说hashcode()方法调用的条件,如果你想往map里面放一个类作为map的键值,这个类又是你自己设计的,或者这个类不是你写的但是你修改了这个类的equals()方法,这个时候,你就要重写hashcode()方法,这样当你往map里放值的时候,系统会调用这个对象的hashcode()方法来生成相应的hash值,来映射相应的对象。
如果同一个类的两个对象的属性值相等,那么他们的hashcode()一定相等吗?这个要看你具体如何实现你的hashcode()方法,如果你希望他们的值一样hashcode()也一样,你就可以这样实现。但是hashcode的实现,一般要满足几个特征:
自反性:即对任意一个非空的指引值x,x.equals(x)永远返回true。
对称性:即对任意两个非空的指引值x,y,如果x.equals(y)返回true,那么y.equals(x)也返回true。
传递性:当x.equals(y)返回true并且y.equals(z)返回true时,x.equals(z)也返回true。
该方法返回对象的字符串表示,形如:java.lang.Object@1db9742,也就是 类名@hashcode。toString()方法是一个从字面上就容易理解的方法,它的功能是得到一个能够代表该对象的一个字符串:类名+"@"+代表该对象的一个唯一的16进制数,例如下面这个例子:
【例】 查看Object类和String类的toString()方法返回值。
public class ObjectSample {
public static void main(String args[]){
Object o = new Object();
System.out.println(o);
System.out.println(o.toString());
String s = new String("hello");
System.out.println(s);
}
}
程序运行结果:
java.lang.Object@1db9742
java.lang.Object@1db9742
hello
程序分析:前两个输出结果表示对象o在内存中的地址,事实上返回这样的字符串没有什么实际的意义。一般子类都会覆盖该方法,让它返回有意义的文本。例如上例中的对象s的输出为"hello",这是因为字符串String类对toString()进行了覆盖,让它返回此String的本身内容。
下面通过实例来看一下如何在自己编写的类中覆盖equals()方法和toString()方法。
【例】 equals()方法和toString()的覆盖
//圆类
public class MyCircle {
private int radius;//半径
public MyCircle(int r) {
radius = r;
}
public int getRadius() {
return radius;
}
public void setRadius(int r) {
radius = r;
}
//覆盖Object中的equals()方法
public boolean equals(Object obj) {
MyCircle o = (MyCircle) obj;
if (o.getRadius() == this.radius)
return true;
else
return false;
}
//覆盖Object中toString方法
public String toString() {
return "radius = " + radius;
}
}
//测试类
public class Test {
public static void main(String[] args) {
MyCircle obj1 = new MyCircle(3);
System.out.println("obj1:" + obj1.toString());
MyCircle obj2 = new MyCircle(3);
System.out.println("obj2:" + obj2.toString());
if (obj1.equals(obj2))
System.out.println("the two objects are equal");
else
System.out.println("the two objects are not equal");
}
}
程序运行结果:
obj1:radius = 3
obj2:radius = 3
the two objects are equal
程序分析:从程序的运行结果来看,我们创建的两个MyCircle对象是相等的,因为MyCircle类中覆盖的equals()方法规定,当两个MyCircle对象的半径相等时,认为这两个对象相等。而我们在调用MyCircle类的构造方法创建对象时设定这两个MyCircle对象的半径均为3,所以obj1.equals(obj2)返回true。