提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
什么是Object
Object是Java中的顶级父类。所有的类都直接或间接的继承于Object类。
一、Object的构造方法
因为Object是所有类的共性,所以说Object中没有成员变量,既然没有成员变量,那就没有带参的构造方法。
因为在顶级父类中只有无参构造,所以可以解释为什么任何一个类的构造方法中的 super() 方法默认继承父类中的无参构造
二、Object中常用的成员方法
Object中一共有11中方法,其中有三种常见的方法分别为以下三种
1.public String toString() 返回对象的字符串形式
代码如下(示例):
Object obj = new Object();
String str1 = obj.toString();
System.out.println(str1);//运行结果:java.lang.Object@1540e19d
java.lang.Object@1540e19d 表示:@全面表示java.lang(包名)+Object(类名)@1540e19d(对象的地址值)
除了在Object类中是如此,它的子类在没有重写toString()方法的的形况下调用输出的结果解释类似结果
思考:默认情况下,因为Object类中的toString方法返回的是地址值,所以,默认情况下,打印一个对象打印的就是地址值,但是地址值对于我们没有太大的意义,这时我想要看到对象内部的属性值,我们该怎么办呢?
我想你应该知道怎么处理了,那就是重写父类Object中的toString()方法即可,例如:
@Override
public String toString()
return name +" "+ age;
}
重写后,输出的就是对象的属性了
toString方法的总结:如果我们打印一个对象,想要看到属性值的话,那么重写toString方法就可以了,再重写的方法中,把对象的属性值进行拼接
2.public boolen equals(Object obj) 比较两个对象是否相等
在子类中没有重写equals()方法的情况下,对象所调用的是父类Object中equals()方法,而这个方法所比较的是对象的地址值,源代码如下:
Student s1 = new Student();
Student s2 = new Student();
boolean result1 = s1.equals(s2);
System.out.println(result1);//输出结果为 false
同理toString()方法如果你想要比较对象之间的属性值是否相等,那就要重写equals()方法,一般重写为:
@Override
public boolean equals(Object o) {
if (this == o) return true;//判断对象地址值是否相等
if (o == null || getClass() != o.getClass()) return false;//非空判断和类型的判断
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);//调用的是Objects中的equals()方法比较,name(String),age(int)
}
在这里就知道了,我们经常使用字符串比较的String类中的equals()方法是重写了Object中的equals()方法
分享一个面试题:
String s = "abc";
StringBuilder sb = new StringBuilder("abc");
System.out.println(s.equals(sb));//输出结果 false
//因为equals方法是被s调用的,而s是字符串
//所以equals要看String类中的
//字符串中的equals方法,先判断参数是否为字符串
//如果是字符串,在比较内部的属性
//但是如果是参数不是字符串,直接返回false
System.out.println(sb.equals(s));//输出结果为 false
//应为equals方法是被sb调用,而sb是StringBuilder
//所以这里的equals方法要看StringBuilder中的equals方法
//那么在StringBuilders中,没有重写equals方法
//使用的是Object中equals方法
//在Object当中默认是使用 == 号比较两个对象的地址值
3.protected Object clone() 对象克隆
把A对象的属性值完全拷贝给B对象,也叫对象拷贝,对象复制
对于clone方法,对象不能直接调用该方法,因为它是被proteced关键字修饰的,所以只能被本包中的类,还有其他包中的子类可以去使用,而Object类是定义在java.lang包下的,咱们不能在java.lang包下去编代码,所以只能自己去重写该方法
重写细节:1.重写Object中的clone方法 2.让javabean类实现Cloneable接口 3.创建原对象并调用clone就可以了。
重写:
@Override
protected Object clone() throws CloneNotSupportedException {
//调用父类中的clone方法
//相当于让Java帮我们克隆一个对象,并把克隆后的对象返回出去。
return super.clone();
}
实现Cloneable接口
//Cloneable
//如果一个接口里没有抽象方法
//表示当前接口是一个标记性接口
//现在Cloneable表示一旦实现了,那么当前类的对象就可以被克隆
//如果没有实现,当前类的对象就不能克隆
public class User implements Cloneable{
public int id ;
public String username;
public String password;
public String path;
public int[] data;
测试类中实现:
public class Test01 {
public static void main(String[] args) throws CloneNotSupportedException {
int[] data = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0};
// User u1 = new User(1,"zhangsan","123456","gilee",data);
User u1 = new User(1,"zhangsan","1234qwer","girl11",data);
User u2 = (User)u1.clone();
System.out.println(u1);//User{id = 1, username = zhangsan, password = 1234qwer, path = girl11, data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]}
System.out.println(u2);//User{id = 1, username = zhangsan, password = 1234qwer, path = girl11, data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0]}
}
}
clone方法实现的内存原理:
原对象:
对象克隆方式一(浅克隆:Object中的clone()方法):1.对于基本类型直接拷贝过来 2. 字符串服用 3.共享引用类型数据,一个对象对引用类型中的数据进行的操作,会影响到被克隆的对象中引用类型的数据
对象克隆方式二(深克隆,深拷贝):1.对于基本类型直接拷贝过来 2.字符串服用 3.引用数据类型会重新创建新的
代码范例如下(其中的变量都为上面 所提到的)
@Override
protected Object clone() throws CloneNotSupportedException {
//先把被克隆对象中的数组取出来
int[] data = this.data;
//创建新的数组
int[] newData = new int[data.length];
//拷贝到新的数组
for (int i = 0; i < data.length; i++) {
newData[i] = data[i];
}
//调用父类中的方法克隆对象
User u = (User)super.clone();
//因为父类中的克隆方法是浅克隆,替换克隆出来对象中的数组地址值
u.data = newData;
return u;
}
如果你觉的深克隆代码太过繁琐,这一点我也感觉到了,所以就有了关于克隆的第三方库 gson-版本号.jar,你可以去自行下载,下载后复制粘贴到你的项目模块中的lib目录下上就可以使用了。下边是使用的截图(其中user是被深克隆出来的新对象)
这是我的第一篇文章,谢谢大家支持