Object类介绍
Object类位于java.lang包,是所有Java类的根父类(唯一没有父类的类),所有类的直接或者间接父类。Java中的每个类都是由这个类扩展而来。
java.lang包在使用的时候无需显示导入,编译时由编译器自动导入。
Java认为所有的对象都具备一些基本的共性内容,这些内容可以不断的向上抽取,最终就抽取到了一个最顶层的类中的,该类中定义的就是所有对象都具备的功能。
如果在类的声明中未使用extends关键字指明其父类,则默认父类为Object类。
public class Test [extends Object]{ // 默认继承了Object类
//...
}
接收任意引用类型的对象
既然Object类是所有对象的父类,则肯定所有的对象都可以向Object进行转换,在这其中也包含了数组和接口类型,即:一切的引用数据类型都可以使用Object进行接收。
使用Object接收接口实例:
public class Test {
public static void main(String[] args) {
A ab = new B() ; // 为接口实例化
Object obj = ab ; // 对象向上转型
A a = (A)obj ; // 对象向下转型
a.print();
}
}
interface A { // 定义接口A
public void print() ; // 定义抽象方法
}
class B implements A { // 子类实现接口
public void print(){ // 覆写接口中的抽象方法
System.out.println("test") ;
}
}
使用Object接收数组:
public class Test {
public static void main(String[] args) {
int[] array = {1, 3, 5, 7, 9} ; // 定义数组
Object obj = array ; // 使用Object接收数组
print(obj) ; // 传递数组引用
}
public static void print(Object o){ // 接收一个对象
if(o instanceof int[]) { // 判断对象的类型
int x[] = (int[])o ; // 向下转型
for(int i=0;i<x.length;i++){ // 循环输出
System.out.print(x + "\t") ;
}
}
}
}
Object的主要方法
Object类中定义了一些有用的方法,由于是根类,所以这些方法都在其他类中存在,一般是进行了重载或者覆盖,实现了各自自己的具体功能。
public boolean equals(Object obj)
Object类中的equlas()方法用来检测两个对象是否等价,查看Object源码为:
public boolean equals(Object obj) {
return (this == obj);
}
equals()只能比较引用类型,其作用与“==”相同,比较是否指向同一个对象(其实内部比较的就是两个对象地址)。对象比较的是引用,即对象在内存中的内存地址,而基本数据类型比较的是值。
用“==”进行比较时,符号两边的数据类型必须兼容(可自动转换的基本数据类型除外),否则编译出错。
equals()方法需要具有如下特点:
自反性(reflexive):任何非空引用x,x.equals(x)返回为true。
对称性(symmetric):任何非空引用x和y,x.equals(y)返回true当且仅当y.equals(x)返回true。
传递性(transitive):任何非空引用x和y,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)返回true。
一致性(consistent):两个非空引用x和y,x.equals(y)的多次调用应该保持一致的结果,(前提条件是在多次比较之间没有修改x和y用于比较的相关信息)。
约定:对于任何非空引用x,x.equals(null)应该返回为false。
Student s1 = new Student();
Student s2 = new Student();
System.out.println(s1 == s2); // false
Student s3 = s1;
System.out.println(s3 == s1); // true
System.out.println(s1.equals(s2)); // false
System.out.println(s1.equals(s1)); // true
System.out.println(s1.equals(s3)); // true
当用equals()方法进行比较时,对类File、String、Date及包装类(Wrapper Class)来说,是比较类型及内容而不考虑引用的是否是同一个对象;因为在这些类中重写了Object类的equals()方法。下面就是String重写的equals()方法:
// 重写了Object类中的equlas()方法
public boolean equals(Object anObject) {
// 判断两个字符串的内存地址是否相等,如果相等,就说明这两个字符串是同一个
if (this == anObject) {
return true;
}
// 判断参数对象是不是String类型的
if (anObject instanceof String) {
// 如果是,就向上转型成一个String对象
String anotherString = (String)anObject;
// 对字符串逐个字符进行比较,每个字符都相等,返回true
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1 != v2)
return false;
i++;
}
return true;
}
}
return false;
}
public int hashCode()
返回该对象的哈希码值。哈希值是根据哈希算法计算出来的一个值。这个值和地址值有关,但不是实际地址值。
该方法用于哈希查找,可以减少在查找中使用equals的次数,重写了equals方法一般都要重写hashCode方法。这个方法在一些具有哈希功能的Collection中用到。
一般必须满足obj1.equals(obj2)==true,可以推出obj1.hashCode()==obj2.hashCode(),但是hashCode相等不一定就满足equals。不过为了提高效率,应该尽量使上面两个条件接近等价。如果不重写hashcode(),在HashSet中添加两个equals的对象,会将两个对象都加入进去。
// 对象不同,哈希值一般也不同
Student s1 = new Student();
System.out.println(s1.hashCode()); // 366712642
Student s2 = new Student();
System.out.println(s2.hashCode()); // 1829164700
System.out.println("-------");
public final Class getClass()
返回Object运行时类,也就是说是字节码文件对象。
不可重写,要调用的话,一般和getName()联合使用,如getClass().getName()。
Student s = new Student();
// getClass方法会返回一个Class类的实例对象,然后调用Class类的getName()方法返回全路径名
System.out.println(s.getClass().getName()); // com.zwj.objectdemo.Student
public String toString()
Object 类的 toString 方法返回一个字符串,该字符串由类名(对象是该类的一个实例)、at 标记符“@”和此对象哈希码的无符号十六进制表示组成。换句话说,该方法返回一个字符串,它的值等于: getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
// toString方法:返回对象的字符串表示
System.out.println(s.toString()); // com.zwj.objectdemo.Student@7852e922
//直接输出对象的名称其实就是调用了对象的toString方法
System.out.println(s); //com.zwj.objectdemo.Student@7852e922
protected void finalize()
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法,用于垃圾回收。但是具体什么时间调用此方法不确定。
Java允许在类中定义一个名为finalize()的方法。它的工作原理是:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法。并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。
关于垃圾回收,有三点需要记住:
1)对象可能不被垃圾回收。只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。
2)垃圾回收并不等于“析构”。
3)垃圾回收只与内存有关。使用垃圾回收的唯一原因是为了回收程序不再使用的内存。
finalize()的用途:
无论对象是如何创建的,垃圾回收器都会负责释放对象占据的所有内存。这就将对finalize()的需求限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储空间。
不过这种情况一般发生在使用“本地方法”的情况下,本地方法是一种在Java中调用非Java代码的方式。
protected Object clone()
创建并返回此对象的一个副本,需要重写该方法。
要克隆的类去实现Cloneable接口 ,Cloneable接口是标记接口,实现该接口的类就可以实现对象的复制。
public class Student implements Cloneable{
private String name; // 姓名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
我们来测试一下:
public class StudentTest{
public static void main(String[] args) throws CloneNotSupportedException {
// 创建显示对象
Student s = new Student();
s.setName("zwj");
// 克隆学生对象
Student cloneStu = (Student) s.clone();
// 引用
Student s2 = s;
System.out.println(s.getName()); // zwj,
System.out.println(cloneStu.getName()); // zwj
System.out.println(s2.getName()); // zwj
s2.setName("爪哇菌");
System.out.println(s.getName()); // 爪哇菌
System.out.println(cloneStu.getName()); // zwj
System.out.println(s2.getName()); // 爪哇菌
}
}
由以上代码代码可以看出Clone()方法的使用比较简单,使用时注意如下几点即可:
什么时候使用shallow Clone,什么时候使用deep Clone,这个主要看具体对象的域是什么性质的,基本型别还是reference variable。
调用Clone()方法的对象所属的类必须实现(implements )Clonable接口,否则在调用Clone方法的时候会抛出CloneNotSupportedException。
---------------------
【转载】
作者:下班后的爪哇菌
原文:https://blog.csdn.net/lxxiang1/a ... 874?utm_source=copy
本文版权归黑马程序员JavaEE培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:黑马程序员JavaEE培训学院
首发:http://java.itcast.cn/?skc