1. 定义
是java所有类的超类,所有的类从根本上都继承自Object类,是唯一没有父类的类。
如果一个类没有明确标识继承某一个类,那么它默认继承自Object类。比如下面两个类是等价的:
public class Person
{}
public class Person extends Object
{}
Object类的方法适用于所有类。
2. Object类的常用方法
2.1 构造方法Object()
2.2 clone()
如果想实现对象的克隆,那么在对象所在的类必须实现cloneable接口,即第11行,这个接口没有定义方法,属于标识接口。
对象的克隆即另开辟一块内存空间,存放复制对象的内容。见下面示例,第3行和第20行需声明异常类型;
第22行继承父类的clone()方法;第6行向下转型;
public class TestDemo
{
public static void main(String[] args) throws Exception
{
Robot r1=new Robot("大疆",12);
Robot r2=(Robot) r1.clone();
System.out.println(r2.name);
}
}
class Robot implements Cloneable
{
String name;
int height;
public Robot(String name,int height)
{
this.name=name;
this.height=height;
}
public Object clone() throws CloneNotSupportedException
{
return super.clone();
}
}
//输出结果:大疆
2.3 equals(object)
此方法必须被覆写。
2.3.1. 不覆写的情景
那么比较两个对象实际上是比较对象的内存地址是否相同。
2.3.2 覆写
覆写后比较的是对象的内容。
须注意第23行和第26行的代码。另外覆写的equals()还有更简便的实现代码,见注释。
第23行中的this表示调用该equals方法的对象;
第26行的向下转型是为了定义传入的对象,向下转型确实说得通,Object是所有类的父类,equals方法传入的对象是父类的对象,通过向下转型才能得到子类的对象,即欲比较的对象;另外就是,因为调用子类的成员属性需由子类的实例对象来完成,父类若不具有和子类相同的成员属性,则父类对象调用子类成员属性会报错。
为什么24行中的o instanceof Person会成立呢?是因为o是Person类对象的向上转型得到的,即Object o=new Person(),这行代码可能不能编译,但就按这么理解吧。
public class draft2
{
public static void main(String[]args)
{
Person p1=new Person(12,"dia");
Person p2=new Person(12,"dia");
System.out.println((p1.equals(p2))?"相等":"不相等");
}
}
class Person
{
int age;
String name;
public Person(int age,String name)
{
this.age=age;
this.name=name;
}
public boolean equals(Object o)
{
boolean temp=true;
Person p1=this;
if(o instanceof Person)
{
Person p2=(Person)o;
if(!(p1.age==p2.age&&p1.name.equals(p2.name)))
{
temp=false;
}
}
else{
temp=false;
}
return temp;
}
// public boolean equals(Object o)
// {
// Person p2=(Person)o;
// return (this.age==p2.age&&this.name.equals(p2.name));
// }
}
2.4 finalize()
2.5 getClass()
2.6 hashCode()
HashTable,哈希表,是一种数据结构,其中的元素是键值对(key:value),具有快速查找、修改、删除的优点;其中用到了哈希算法,该算法的功能是将任意长度的输入转换成固定长度的输出,这就是hashcode,是整数值,默认情况下表示对象的存储地址。hashtable、hashmap、hashset均是基于此数据结构的具体实现。
hashcode是对象的哈希值,也可以称关键码,是上文说的key。
下面代码中,第27行的name.hashcode(),name是String类的实例对象,因此调用hashcode方法没毛病,调用的目的是得到name的哈希值,用于后续计算。
覆写equals()方法必须覆写hashcode()方法,那么覆写后两者的联系是什么呢?在于,覆写后的equals方法是比较age和name这俩成员变量,覆写后的hashcode方法也是用上了这两个成员变量-用它俩来计算对象的哈希值,如此将对象的哈希值与对象匹配了起来。
public class draft2
{
public static void main(String[]args)
{
Person p1=new Person(12,"dia");
Person p2=new Person(12,"dia");
Person p3=new Person(14,"dao");
System.out.println((p1.equals(p2))?"相等":"不相等");
System.out.println((p1.equals(p3))?"相等":"不相等");
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p3.hashCode());
}
}
class Person
{
int age;
String name;
public Person(int age,String name)
{
this.age=age;
this.name=name;
}
public int hashCode()
{
return age*(name.hashCode());
}
public boolean equals(Object o)
{
boolean temp=true;
Person p1=this;
if(o instanceof Person)
{
Person p2=(Person)o;
if(!(p1.age==p2.age&&p1.name.equals(p2.name)))
{
temp=false;
}
}
else{
temp=false;
}
return temp;
}
}
/*输出结果
相等
不相等
1193424
1193424
1389052*/
2.7 notify()
2.8 nitifyAll()
2.9 wait()
2.10 toString()
2.10.1 默认调用
为了适用于所有子类,在默认情况下该方法返回对象地址,见第7行;第6、7两行的输出结果相同,说明在输出对象时,会默认调用toString方法。
public class toString
{
public static void main(String[]args)
{
Person p=new Person();
System.out.println(p);
System.out.println(p.toString());
}
}
class Person
{
}
//输出结果
//Person@279f2327
//Person@279f2327
2.10.2 子类覆写
当然,子类(相比于object来说,任何类都是其子类)也可以自己修改该方法的输出。
public class toString
{
public static void main(String[]args)
{
Person p=new Person();
System.out.println(p);
System.out.println(p.toString());
}
}
class Person
{
public String toString()
{
return "该通知表示方法已覆写。";
}
}
/*
输出结果
该通知表示方法已覆写。
该通知表示方法已覆写。
*/
2.11 wait(long)
2.12 wait(long,int)
2.13 Object接收任意引用数据类型对象
2.13.1 接收方法的传入参数
public class ObjectArrayTest
{
public static void main(String[] args)
{
int[] arr={1,2,3,4,5};
Person p=new Person();
p.print(arr);
}
}
class Person
{
public void print(Object o)
{
if(o instanceof int[])
{
int[] x=(int[]) o;
for(int i=0;i<x.length;i++)
{
System.out.println(i);
System.out.println(x[i]);
}
}
}
}
其实这里用Object来接收引用数据类型参数增加复杂度了,如下代码13行所示,更简单:
public class ObjectArrayTest
{
public static void main(String[] args)
{
int[] arr={1,2,3,4,5};
Person p=new Person();
p.print(arr);
}
}
class Person
{
public void print(int[] x)
{
for(int i=0;i<x.length;i++)
{
System.out.println(i);
System.out.println(x[i]);
}
}
}
2.13.2 接收数组的元素
class MyStack<T>
{
private static final int STACK_CAPACITY=3;
private T[] myStack;
int top; //栈顶索引
// int size;
@SuppressWarnings("unchecked")
public MyStack()
{
myStack=(T[]) new Object[STACK_CAPACITY];
// myStack[++top]=data;
top=-1;
}
}
见上面代码第11行,java不能直接创建泛型数组(因为 Java 的泛型是基于擦除机制实现的,在运行时泛型类型信息会被擦除,所以无法确定具体的数组类型。),不能直接这样:
myStack=new T[STACK_CAPACITY];
那么将T[]替换成Object[],即创建Object数组,然后再进行强制类型转换就可以了。

被折叠的 条评论
为什么被折叠?



