object类
前言
含义:object类是所有java类的祖先,也就是说我们所说的”顶级父类”
注意:
- 它存在于java.lang.object,这个包不需要我们手动导包
- 每个类都使用object作为超类.所有对象(包括数组)都实现这个类的方法.
- 如果在类的声明中未使用extends关键字指明其父类,则默认继承object类
以下两种写法效果完全相同
class person { }
class person extends object { }
常用方法
hashcode()
public native int hashcode();
理解:该方法用于哈希查找,不同的hash值对应不同的对象。
getclass()
public final native class getclass();
理解:final方法,返回class类型的对象,反射来获取对象。
tostring()
作用:对对象进行介绍,一般子类对父类提供的tostring都不满意,都要进行重写
public string tostring()
本方法用于返回对应对象的字符串表示
public class test {
public static void main(string[] args) {
gril lili = new gril("lili", 18);
system.out.println(lili);//省略了.tostring()
system.out.println(lili.tostring());//地址
person lan = new person("lan", 23);
system.out.println(lan);//person{name='lan', age=23}
}
}
class person{
string name;
int age;
public person(string name, int age) {
this.name = name;
this.age = age;
}
//重写tostring
@override
public string tostring() {
return "person{"
"name='" name '\''
", age=" age
'}';
}
}
class gril{
string name;
int age;
public gril(string name, int age) {
this.name = name;
this.age = age;
}
}
注意:
- 在使用对象直接输出的时候,默认输出的是一个对象在堆内存上的包名、类名以及地址值;如若要输出该对象的内容,则要覆写
tostring()
方法 - string作为信息输出的重要数据类型,在java中所有的数据类型只要遇见string就执行了
拼接
,都要求其变为字符串后连接,而所有对象想要变为字符串就默认用tostring( )方法
finalize()
protected void finalize() throws throwable { }
作用:清理空间,释放资源
执行者:
- jvm的垃圾回收期,简称gc
- object的子类对象(就是程序员自己手动调用,不建议)
//该方法用于回收资源,当system.gc();之后由垃圾回收器调用,用来回收垃圾
@override
protected void finalize() throws throwable {
super.finalize();
}
注意:
- 重写finalize方法语句中的super.finalize()意味着可以实现从下到上实现finalize的调用,即先释放自己的资源再释放父类的资源
- 程序员无权调用垃圾回收器,但程序员可以调用system.gc()方法通知gc回收垃圾,但是jvm规范中并不保证你调用了就一定能执行垃圾回收
- finalize方法是java提供给程序员主动来调用,释放对象占用的内存空间,但尽量少用,因为这样会扰乱gc的正常垃圾回收进程,影响gc效率
equals()
public boolean equals(object obj) {return (this == obj);}
- ==用来判断两个变量的值是否相等。如果变量是基本数据类型,则直接比较;如果变量是引用类型,则比较引用内存的首地址。
- equals比较两个对象是否一样,实际上就是调用对象equals方法进行比较。equals 默认情况下是采用==比较,只是很多类重写了 equals 方法,比如 string、integer 等把它变成了值比较,所以一般情况下 equals 比较的是值是否相等。
import java.util.objects;
public class test2 {
public static void main(string[] args) {
phone h1 = new phone("华为", 55.5);
phone h2 = new phone("华为", 55.5);
system.out.println(h1==h2);
system.out.println(h1.equals(h2));//true——重写了
}
}
class phone{
string brand;
double price;
public phone(string brand, double price) {
this.brand = brand;
this.price = price;
}
@override
public boolean equals(object o) {
if (this == o) return true;
if (o == null || getclass() != o.getclass()) return false;
phone phone = (phone) o;
return double.compare(phone.price, price) == 0 &&
objects.equals(brand, phone.brand);
}
@override
public int hashcode() {
return objects.hash(brand, price);
}
}
wait()
public final native void wait(long timeout) throws interruptedexception;
public final void wait(long timeout, int nanos) throws interruptedexception
public final void wait() throws interruptedexception {wait(0);}
理解:当调用wait()方法时就把线程本来已经得到的同步锁释放掉,并进入等待队列(等待池),让其他线程可以去抢这个锁,当其他线程调用notify()或者notifyall()时才会去通知之前的线程可以去争抢锁了而不是立马就得到锁
注意:wait()方法只能用在同步代码块或同步方法中
notify()
public final native void notify();
作用:用于随机通知一个等待池中的对象停止等待
notifyall()
public final native void notifyall();
作用:通知等待池中的所有对象停止等待
clone()
protected native object clone() throws clonenotsupportedexception;
理解:保护方法,实现对象的浅复制,只有实现了cloneable
接口才可以调用该方法,否则抛出clonenotsupportedexception异常。
克隆:创建并返回对象的一个副本——按照原对象,创建一个新对象(复制原对象的内容)
创建对象的方式:用new关键字实例化、反射、克隆
使用克隆的原因:使用反射或实例化两个或多个内容一样的对象比较麻烦
使用clone方法创建对象步骤
- 在需要调用clone方法的对象上添加实现cloneable接口
- 复写clone方法,在自己的克隆方法中调用父类的clone方法,将返回值强转为本类类型,并将当前的方法修饰符改为public
- 在测试中调用对象的clone方法
克隆方法存在意义:使用clone方法可以大大减少创建重复的对象代码
案例
public class clonetest {
public static void main(string[] args) throws exception {
student student = new student();
student.setname("lili");
children children = new children();
children.setname("lala");
student.setchildren(children);
//克隆
student clone = student.clone();
//内容一样,对象不同;成员对象内容和地址均一样
system.out.println(student ":" student.hashcode() student.getchildren() ":" student.getchildren().hashcode());
system.out.println(clone ":" clone.hashcode() clone.getchildren() ":" clone.getchildren().hashcode());
}
}
class student implements cloneable{
private string name;
private children children;
public string getname() {
return name;
}
public void setname(string name) {
this.name = name;
}
public children getchildren() {
return children;
}
public void setchildren(children children) {
this.children = children;
}
@override
protected student clone() throws clonenotsupportedexception {
return (student)super.clone();
}
}
class children{
private string name;
public string getname() {
return name;
}
public void setname(string name) {
this.name = name;
}
@override
public string tostring() {
return "children{"
"name='" name '\''
'}';
}
}
注意:
- 以上克隆出来的内容一样,但hash值不同
- 如果对象里面的成员存在另一对象,那么复制前和复制后的两个原对象内容相同,地址不同,里面的成员对象内容和地址均相同(这样的复制也称浅表复制)
- clone方法的默认复制操作是浅表复制
浅表复制
浅表复制:对象内容完全复制,遇到成员对象只将之前的引用复制过去
浅表复制特点
- 克隆的对象是一个新对象
- 克隆对象的成员变量与原对象的成员变量是同一个数据(底层hash值一致)
浅表复制的弊端:仅仅创建新的对象,对象成员内容底层hash值是一致的,因此,不管原对象还是克隆对象,只要有其中一个修改了成员的数据,就会影响所有的原对象和克隆对象
深层复制
深层复制:不仅执行clone的时候,克隆对象是一个新对象,而且,克隆对象中的成员变量也要求是一个新对象
开发步骤
- 修改成员类实现cloneable接口
- 修改成员类重写clone方法
- 修改要克隆的类的clone方法,在clone方法中调用成员类的clone方法
public class clonetest {
public static void main(string[] args) throws exception {
student student = new student();
student.setname("lili");
children children = new children();
children.setname("lala");
student.setchildren(children);
//克隆
student clone = student.clone();
//内容一样,对象不同;成员对象内容一样,地址不同
system.out.println(student ":" student.hashcode() student.getchildren() ":" student.getchildren().hashcode());
system.out.println(clone ":" clone.hashcode() clone.getchildren() ":" clone.getchildren().hashcode());
}
}
class student implements cloneable{
private string name;
private children children;
public string getname() {
return name;
}
public void setname(string name) {
this.name = name;
}
public children getchildren() {
return children;
}
public void setchildren(children children) {
this.children = children;
}
@override
protected student clone() throws clonenotsupportedexception {
student clone = (student) super.clone();
clone.setchildren(children.clone());
return clone;
}
}
class children implements cloneable{
private string name;
public string getname() {
return name;
}
public void setname(string name) {
this.name = name;
}
@override
public string tostring() {
return "children{"
"name='" name '\''
'}';
}
@override
protected children clone() throws clonenotsupportedexception {
return (children)super.clone();
}
}