@TryLoveCatch
2022-04-14T16:47:18.000000Z
字数 5998
阅读 561
Java知识体系
public final native Class<?> getClass();
这是一个 final 类型的native方法,也就是说这个方法不能被子类重写,同时它的实现并不是通过Java语言实现的,而是用其他语言(C/C++)实现的,一般主要用在反射里面。
由于设计到JNI,所以这个方法是有一定耗时的是,使用的时候需要注意,还就是,toString()就使用了该方法。
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
返回一个 String 对象,一般子类都有覆盖。默认返回格式如下:对象的 class 名称 + @ + hashCode 的十六进制字符串。
调用到的方法:
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
考虑一下HashMap,其实就是先判断hashCode再判断equals。
除了遵循这三原则之外,还要遵循:
关于相应的哈希算法,一个简单的算法如下:
组合公式:result = 31 * result + c
比如,String 类的 hashCode 方法如下(JDK 1.8):
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;
}
class Baz {
private int id;
private String name;
private double weight;
private float height;
private String note;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Baz baz = (Baz) o;
if (id != baz.id) return false;
if (Double.compare(baz.weight, weight) != 0) return false;
if (Float.compare(baz.height, height) != 0) return false;
if (name != null ? !name.equals(baz.name) : baz.name != null) return false;
return !(note != null ? !note.equals(baz.note) : baz.note != null);
}
@Override
public int hashCode() {
int result;
long temp;
result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
temp = Double.doubleToLongBits(weight);
result = 31 * result + (int) (temp ^ (temp >>> 32));
result = 31 * result + (height != +0.0f ? Float.floatToIntBits(height) : 0);
result = 31 * result + (note != null ? note.hashCode() : 0);
return result;
}
}
protected native Object clone() throws CloneNotSupportedException;
目的是想要两个相同的对象,重新new一个还得自己重新赋值,太麻烦
举个例子,一个男孩拥有一台电脑
- 需要拷贝的对象(Student)实现Cloneable接口
- 重写clone()方法
- 访问修饰符修改为public
- 通过super.clone()调用Object类中的原clone方法。
public class Student implements Cloneable {
private String name;
private Bag bag;
public Student(String name,Bag bag) {
this.name = name;
this.bag = bag;
}
@Override
public Student clone(){
Student stu = null;
try{
stu = (Student)super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return stu;
}
}
//背包类
public class Bag {
private String name;
public void setName(String name) {
this.name = name;
}
}
- 需要拷贝的对象(Student)以及其所有的对象成员变量(Bag)实现Cloneable接口
- 重写clone()方法
- 访问修饰符修改为public
- 通过super.clone()调用Object类中的原clone方法。
- 对于成员变量,都调用其重写的clone()方法
public class Student implements Cloneable {
private String name;
private Bag bag;
public Student(String name,Bag bag) {
this.name = name;
this.bag = bag;
}
// 这里不一样!!!!!
@Override
public Student clone(){
Student stu = null;
try{
//浅克隆
stu = (Student)super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
//深克隆
stu.bag = (Bag)bag.clone();
return stu;
}
}
//背包类
public class Bag {
private String name;
public Bag(String name) {
this.name = name;
}
// 这里不一样!!!!!
@Override
public Bag clone(){
Bag bag= null;
try{
bag= (Bag )super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
}
return bag;
}
}
- 需要拷贝的对象(Student)实现Serializable接口
- 在需要拷贝的对象(Student)里面增加新方法,例如myClone()
- 通过ObjectOutputStream和ObjectInputStream序列化和反序列化获取到新的对象
// 这里不一样!!!!!
public class Student implements Serializable {
private String name;
private Bag bag;
public Student(String name,Bag bag) {
this.name = name;
this.bag = bag;
}
// 这里不一样!!!!!
public Student myClone(){
Student stu = null;
try {
//将对象序列化到流里
ByteArrayOutputStream os = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject(this);
//将流反序列化成对象
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
ObjectInputStream ois = new ObjectInputStream(is);
stu = (Student) ois.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return stu;
}
}
// 这里不一样!!!!!
public class Bag implements Serializable {
private String name;
public Bag(String name) {
this.name = name;
}
}
如果某个属性被transient修饰,那么该属性就无法被拷贝了。
protected void finalize() throws Throwable { }
finalize()方法是保护方法,主要用于在 GC 的时候再次被调用,如果我们实现了这个方法,对象可能在这个方法中再次复活,从而避免被 GC 回收。
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait() throws InterruptedException {
wait(0);
}
都是final方法,不能被子类重写。
https://www.sczyh30.com/posts/Java/java-hashcode-equal/
https://zhuanlan.zhihu.com/p/41880899