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 { }
作者:zbt
链接:https://juejin.cn/post/6955413784143855629
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。