在 Java 中 Object
类是全部类的祖先类,Object
没有定义属性,一共有13个方法。其它全部的子类都会继承这些方法。java
private static native void registerNatives();
static {
registerNatives();
}
复制代码
在 Java 中,用 native 关键字修饰的函数代表该方法的实现并非在Java中去完成,而是由C/C++去完成,并被编译成了.dll,由Java去调用ios
而 registerNatives()
方法的主要做用则是将C/C++中的方法映射到 Java 中的 native
方法,实现方法命名的解耦。多线程
@HotSpotIntrinsicCandidate
public Object() {}
复制代码
@HotSpotIntrinsicCandidate注解,该注解是特定于Java虚拟机的注解。经过该注解表示的方法可能( 但不保证 )经过HotSpot VM本身来写汇编或IR编译器来实现该方法以提供性能。 它表示注释的方法可能(但不能保证)由HotSpot虚拟机内在化。若是HotSpot VM用手写汇编和/或手写编译器IR(编译器自己)替换注释的方法以提升性能,则方法是内在的。 也就是说虽然外面看到的在JDK9中weakCompareAndSet和compareAndSet底层依旧是调用了同样的代码,可是不排除HotSpot VM会手动来实现weakCompareAndSet真正含义的功能的可能性函数
通常建立对象的时候直接使用 new className(Args)
来建立一个新的对象。而在类的定义过程当中,对于未定义构造函数的类,那么它就会默认继承Object
的无参构造函数,若是定了一个或多个构造函数,那么就须要把无参构造函数方法也写上。性能
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
复制代码
getClass
返回运行时当前对象的类对象。在 Java 中,类是对具备一组相同特征或行为的实例的抽象进行描述。而类对象则是对类的特征和行为进行描述(即类的名称,属性,方法...)。也就是说经过获取到类对象,则能够获取到该类的全部属性,方法等。this
@HotSpotIntrinsicCandidate
public native int hashCode();
复制代码
hashCode
返回当前对象的哈希码。hashCode
遵照如下三个约定spa
hashCode
,那么它们的返回值须要是一致的。(前提:没有对对象进行修改)equals()
方法),那么这两个对象的 hashCode
也是同样hashCode
方法返回的哈希码相等,这两个对象不必定相等也便是说,调用equals
方法返回值相等,那么调用hashCode
方法返回值也必定相等。因此,在重写euqlas
方法以后,必定要重写hashCode
方法。.net
那么判断对象是否先等能够直接用equals
来判断,为何还须要hashCode
方法呢?线程
其实hashCode
方法的一个主要做用是为了加强哈希表的性能。好比:咱们知道Set
集合不能存在相同的两个对象,那么该怎么判断两个对象是否相同呢?若是没有hashCode
,那么就须要进行遍从来逐一判断。那么有hashCode
,咱们就能够计算出即将要加入集合的对象的hashCode
,而后查看集合中对应的位置上是否有对象便可。code
public boolean equals(Object obj) {
return (this == obj);
}
复制代码
equals()
用于判断两个对象是否相等。根据 Object
的实现,能够看到判断的依据是看两个对象的引用地址是否相等。
而通常咱们会用另一种方式来判断是否相等。即==
,==
表示的是两个变量值是否相等(基础类型的值在内存地址中存储的是值)
那么咱们想要判断是否相等:
==
来判断equals
方法来判断(在实际业务中,通常会重写equals
方法)须要注意的一点是String
也是引用类型,咱们判断String
的时候是直接使用的equals
方法,而按照默认的equals
实现,建立两个具备相同值的String
对象,那么equals
返回的应该是false
,
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
复制代码
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
复制代码
toString()
返回该对象的字符串表示。在使用 System.out.printLn(obj)
的时候,其内部也是调用的toString
方法。能够按需重写toString
方法。
protected native Object clone() throws CloneNotSupportedException;
复制代码
clone()
方法返回的是当前对象的引用,指向的是新clone
出来的对象,此对象和原对象占用不一样的堆空间。
clone
方法的正确调用须要实现 cloneable
接口,若是没有实现该接口,那么子类调用父类的 clone
方法则会抛出CloneNotSupportedException
异常
Cloneable接口仅仅是一个表示接口,接口自己不包含任何方法,用来指示Object.clone()能够合法的被子类引用所调用。
先看一段代码
public class CloneTest {
public static void main(String[] args) {
Object o1 = new Object();
try {
Object clone = o1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
复制代码
执行这段段代码会抛出The method clone() from the type Object is not visible
异常。缘由是clone
方法是被 protected
修饰的,也就是说被protected
修饰的属性和方法,在同一包下或在不一样包下的子类能够访问。显然,CloneTest
和Object
不在同一包下,不过按照字面意思,CloneTest
会默认继承Object
,因此即便在不一样的包下,应该也是能够访问的才对。那么问题就出如今「在不一样包下的子类能够访问」这句话上:
不一样包中的子类能够访问: 是指当两个类不在同一个包中的时候,继承自父类的子类内部且主调(调用者)为子类的引用时才能访问父类用protected修饰的成员(属性/方法)。 在子类内部,主调为父类的引用时并不能访问此protected修饰的成员。(super关键字除外)
也就是说在子类中想要调用父类的protected
方法,能够
super.methodName()
来调用父类方法浅拷贝: 浅拷贝是按位拷贝对象,它会建立一个新对象,这个对象有着原始对象属性值的一份精确拷贝。若是属性是基本类型,拷贝的就是基本类型的值;若是属性是引用类型,拷贝的就是内存地址。 深拷贝: 深拷贝会拷贝全部的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一块儿拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢而且花销较大。
对于浅拷贝来讲,若是含有引用类型,那么修改其中一个对象的引用值,那么会影响到另一个对象。按层级来讲,浅拷贝只拷贝了第一层。对于默认的clone
实现是浅拷贝。若是想要实现深拷贝,能够
clone
方法//序列化实现深拷贝
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj){
T cloneObj = null;
try {
//写入字节流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
//分配内存,写入原始对象,生成新对象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
//返回生成的新对象
cloneObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
public class Person implements Serializable{
private static final long serialVersionUID = 2631590509760908280L;
}
public class CloneTest {
public static void main(String[] args) {
Person person = new Person();
Person person1 = CloneUtils.clone(person);
}
}
参考:https://blog.csdn.net/chenssy/article/details/12952063
复制代码
protected void finalize() throws Throwable {}
复制代码
finalize()
方法主要与 Java 垃圾回收机制有关,JVM准备对此对形象所占用的内存空间进行垃圾回收前,将被调用。因此此方法并非由咱们主动去调用的。
可先看java 多线程尝鲜。后续会专门讲多线程相关源码。