最近面试有家公司让我回答Object都有哪些方法,平时很少关注,回家补了下脑,它有如下方法:
Object,clone,,equals(Object o),finalize,getClass,hashCode,notify,notifyAll,wait, wait(long millis),wait(long millis, int nanos),toString
接下来我就以上加粗的几个方法根据源码注释做一个解释:
- clone
该方法被protected修饰,为了对象能够被克隆,类必须实现Cloneable接口,这里涉及到 Shadow 和 Deep 克隆,Deep 克隆时针对非immutable且引用型 的 member,在克隆时须调用该成员的clone,如下:
Deep Clone:
public final class ImmutableNestedClass {
private final String padding;
public ImmutableNestedClass(String padding) {
this.padding = padding;
}
public final String getPadding() {
return padding;
}
}
public class NestedClass implements Cloneable{
private String padding;
public NestedClass(String padding) {
this.padding = padding;
}
public void setPadding(String padding) {
this.padding = padding;
}
@Override
public NestedClass clone() {
NestedClass cloned = null;
try {
cloned = (NestedClass) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return cloned;
}
}
public class SuperClass {
String name; // Though name is reference type member, but it is immutable.
int age;
NestedClass nestedClass = new NestedClass("padding");
public SuperClass(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return new StringBuilder().append(name).append(",").append(age).toString();
}
}
public class SubClass extends SuperClass implements Cloneable {
private String sex; // Though name is reference type member, but it is immutable.
private NestedClass nestedInstance;
private ImmutableNestedClass immutableNestedInstance;
public SubClass(String sex, String name, int age) {
super(name, age);
this.sex = sex;
this.nestedInstance = new NestedClass("padding");
this.immutableNestedInstance = new ImmutableNestedClass("padding");
}
@Override
protected SubClass clone() {
SubClass cloned = null;
try {
cloned = (SubClass)super.clone();
cloned.nestedInstance = nestedInstance.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return cloned;
}
public NestedClass getNestedInstance() {
return nestedInstance;
}
public ImmutableNestedClass getImmutableNestedInstance() {
return immutableNestedInstance;
}
public String getSex() {
return sex;
}
@Override
public String toString() {
return new StringBuilder().append(sex).append(",").append(nestedInstance).append(",").append(super.toString()).toString();
}
}
Shadow Clone: 其他不变,只改SubClass
public class SubClass extends SuperClass implements Cloneable {
private String sex; // Though name is reference type member, but it is immutable.
private NestedClass nestedInstance;
private ImmutableNestedClass immutableNestedInstance;
public SubClass(String sex, String name, int age) {
super(name, age);
this.sex = sex;
this.nestedInstance = new NestedClass("padding");
this.immutableNestedInstance = new ImmutableNestedClass("padding");
}
@Override
protected SubClass clone() {
SubClass cloned = null;
try {
cloned = (SubClass)super.clone();
// 注释掉以下这行
// cloned.nestedInstance = nestedInstance.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return cloned;
}
public NestedClass getNestedInstance() {
return nestedInstance;
}
public ImmutableNestedClass getImmutableNestedInstance() {
return immutableNestedInstance;
}
public String getSex() {
return sex;
}
@Override
public String toString() {
return new StringBuilder().append(sex).append(",").append(nestedInstance).append(",").append(super.toString()).toString();
}
}
如何验证?用==比较前后实例的非immutable 引用型成员,如果不相等说明深度克隆成功!
待续。。。
- equals && hashCode
package jc.download.impl;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import jc.download.interfac.Key;
import jc.download.util.Util;
public class UrlKey implements Key {
String url;
private String str;
public UrlKey(String url, @Nullable String str) {
if (TextUtils.isEmpty(url)) throw new IllegalArgumentException("url can't be null.");
this.url = url;
this.str = str;
}
@Override
public boolean equals(Object o){
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) { // much more exactly than using instanceof.
return false;
}
UrlKey that = (UrlKey)o;
/**
* If field is primitive compare with '==', else compare with equals method.
*/
if (!url.equals(that.url) || (null == str ? that.str != null : !str.equals(that.str))) {
return false;
}
return true;
}
/** equal instances must have equal hash codes. */
@Override
public int hashCode() {
// Start with a non-zero constant
int result = 17;
result = 31 * result + url.hashCode();
return result;
}
@Override
public String toString(){
if (str == null) {
str = Util.byteArrayToHex(url.getBytes());
}
return str;
}
}
hash code 将作为hash表类数据结构用来计算元素index的重要因子。API说明hashCode最好按照以下规则实现:
Override public int hashCode() {
// Start with a non-zero constant.
int result = 17;
// Include a hash for each field.
result = 31 * result + (booleanField ? 1 : 0);
result = 31 * result + byteField;
result = 31 * result + charField;
result = 31 * result + shortField;
result = 31 * result + intField;
result = 31 * result + (int) (longField ^ (longField >>> 32));
result = 31 * result + Float.floatToIntBits(floatField);
long doubleFieldBits = Double.doubleToLongBits(doubleField);
result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32));
result = 31 * result + Arrays.hashCode(arrayField);
result = 31 * result + referenceField.hashCode();
result = 31 * result +
(nullableReferenceField == null ? 0
: nullableReferenceField.hashCode());
return result;
}
finalize
用途:
1.回收Native分配的内存
2.检测程序员的疏漏
按照以下方式来实现:
@Override
protected void finalize() throws Throwable {
try {
// TODO. release native resources here.
}finally {
super.finalize();
}
}
不提倡实现finalize的原因是,GC在回收某个对象前会调用finalize方法(如果实现的话),finalize耗时太长,会导致内存得不到及时回收。
比较好的分析:
深入理解ReferenceQueue GC finalize Reference
- getClass
用来确认对象是哪个类的实例。
public class SuperClass {
....
}
public class SubClass extends SuperClass {
...
}
SubClass instance = new SubClass();
boolean ret = instance instanceof SubClass; // ret is true
boolean ret = instance instanceof SuperClass; // ret is true
boolean ret = original.getClass() == SubClass.class; // ret is true
boolean ret = original.getClass() == SuperClass.class; // ret is false
- wait&¬ify
boolean set = false;
Object obj = new Object();
//get thread
synchronized (obj) { // synchronized
while (!set) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
set = false;
obj.notify();
}
//set thread
synchronized (obj) {
while (set) {
try {
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
set = true;
obj.notify();
}