Object类是java中所有类父类
java.lang.Object

native关键字
被它修饰的方法,叫做本地方法
都是没有实现体。
JVM在底层使用C/C++实现。
1. public final native Class> getClass(); // 获取类的字节码文件

2. public native int hashCode(); // 获取对象的hashcode(获取对象的内存地址的hashcode值)
对象都是有内存地址的。如int a = 10,是把10存在一个内存地址。在java中,为了方便,把内存地址做了哈希算法,最终获取一个hashcode值,这个值也是native的,是底层实现的

3. public boolean equals(Object obj) // 比较对象,默认使用== ,比较的是内存地址
字符串重写了该方法,因为字符串一般比较的是内容,而不是地址

4. public String toString() // 以字符串的形式展示对象信息,打印对象时调用
返回的是 对象的类名称 + @ + 十六进制数字(内存地址的16进制值)

getClass() 拿到字节码文件。getName()获取类的名称
getClass().getName() 获取类的名称。注意:是获取全路径,包名+类名
Integer.toHexString() 将int值转换成十六进制的字符串
hashCode() 获取内存地址的hashcode值
5. public final native void notify() //唤醒当前沉睡的线程
6. public final native void notifyAll() //唤醒当前所有沉睡的线程
7. public final void wait() // 让当前线程进行等待。存在三个重载
8. protected void finalize() // 该方法在GC(垃圾回收机制)触发前,会自动触发
// 在当前对象被GC前,会自动触发
// 适合于做一些垃圾回收前的各种工作、挽救工作
先重写该方法
@Override
protected void finalize() throws Throwable {
System.out.println("我觉得还可以挽救");
}
再进行测试
- package com.openlab.day15;
-
- import org.junit.jupiter.api.Test;
-
- public class TestObject {
-
- @Test
- void testFinalize() {
- User u = new User();
- u = null;
- //把u置空,对于gc而言,内存不一定已经变为空了
- //java的垃圾回收机制是自动在维护的,不是程序员维护。c立刻回收,java不是
- //标记为空相当于告诉垃圾回收机制,这个是垃圾,垃圾回收机制会过来回收,但是
- //过来回收的时间不确定,有时候会立刻过来回收,有时候会等一会过来回收
- System.gc();//手动调用gc,让立即回收
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
面试题,这三种的区别和联系:
final
finally
finalize() 在jdk9之后过时了
final和finally是java的关键字,finalize()是Object类提供一个方法
final关键字修饰变量、方法、类,...
finally是用在try语法块中的,写在finally中的代码是必须要执行的
9. protected native Object clone() throws CloneNotSupportedException //对象拷贝

引用传递:将栈引用进行复制,堆中的对象始终是一个
对象拷贝:堆对象会进行复制。借助clone方法
在java中,如果需要拷贝对象,一定要去该类实现Cloneable接口
1.引用传递
- package com.openlab.day15;
-
- public class User {
- private Integer id;
- private String username;
- private String password;
- private String nickname;
- private Integer age;
-
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public String getNickname() {
- return nickname;
- }
-
- public void setNickname(String nickname) {
- this.nickname = nickname;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-
- public User() {
- super();
- }
-
- public User(Integer id, String username, String password, String nickname, Integer age) {
- super();
- this.id = id;
- this.username = username;
- this.password = password;
- this.nickname = nickname;
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "User [id=" + id + ", username=" + username + ", password=" + password + ", nickname=" + nickname
- + ", age=" + age + "]";
- }
-
- }
- package com.openlab.day15;
-
- import org.junit.jupiter.api.Test;
-
- public class TestObject {
-
- @Test
- void testObjectClone() {
- //创建一个对象
- User u1 = new User(1, "张三", "123456", "法外狂徒", 20);
- System.out.println(u1);
- //引用传递
- User u2 = u1;//u1存的是内存地址,把u1给u2就是把内存地址给u2
- System.out.println(u1 == u2);
- }
-
- }


如果将u1置为空
u1 = null;
System.out.println(u2);
u2还在,虽然一条线没有了,但是另一条还在。

要是u1和u2都置空,内存就会被回收(在栈中已经没有引用指向堆了)。当没有人引用的时候,这块内存就会被认为是垃圾。java的GC是自动的,有自己的垃圾回收机制,根据特定的算法去回收。
2. 对象拷贝
可以重写clone(),也可以直接调用,习惯于重写该方法
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
在java中,如果需要拷贝对象(clone()),一定要去实现Cloneable接口,如果不实现,默认不能克隆。
public class User implements Cloneable{
}
- package com.openlab.day15;
-
- //在java中,如果需要拷贝对象,一定要去实现Cloneable接口
- public class User implements Cloneable{
- private Integer id;
- private String username;
- private String password;
- private String nickname;
- private Integer age;
-
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getUsername() {
- return username;
- }
-
- public void setUsername(String username) {
- this.username = username;
- }
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- public String getNickname() {
- return nickname;
- }
-
- public void setNickname(String nickname) {
- this.nickname = nickname;
- }
-
- public Integer getAge() {
- return age;
- }
-
- public void setAge(Integer age) {
- this.age = age;
- }
-
- public User() {
- super();
- }
-
- public User(Integer id, String username, String password, String nickname, Integer age) {
- super();
- this.id = id;
- this.username = username;
- this.password = password;
- this.nickname = nickname;
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "User [id=" + id + ", username=" + username + ", password=" + password + ", nickname=" + nickname
- + ", age=" + age + "]";
- }
-
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- }
- package com.openlab.day15;
-
- import org.junit.jupiter.api.Test;
-
- public class TestObject {
-
- @Test
- void testObjectClone() {
- //创建一个对象
- User u1 = new User(1, "张三", "123456", "法外狂徒", 20);
- System.out.println(u1);
-
- User u2 = u1;
- System.out.println(u1 == u2);
-
- //u1 = null;
- //System.out.println(u2);
-
- try {
- User u3 = (User) u1.clone();//要做强转(u1.clone()是Object)
- System.out.println(u1 == u3);
- System.out.println(u2 == u3);
- System.out.println(u3);
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- }
-
- }

我们新克隆一个u3,发现u3和u1、u2都不想等,但是它们的值相等。这个拷贝相当于是把u1复制了一份对象放在堆内存,之后赋给u3的引用,叫对象拷贝。这种拷贝叫浅拷贝。
以下介绍浅拷贝。
我们再创建一个猫类,将猫的一个对象交给主人u1。执行这行代码,发现结果为true
System.out.println(u1.getCat() == u3.getCat());
- package com.openlab.day15;
-
- public class Cat {
- private int id;
- private String name;
-
- public int getId() {
- return id;
- }
-
- public void setId(int id) {
- this.id = id;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public Cat() {
- super();
- }
-
- public Cat(int id, String name) {
- super();
- this.id = id;
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "Cat [id=" + id + ", name=" + name + "]";
- }
-
- }
- package com.openlab.day15;
-
- import org.junit.jupiter.api.Test;
-
- public class TestObject {
-
- @Test
- void testObjectClone() {
- //创建一个对象
- User u1 = new User(1, "张三", "123456", "法外狂徒", 20);
- Cat cat = new Cat(2022, "小贝");
- //将小贝交给了主人
- u1.setCat(cat);
-
- System.out.println(u1);
-
- User u2 = u1;
- System.out.println(u1 == u2);
-
- //u1 = null;
- //System.out.println(u2);
-
- try {
- User u3 = (User) u1.clone();//要做强转(u1.clone()是Object)
- System.out.println(u1 == u3);
- System.out.println(u2 == u3);
- System.out.println(u3);
- System.out.println(u1.getCat() == u3.getCat());
- } catch (CloneNotSupportedException e) {
- e.printStackTrace();
- }
- }
-
- }

红色的表示猫对象,u1存了猫的地址,复制时把红色的地址复制了过来 ,所以u3的猫地址和u1相同。
对象的深浅拷贝:
1. 浅拷贝:将对象的第一层完成拷贝,使得两个对象完成了基本的分离
有可能还存在着藕断丝连,因为有可能有多层对象,多层对象不会做深层次的拷贝
优点:内存占有较少
缺点:如果存在底对象,则子对象没有拷贝,还是指向同一个。
2. 深拷贝:
将两个对象完成分离,彼此之间将无任何关系。
递归拷贝
java实现深拷贝有两种方法:
1)、所有相关对象都实现浅拷贝。有几个实现几个,该方法用的不多
2)、通过序列化对象实现深拷贝
对象 <==> 字节数据
对象 <==> 字符串数据(如JSON)
1)、所有相关对象都实现浅拷贝
案例中猫实现Cloneable接口,重写clone()方法,最后再添加
//需要手动添加
u3.setCat((Cat)(u1.getCat().clone()));

![]()
