package java.lang;
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
// 类加载器
//返回Object 的运行时类
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}
为什么不用继承Object对象,就可以拥有Object的方法,虚拟机做了什么
JVM在编译源代码时,在遇到没有继承Object的对象的时候,编译器会默认指定一个默认的父类Object
Object 和接口的关系,接口是否继承Object
接口没有继承顶级父类,会隐式的声明一套和Object中的方法签名完全一样的方法,这也就符合万物皆对象的面向对象思想,任何对象直接或间接的跟Object对象有关
1. getClass()方法,返回的是运行时类Class,也就是当前运行类的字节码对象,可以获取到构造器、属性、方法
Java中获取Class对象的方式:
a.通过类名的方式 ClassName.class 编译期,不能执行到静态信息和动态信息
b.通过Class的方法中,使用类的全路径方式 Class.forName("类路径名"); 运行时期,可以执行到静态信息,不能获取到动态信息
c.通过运行实例类过去 Object.getClass(); 运行时期,可以到所有的信息
它们获取到的Class字节码对象的区别?
Classd对象和实例对象的关系?(https://blog.csdn.net/javazejian/article/details/70768369?utm_source=gold_browser_extension)
过去到Class,跟反射相关。
2.重写equals()方法,为什么也需要重写hashcode()方法
对象判断相当obj==obj1;
equals(Object obj){
this==obj;
}
如果重写了equals方法,没有重写hashCode()方法;
会出现equals()相等为true; 而obj==obj1是对象判断,取出的是对象散列值,所以为false。所以显然没有达到想要的效果,需要得到这个对象也相等
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
Map.Entry e = (Map.Entry)o;
Object k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return false;
}
public final int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
}
3. hashcode()算法 javaHashCode算法是通过存储地址值和对象信息算出来的
String,Long,Double,HashMap等对象都重写了hashCode()方法和equals()方法,为了比较的对象和数值有关
Integer 返回原来的value值
Hash冲突的解决方案:
1.链表的方式:
2.再哈希方法:当发现冲突的时候,再次计算hash值来得到
3.开放地址:线性探测再散列,二次探测再散列,伪随机探测再散列
4.建立公共溢出区
Long、Double重写HashCode算法
public int hashCode() {
return (int)(value ^ (value >>> 32));
}
Long,Double重写hashCode() 做右移32位的原因?
为了避免高32位相同、低32位不同hashCode()生成的key一样,推荐的做法是将高32位和低32位做异或运算,
id >>> 32 无符号右移32位,高32位变成低32位,再与原有的id进行异或运算,再强转int取低32位
String重写hashCode算法
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
1.31是一个不大不小的奇素数,不至于乘以其他数时溢出,或太小以至于Hash表太小,分散不开
2.31会被JVM优化,31*i=(i<<5)-i;
String重写hashCode算法的说明—— https://cloud.tencent.com/developer/article/1113699
4.Java 克隆方法——原型设计模式,深克隆和浅克隆的区别
浅克隆是引用的克隆,对象引用指向同一个对象
深克隆是克隆创建对象,对象地址不同
实现深度克隆的方式,实现Cloneable接口,重写clone()方法
new创建对象时,首先查看new操作符后面的类型,知道了对象类型,才知道分配多大的内存空间。分配内存之后,再调用构造器函数,填充对象的个域,然后将他的引用(地址)发布到外部,通过引用操作对象
clone方法跟new方法相似
5.wait()方法,每个对象都有monitor(即锁)
如果调用对象wait()方法,当前线程必须拥有对象的monitor(即锁),调用wait()必须在同步代码块中或同步方法里面(synchorinized),否则会抛出java.lang.IllegalMonitorStateException异常
调用wait()方法时,相当于交出当前对象的monitor来释放锁,让线程处于等待状态,通过对象的notify()和notifyAll()方法来实现线程同步唤醒。这一点也是跟Thread.sleep()方法的区别,sleep()不释放锁
6. finalize() 方法