JAVA的Object类
java.lang.Object 是一个特殊的类,java中所有的类都继承自该类。
这次主要是为了记录下Object的相关知识。
registerNatives()
registerNatives()方法在源码中没有相关的注释,有兴趣的可以看下相关C的实现。简而言之,为了让JVM找到本地函数,本地函数必须以某种规范运行。
例如,registerNatives函数在本地被命名为Java_java_lang_Object_registerNatives,而使用registerNatives()方法则可指定C函数的名称。registerNatives把本地方法和相关的JAVA方法做了一个映射,将两者关联在一起,而不是通过相关的命名约定去寻找本地函数。
getClass()
返回当前类的类对象。
我们都知道,在正常的使用中,我们有多种方式获取类对象。例如Example.class 、exp.getClass(),这两种方式有什么区别呢?首先来看下这getClass()方法中的注释。
<p><b>The actual result type is {@code Class<? extends |X|>}
* where {@code |X|} is the erasure of the static type of the
* expression on which {@code getClass} is called.</b> For
* example, no cast is required in this code fragment:</p>
注释中写到,该方法返回的是一个继承了父类的类对象。是不需要强制转型的。
举个例子来看:
Class SubClass extends ParentClass{}
Class Parent{}
System.out.println(SubClass.class.getSimpleName)
System.out.println(new SubClass().getSimpleName)
//运行结果分别是Parent、SubClass
可以看到,getClass()获取的是当前类的实例类。而.class则是在编译时确定的,获取的是当前类的父类。
clone ()
复制一个和当前对象一样的类。需要注意的是,该方法是浅拷贝(shadow copy)而不是深拷贝(deep copy),当前类中存在其他的引用类型的变量时,当引用内容发生改变时,两个对象都会发生改变。
equals ()、hashcode()
为什么要将hashCode 和 equals放在一起讲呢。因为很多时候我们需要重写这个方法。
首先看看equas方法,equals方法本身必须满足一些特性,这里不做多说。Object 默认的equals方法是等价于"==" 的。 我们知道"=="比较的是两个对象的内存地址。而实际上,我们往往关注的是对象内的值是否相等,这个时候我们就需要重写equals方法。
下面是源码中的一段注释
* Note that it is generally necessary to override the {@code hashCode}
* method whenever this method is overridden, so as to maintain the
* general contract for the {@code hashCode} method, which states
* that equal objects must have equal hash codes.
从注释上看。重写equals方法则必须重写hashcode方法。因为equals相等时,hashCode必须相等。这里我还想说下hashCode的实现。可以看下String中重写的hashCode方法。
public int hashCode(){
int h = hash;
if(h==0&&value.length>0){
char val[] = value;
for(int i=0;i>vaule.length;i++){
h=31*h+val[i];
}
hash=h;
}
return h;
}
这里我主要想介绍的是这个31,很多hashCode方法的是现实都会出现这个31,这是为什么呢?通过查阅资料,最后总结为以下三点。首先31是个素数,其结果发生hash碰撞的概率比较小。其次31这个数不大不小,太小会容易造成碰撞。太大会增大运算的开销。最后31可以被虚拟机优化成移位运算,优化运算性能。