Object类和Any详解

Object类和Any详解

Any

Any类是kotlin类结构的跟,每个kotlin都继承或间接继承于Any类

/**
 * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass.
 */
public open class Any {
	// kotlin的函数可以没有函数体,其不是Abstract方法,所以子类不必重写。
	public open operator fun equals(other: Any?): Boolean
	public open fun hashCode(): Int
	public open fun toString(): String
}
复制代码

里面有三个open的方法equals、hashCode和toString,其中equals和hashCode如果需要修改就必须同时修改。

Object

同样java中Object也是class结构的根,每个类继承或者间接继承于Object

package java.lang;

public class Object {
	public Object() {
	}

	private static native void registerNatives();

	public final native Class<?> getClass();

	public native int hashCode();

	public boolean equals(Object var1) {
		return this == var1;
	}

	protected native Object clone() throws CloneNotSupportedException;

	public String toString() {
		return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
	}

	public final native void notify();

	public final native void notifyAll();

	public final native void wait(long var1) throws InterruptedException;

	public final void wait(long var1, int var3) throws InterruptedException {
		if (var1 < 0L) {
			throw new IllegalArgumentException("timeout value is negative");
		} else if (var3 >= 0 && var3 <= 999999) {
			if (var3 > 0) {
				++var1;
			}

			this.wait(var1);
		} else {
			throw new IllegalArgumentException("nanosecond timeout value out of range");
		}
	}

	public final void wait() throws InterruptedException {
		this.wait(0L);
	}

	protected void finalize() throws Throwable {
	}

	static {
		registerNatives();
	}
}
复制代码

相比于Kotlin,java中的class方法丰富的多,十二个。其中7个本地方法包含一个静态本地方法,5个可以被子类覆盖的方法

private static native void registerNatives();
static {
    registerNatives();
}
复制代码

静态本地方法在类加载时执行。该方法的作用是通过类加载器加载一些本地方法到JVM中。Object类在被加载时,会加载一些methods中的本地方法到JVM中如下:

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},
};
复制代码
@Contract(pure = true) public final native Class<?> getClass();

返回该对象的类的Class对象。Class对象可以用于反射等场景。

public native int hashCode();

返回对象的哈希值,主要用于HashMap的hash tables。

哈希需要注意的几点:

  • 相等的对象必须要有相同的哈希码

  • 不相等的对象一定有着不同的哈希码——错!

  • 有同一个哈希值的对象一定相等——错!

  • 重写equals时必须重写hashCode

equals
 public boolean equals(Object var1) {
	return this == var1;
}
复制代码

判断引用是否指向同一个地址,就是判断两个引用指向的对象是否是同一个对象, String重写了该方法,判断字符串是否相等。

protected native Object clone() throws CloneNotSupportedException;

该方法用于拷贝。要调用该方法需要类实现Cloneable接口,否则抛出CloneNotSupportedException。

浅拷贝,重写clone方法,调用super.clone():

public class TestOne implements Cloneable {
	@NonNull
	@Override
	protected TestOne clone() {
		TestOne obj = null;
		try {
			obj = (TestOne) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return obj;
	}
}
复制代码

深拷贝

public class TestTwo implements Cloneable {
	public TestOne var;
	@NonNull
	@Override
	protected TestTwo clone() {
		TestTwo obj = null;
		try {
			obj = (TestTwo) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		obj.var = obj.var.clone();
		return obj;
	}
}
复制代码
public String toString()

返回类名和对象的哈希值的十六进制字符串,推荐子类重写该方法。

notify()、notifyAll()、wait()方法

从1.0版开始,Java中的每一个对象都有一个内部锁。如果一个方法用synchronized关键字声明,那么对象的锁将保护整个方法。也就是说,要调用该方法,线程必须获得内部的对象锁。

public synchronize void method(){
	method body
}
等同于
public void method(){
	this.intrinsicLock.lock();
	try{
		method body
	}
	finally{ this.intrinsicLock.unlock();}
}
复制代码

从这个示例我们即可看出上面几个方法的作用。

public final native void notify();

随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态。该方法只能在一个同步方法或同步块中调用。如果当前线程不是对象锁的持有者,该方法抛出一个IllegalMonitorStateException异常。

public final native void notifyAll();

解除那些在该对象上调用wait方法的线程的阻塞状态。该方法只能在同步方法或同步块内部调用。如果当前线程不是对象锁的持有者,该方法抛出一个IllegalMonitorStateException异常。

public final void wait() throws InterruptedException

使线程进入等待状态直到它被通知。该方法只能在一个同步方法中调用。如果当前线程不是对象锁的持有者,该方法抛出一个IllegalMonitorStateException异常。

public final void wait(long millis, int nanos) throws InterruptedException
public final native void wait(long millis) throws InterruptedException;

参数:millis 毫秒数 nanos 纳秒数 < 1000 000
使线程进入等待状态直到它被通知或者经过指定的时间。这些方法只能在一个同步方法中调用。如果当前线程不是对象锁的持有者该方法抛出一个IllegalMonitorStateException异常。

protected void finalize() throws Throwable

当一个堆空间中的对象没有被栈空间变量指向的时候,这个对象会等待被java回收。

GC特点:

  • 当对象不再被程序所使用的时候,垃圾回收器将会将其回收
  • 垃圾回收是在后台运行的,我们无法命令垃圾回收器马上回收资源,但是我们可以告诉他可以尽快回收资源(System.gc()和Runtime.getRuntime().gc())
  • 垃圾回收器在回收某个对象的时候,首先会调用该对象的finalize()方法
  • GC主要针对堆内存
  • 单例模式的缺点

Any和Object相同点

Kotlin中的Any只存在于编译期,运行期就不存在了。

val any = Any()
println("any:$any ")
println("anyClass:${any.javaClass} ")

val obj = any as Object
synchronized(obj){
	obj.wait()
}
println("obj:$obj ")
println("obj:${any.`class`} ")

I/System.out: any:java.lang.Object@d12ebc1 
I/System.out: anyClass:class java.lang.Object 
I/System.out: obj:java.lang.Object@d12ebc1 
I/System.out: obj:class java.lang.Object 
复制代码

从上面的示例可以看出在runtime,Any变成了Object,在kotlin中也可以将Any强转为Object。

从Kolitn的官方文档 kotlinlang.org/docs/java-i… 可以看到Object对应的就是Any

Kotlin专门处理一些Java类型。这些类型不是按原样从Java加载的,而是映射到相应的Kotlin类型。映射只在编译时起作用,运行时表示保持不变。Java的原语类型映射到相应的Kotlin类型(保持平台类型)

从上面的示例可以看出obj可以any混用,any强转后不仅可以使用notify()等方法,还可以使用Any的扩展方法,如使用 obj.apply { }

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享