所有类的父类,可以说是超级父类,他有的方法所有类都有:
protected Object clone();//获得一个对象的副本 默认浅克隆
boolean euqals(Object obj)
int hashcode();//与equals成对出现
String toString();//将对象转换成字符串来输出
protected void finalize();//提示GC回收对象
Class getclass();//获得正在运行的类或接口的class类对象-->反射的基础
//与线程的通信有关
void notify();
void notifyAll();//唤醒其他处于等待的线程
void wait();//当前线程等待
void wait(long timeout);
void wait(long timeout,int nanos);
在java中,如果两个对象的hashcode都相同,可以认为两个对象相等,不同对象的hashcode可能相等
我们来讨论以下三个问题:
如何比较两个对象?为什么要重写equals和hashcode?
我们用equals来比较两个对象是否相等:
BaoLei baoLei=new BaoLei();
BaoLei baoLei1=new BaoLei();
System.out.println(baoLei.equals(baoLei1));
//equals的底层
public boolean equals(Object obj) {
return (this == obj);
}
可以看到object的equals的底层用的是==,因此返回值是FALSE,看看两个对象的hashcode
System.out.println(baoLei1.hashCode());
System.out.println(baoLei.hashCode());
两个对象的hashcode也是不一样的,可能有人会觉得是因为对象的属性不一样,那么我们来创建两个属性完全一样的两个属于同一个类的对象,并且看看他们是否equals对方,并且hashcode是否相等
Student student=new Student(36,"张三");
Student student1=new Student(36,"张三");
System.out.println(student == student1);
System.out.println(student.equals(student1));
System.out.println(student.hashCode());
System.out.println(student1.hashCode());
输出结果两个都不相等,但是如果我们想让他相等,那么在类里面重写equals来让他相等:
public boolean equals(@NonNull Object obj){
if(!(obj instanceof Student))
return false;
Student stu=(Student)obj;
return Objects.equals(this.id,stu.id)&&Objects.equals(this.id,stu.id);
}
此时equals返回值变成TRUE,hashcode还是FALSE,会导致一些错乱,因此我们也要重写hashcode,但我不会写hashcode,我就仿照着string底层来重写一下hashcode:
//string底层重写的hashcode方法
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;//获得每个变量的hashcode放入数组
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];//乘以31加上每个变量的hashcode
}
hash = h;
}
return h;
}
//仿写hashcode
public int hashCode(){
int hash=0;
hash=hash*31+id.hashCode();
hash=hash*31+name.hashCode();
return hash;
}
结果二者都是TRUE,因此重写equals时也要重写hashcode,可以用alt+insert快捷键选择重写,也可以直接增加注解@@EqualsAndHashCode,用@Data来替换有参无参构造,set/get方法,这里面也包含重写hashcode和equals
什么是克隆?object.clone默认是什么克隆?深克隆和浅克隆什么区别?
需要实现coloneable接口不然会出现异常
public class Student implements Cloneable {
private Integer id;
private String name;
private String[] hobby;
public Student(Integer id, String name, String[] hobby) {
System.out.println("all args constructor");
this.id = id;
this.name = name;
this.hobby = hobby;
}
public Student() {
System.out.println("no args constructor");
}
//重写克隆方法,浅克隆
@Override
public Student clone() {
Student student = null;
try {
student = (Student)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student ;
}
}
这是个标识接口,表示该类可以被克隆,不加的话是无法用clone
String[] hobby={"basketball","volleyball"};
Student student=new Student(36,"张三",hobby);
Student clone = student.clone();
System.out.println(student);
//输出all args constructor
// Student(id=36, name=张三, hobby=[basketball, volleyball])
System.out.println(clone);
//输出Student(id=36, name=张三, hobby=[basketball, volleyball])
System.out.println(clone==student);//false
//将原对象属性值修改,再次输出
student.setId(10);
student.setName("李四");
student.getHobby()[0]="play";
System.out.println(student);
//Student(id=10, name=李四, hobby=[play, volleyball])
System.out.println(clone);
//Student(id=36, name=张三, hobby=[play, volleyball])
System.out.println(clone==student);//false
说明克隆对象不执行构造方法而且对于属性修饰符为final的,值不会改变,但是数组的值会随着原来对象值的改变而改变,这就是浅克隆
//深克隆
public Student clone() {
Student student = null;
try {
student = (Student)super.clone();
student.setHobby(hobby.clone());//加上这句给hobby重新赋值,就成为深克隆
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return student ;
}
GC可以回收哪些引用?
判断对象是否有用算法:
-
引用计数法
-
可达性分析法
强引用:
在运行期间,宁愿抛出堆栈内存溢出问题也不会回收这种类型的对象
String[] hobby={"basketball","volleyball"};
Student student=new Student(36,"张三",hobby);//强引用,表示对象必须的,有用的对象
软引用:
有用非必须对象,只有内存不足时候会回收软引用对象,即使将对象变为无用(空),手动调用gc来回收,也会判断内存是否足够才会回收
String[] hobby={"basketball","volleyball"};
Student student = new Student(36,"张三",hobby);
SoftReference<Student> softReference=new SoftReference<>(student);
student=null;
System.gc();
弱引用:
有用非必须,将对象变为无用(空),手动调用gc来回收,计算机就会将它回收
String[] hobby={"basketball","volleyball"};
Student student = new Student(36,"张三",hobby);
WeakReference<Student> weakReference=new WeakReference<>(student);
student=null;
System.gc();
虚引用:
没用的对象,即使不将对象变成无用,程序也会认为它是无用的
String[] hobby={"basketball","volleyball"};
Student student = new Student(36,"张三",hobby);
ReferenceQueue<Student> referenceQueue=new ReferenceQueue<>();
PhantomReference<Student> phantomReference=new PhantomReference<>(student,referenceQueue);
标签:Student,object,System,hashcode,equals,student,hobby
From: https://www.cnblogs.com/Liku-java/p/16845544.html