java中的Object类和其clone()
1.Object是所有类的父类,任何类都默认继承Object,即直接或间接的继承java.lang.Object类。由于所有的类都继承在Object类,因此省略了
extends Object关键字。
2.Object类中主要有以下方法:
toString() getClass() equals() clone() finalize() notify() notifyAll() wait()
其中toString(),getClass(),equals()是其中最重要的方法。getClass(),notify(),notifyAll(),wait()等方法被定义为final类型,因此不能重写。
3.clone()方法
public class Object {
protected native Object clone() throws CloneNotSupportedException;
}
(1) clone()存在的原因是Java里除了8种基本类型传参数是值传递,其他的类对象传参数都是引用传递。可以在类中复写clone方法以实现深拷贝。
(2) Object类的 clone() 方法是一个native方法,native方法的效率一般来说都是远高于Java中的非native方法。这也解释了为什么要用Object中clone()
方法而不是先new一个类,然后把原始对象中的信息复制到新对象中。
(3) 必须要重写clone()方法以达到在类外使用的目的。
(4) Object.clone()方法返回一个Object对象, 必须进行强制类型转换才能得到我们需要的类型。
在派生类中实现Cloneable接口。奇怪的发现Cloneable竟然是空的,它仅仅是一个标志,而且这个标志也仅仅是针对 Object类中 clone()方法的,如果 clone 类没有实现
Cloneable 接口,并调用了 Object 的 clone() 方法(也就是调用了 super.Clone() 方法),那么Object 的 clone() 方法就会抛出
CloneNotSupportedException 异常。
clone使用demo1:
class Person implements Cloneable { //clone()是Object类中的protected成员方法。继承Cloneable只是为了运行时不要报异常。
private int age ;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public Person() {}
public int getAge() {
return age;
}
public String getName() {
return name;
}
/*
* 这里必须要复写Object类的clone()方法,原因:
* Object类中的clone()方法是protected权限,只能在本包中或者在其它包的子类中访问(注意是子类中)
* 这里重写一下,虽然还是protected的,但是可以在本包中访问了。
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Test {
public static void main(String args[]) {
Person p = new Person(23, "zhang");
Person p1 = null;
try {
p1 = (Person) p.clone(); //非子类中访问clone()方法
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
if (p1 != null) {
System.out.println(p); //若引用的是同一个类,打印的hash值是一样的,clone的是不同的
System.out.println(p1);
}
}
}
如果想要拷贝一个对象,这个对象必须要实现Cloneable接口,实现clone方法。
clone使用demo2:
public class CloneTest {
static class Body implements Cloneable {
/**/
public Head head;
public Body() {}
public Body(Head head) { this.head = head; }
@Override
protected Object clone() throws CloneNotSupportedException {
Body newBody = (Body)super.clone();
newBody.head = (Head)head.clone(); //
return newBody;
}
}
static class Head implements Cloneable {
public Face face;
public Head() {}
public Head(Face face){ this.face = face; }
@Override
protected Object clone() throws CloneNotSupportedException {
Head newHead = (Head)super.clone();
newHead.face = (Face)face.clone(); // face.clone();相对于Face类来说在Face类外部,若Face类没有重写这个接口将报错
return newHead;
}
}
static class Face implements Cloneable {
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public static void main(String[] args) throws CloneNotSupportedException {
Body body = new Body(new Head(new Face()));
Body body1 = (Body) body.clone();
System.out.println("body == body1 : " + (body == body1) );
System.out.println("body.head == body1.head : " + (body.head == body1.head));
System.out.println("body.head.face == body1.head.face : " + (body.head.face == body1.head.face));
}
}
若Face类不实现Cloneable接口,Head类中也不调用face.clone(),那么成员对象face传的还是引用!这就是一种不彻底的深拷贝。
结论:如果想要深拷贝一个对象,这个对象必须要实现Cloneable接口,实现clone方法,并且在clone方法内部,把该对象成员变量中引用的其他对象也要clone一份,这就要求这个被成员对象引用的对象必须也要实现Cloneable接口并且重写clone方法。
4.toString()方法
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
一般子类重写这个方法以便打印自己想到的内容。
5.getClass()方法
public final native Class<?> getClass();
返回此Object运行时类类型,final修饰不可重写,一般和getName()联合使用,如getName().getClass().
6.finalize()方法
protected void finalize() throws Throwable {}
该方法用于释放资源。因为无法确定该方法什么时候被调用,很少使用。
关于垃圾回收,有三点需要记住:
a.对象可能不被垃圾回收,只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。
b.垃圾回收并不等于“析构”。
c.垃圾回收只与内存有关,使用垃圾回收的唯一原因是为了回收程序不再使用的内存。
7.equals()方法
public boolean equals(Object obj) {
return (this == obj);
}
直接判断的是引用,若想判断内容是否相同,需要重写此方法。
8.hashCode()方法
public native int hashCode();
返回该对象的哈希值,该方法用于哈希查找.
9.wait()方法
public final native void wait() throws InterruptedException;
public final native void wait(long timeout) throws InterruptedException; //超时时间timeout ms
wait()方法一直等待,直到获得锁或者被中断。wait(timeout)如果在规定时间内没有获得锁就返回。
调用该方法后当前线程进入睡眠状态,直到以下事件发生。
a.其他线程调用了该对象的notify方法。
b.其他线程调用了该对象的notifyAll方法。
c.其他线程调用了interrupt中断该线程。
d.时间间隔到了。
注意:只有获取锁后wait()方法才起作用,没有获取锁调用wiat()方法无效。调用wait()方法后会释放线程锁,等待结束后重新获取锁继续执行。
class A {
public synchronized void printThreadInfo() throws InterruptedException
{
int i = 0;
while (i++ < 5) {
this.wait(1000);
System.out.println("Still need wait resourse");
}
}
}
public class Test {
public static void main(String args[]) {
A a = new A();
try {
a.printThreadInfo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class WaitNotifyTest {
public static void main(String[] args) {
final Object lock = new Object(); //局部变量lock在内部类中访问了,需要加上final修饰
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程A等待获取lock锁");
synchronized (lock) {
try {
System.out.println("线程A获取了lock锁");
Thread.sleep(1000);
System.out.println("线程A将要运行lock.wait()方法进行等待");
lock.wait();
System.out.println("线程A等待结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程B等待获取lock锁");
synchronized (lock) {
System.out.println("线程B获取了lock锁");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程B将要运行lock.notify()方法进行通知");
lock.notify();
}
}
}).start();
}
}
JVM的一些函数使用了JNI
static JNINativeMethod methods[] = {
{"hashCode", "()I", (void *)&JVM_IHashCode},
{"wait", "(J)V", (void *)&JVM_MonitorWait},
{"notify", "()V", (void *)&JVM_MonitorNotify},
{"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
{"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
};
参考:https://blog.csdn.net/qq_38293564/article/details/80432875
10.notify()方法
public final native void notify();
该方法唤醒在该对象上等待的某个线程。
11.notifyAll()方法
public final native void notifyAll();
该方法唤醒在该对象上等待的所有线程。
java中的Object类和其clone()的更多相关文章
- Java学习笔记二十四:Java中的Object类
Java中的Object类 一:什么是Object类: Object类是所有类的父类,相当于所有类的老祖宗,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object ...
- Java基础(43):Java中的Object类与其方法(转)
Object类 java.lang.Object java.lang包在使用的时候无需显示导入,编译时由编译器自动导入. Object类是类层次结构的根,Java中所有的类从根本上都继承自这个类. O ...
- java中的object类
在Java中,任何一个类都扩展来自Object类.当没有为某一个类定义父类时,Java会自动定义Object类为其父类. object类的一些常用方法: (1)public String toStri ...
- Java中的Object类的几个方法
Object类被称为上帝类,也被称为祖宗类.在定义Java类时,如果没有指定父类,那么默认都会去继承Object类.配合Java的向上类型转换,借助Object类就可以完成很多工作了. 在Object ...
- Java中的Object类介绍
Object类是所有类的父类,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object类. Object类中的所有方法适用于所有子类 Object中比较常见的方法: ...
- Java中的Object类的toString()方法,equals()方法
Object类是所有类的父类,若没有明确使用extends关键字明确表示该类继承哪个类,那么它就默认继承Object类,也就可以使用Object中的方法: 1.toString 如果输出一个对象的时候 ...
- Java中特殊的类——Object类
Java中特殊的类--Object类 1.Object类的概述 Object类是java默认提供的类.Java中除了Object类,所有的类都是有继承关系的.默认会继承Object类,即所有的对象都可 ...
- Java常见对象Object类中的个别方法
Java常见对象Object类 public int hashCode() : 返回该对象的哈希码值. 注意:哈希值是根据哈希算法计算出来的一个值,这个值和地址值有关,但是不是实际地址值.你可以理解成 ...
- Java中的Collections类
转载:https://blog.csdn.net/yangxingpa/article/details/80515963 从[Java]Java中的Collections类——Java中升级版的数据结 ...
随机推荐
- 《Python》并发编程
手工操作 —— 穿孔卡片 1946年第一台计算机诞生--20世纪50年代中期,计算机工作还在采用手工操作方式.此时还没有操作系统的概念. 程序员将对应于程序和数据的已穿孔的纸带(或卡片)装入输 ...
- Linux U盘安装
Ubuntu 15 U盘安装: 用UltraISO把iso文件写入到U盘中,选择hdd+模式. u盘启动后提示not a com32r image,先按tab键,然后输入live进入试用模式,然后再点 ...
- centos7安装配置zabbix4.0
zabbix01 198.8.8.211 zabbix-server4.0 zabbix02 198.8.8.212 zabbix-agent4.0 一:zabbix服务端环境 ...
- fortran学习网站
https://www.sciencesoft.cn/Fortran/Index.htm http://m.fcode.cn/
- 5.Python爬虫入门五之URLError异常处理
大家好,本节在这里主要说的是URLError还有HTTPError,以及对它们的一些处理. 1.URLError 首先解释下URLError可能产生的原因: 网络无连接,即本机无法上网 连接不到特定的 ...
- pytest的执行规则和顺序
用例运行级别 模块级(setup_module/teardown_module)开始于模块始末,全局的 函数级(setup_function/teardown_function)只对函数用例生效(不在 ...
- os与操作系统进行交互,sys解释器相关,random随机数,shutil解压和压缩
1.os 与操作系统相关 对文件的处理 对路径的处理 import os#主要用于与操作系统进行交互 掌握: print(os.makedirs('a/b/c'))#创建目录 可用递归创建 print ...
- Day16作业及默写
hashlib模块,写函数校验两个文件是否内容相同(如果这两个文件很大) import hashlib md5 = hashlib.md5() md5.update(b'hello') md5.upd ...
- jQuery中extend()实现原理
jQuery.extend使用的几种方式 1.jQuery.extend(源对象) jQuery源代码: if(length == i){ target = this; --i; } 示例1: var ...
- 【Python】多进程1
1. 进程定义: (1) 进程是一个实体.每个进程都有他自己的地址空间,一般包括文本区域.数据区域和堆栈.进程是线程的容器. (2) 进程是一个“执行中的程序” 2. 进程的特征: (1) ...