一、object概述
1、什么是object
objest是所有类的直接或间接父类,位于继承树的最顶层,我们在新建类的时候,会默认继承该父类而不需要些
关键字
2、object的作用
➢提供了很多有用的方法
➢可以让我们书写方法的时候,返回类型或者参数类型用Object,方便接收任何类型的数据
二、object的有用的方法
1、clone
1.1、介绍
➢能让对象实现复制的功能(注意,这个复制默认是浅层复制
,如果想要进行深层复制,我们需要手动书写里面的方法逻辑);
➢要想实现克隆的功能,就需要让你要实现的对象所在的类去实现CloneAble接口;
➢CloneAble接口里面提供了一个clone的方法,该方法默认已经完成了复制功能;
➢clone方法调用之后,返回的是一个0bject对象, 所以我们需要进行强转为我们需要的类型;
1.2、浅层复制 demo
a、让你要实现复制的类来实现一个Cloneable接口;
b、重写clone方法,里面不需要写任何的代码,默认即可;
c、调用该clone方法;
d、返回的是Object类型,进行强转;
public class CloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(1001,"张三");
Person p2 = (Person)p1.clone();
//复制完成之后,更改p1里面的内容,看是否会影响到p2
p1.pid = 1002;
System.out.println(p1.pid+","+p1.pname);
System.out.println(p2.pid+","+p2.pname);
//查看这两个对象的地址值是否相同
System.out.println(p1==p2);
}
}
class Person implements Cloneable{
int pid;
String pname;
public Person() {
}
public Person(int pid, String pname) {
super();
this.pid = pid;
this.pname = pname;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
1.2、浅层复制图解
1.3、深层复制demo
a、如果要单独进行深层复制的话,那么就证明当前对象里面的属性肯定拥有
基本数据类型和字符串之外的属性(引用类型)存在;
b、对这个自定义数据类型的类来实现Cloneable接口
c、重写里面的clone方法,里面内容不用改,默认即可;
d、在需要进行深层复制的对象的clone方法里面进行手动书写,书写的目的在于
手动调用它里面的自定义属性的clone方法;
public class CloneDemo {
public static void main(String[] args) throws CloneNotSupportedException {
Person p1 = new Person(1001,"张三");
//为当前对象加入一个新的Address属性
Address address = new Address("家庭","湖南长沙");
p1.address = address;
Person p2 = (Person)p1.clone();
//复制完成之后,更改p1里面的内容,看是否会影响到p2
p1.pid = 1002;
p1.address.type = "公司";
System.out.println(p1.pid+","+p1.pname+","+p1.address.type+","+p1.address.location);
System.out.println(p2.pid+","+p2.pname+","+p2.address.type+","+p2.address.location);
//查看这两个对象的地址值是否相同
System.out.println(p1==p2);
//查看address是否是同一个对象,如果为true,就是浅层复制
System.out.println(p1.address==p2.address);
}
}
class Person implements Cloneable{
int pid;
String pname;
//加上自定义数据类型Address
Address address;
public Person() {
}
public Person(int pid, String pname) {
super();
this.pid = pid;
this.pname = pname;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//1、拿到返回的Person对象
Person person = (Person)super.clone();
//2、拿到该对象里面的Address属性
Address address = person.address;
//3、针对该属性来进行一个clone
Address newAddress = (Address)address.clone();
//4、把克隆完成之后的address对象放回你要返回的Person对象内部
person.address = newAddress;
return person;
}
}
class Address implements Cloneable{
String type;//地址的类型,比如家庭还是公司
String location;//地址的具体位置
public Address() {
}
public Address(String type, String location) {
super();
this.type = type;
this.location = location;
}
@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
1.3、深层复制图解
2、equals
2.1、equals介绍
在java中比较对象有两种方式
- 第一种:双等号,比较的是对象的地址值是否相同
- 第二种:equals,用来比较对象里面的内容是否相同
但是object类中的equals方法是模版方法,字类必须重写equals方法
2.2、equals重写的思路
比较两个引用是否指向同-一个对象。
判断obj是否为null。
判断两个引用指向的实际对象类型是否一 致。
强制类型转换。
依次比较各个属性值是否相同。
注意:如果你一个类中拥有另外一个自定义数据类型的属性的话
你要重写equals就必须提前先把那个属性里面的equals也重写了;
2.3、equals 重写代码
public class EqualsDemo {
public static void main(String[] args) {
Book b1 = new Book(1001, "红楼梦");
Book b2 = new Book(1001, "红楼梦");
//使用==和equals分别进行判断
System.out.println(b1 == b2);//false
System.out.println(b1.equals(b2));//true
}
}
class Book {
int bid;
String bname;
public Book() {
}
public Book(int bid, String bname) {
super();
this.bid = bid;
this.bname = bname;
}
public boolean equals(Object obj) {
//1、判断两个对象是否指向的是同一个
if (this == obj) {
return true;
}
//2、判断obj是否为null
if (obj == null) {
return false;
}
//3、判断两个对象是否是同一个类型
if (this.getClass() != obj.getClass()) {
return false;
}
//4、类型转换
Book other = (Book) obj;
//5、进行里面属性的一个个的判断
return this.bid == other.bid && this.bname.equals(other.bname);
}
}
2.4、 自动生成
3、hashcode
3.1、hashcode 介绍
➢Java中的hashcode方法作用就是在我们往堆里面/容器里面放入一个对象之前,先判断这个对象是否存在,虽然我们可以通过equals来进行判断,但是一个个判断效率太过于低下,所以Sun公司就给出规范,内容相同对象的hashcode值一定相同
。这个hashcode值,我们称之为哈希码值,也叫散列值;
(内容可以看作对象中的属性值要一致,并非所有属性都要一致,选取自己需要的)
➢散列值是怎么算出来的
:根据一定的规则将与对象相关的信息(比如对象的存储地址,对象的字段等)映射成一个数值,这个数值称作为哈希码值。
➢默认的hashcode方法的哈希码并不唯一
, 我们需要重写该方法
,来可保证相同对象(内容相同)返回相同哈希码,尽量保证不同对象返回不同哈希码
。
➢我们一般直接调用0bjects.hashcode方法来完成该方法的重写,当然,你也可以书写一个方法,只要该方法可以通过对象里面的属性值来算出一个数值出来,并且能保证不同的对象这个数值不相同;
➢我们为了按照Sun公司的建议,一般来说, equals为true, 那么它们的hashcode值也要一定相等 ,所以我们在重写hashcode方法的时候,请务必把该方法里面所用到的属性和equals方法所用到的属性保持一致
。
3.2、hashcode 重写
a、hashcode默认是0bject类中的方法,这个方法不能保证不同的对象拥有不同的hashcode值;
b、我们书写hashcode方法需要遵循的原则是,hashcode通过哪些具体的属性来算出来要和 equals判断的属性保持一致, 比如说equals方法的return后面用了一个类中的3个属性的2个属性 那么,hashcode方法也只需要使用这两个即可
;
C、我们一般不手动去书写该方法,直接调用0bjects. hash即可;
public class EqualsDemo {
public static void main(String[] args) {
Book b1 = new Book(1001,"红楼梦");
Book b2 = new Book(1001,"红楼梦");
//查看这两个对象的hashcode值
System.out.println(b1.hashCode());
System.out.println(b2.hashCode());
}
}
class Book{
int bid;
String bname;
public Book() {
}
public Book(int bid, String bname) {
super();
this.bid = bid;
this.bname = bname;
}
@Override
public int hashCode() {
return Objects.hash(bid,bname);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (bid != other.bid)
return false;
if (bname == null) {
if (other.bname != null)
return false;
} else if (!bname.equals(other.bname))
return false;
return true;
}
3、tostring
3.1、tostring方法介绍
➢Java中的对象进行输出的话,会默认调用Object类的toString方法,而该方法的底层其实就是输出该对象的全限定名+该对象的的hashcode值
,这个数值对于我们开发者来说其实并没有含义
,而我们更喜欢在输出对象的时候,能输出当前对象的一些属性,让我们更加方便的识别该对象;
➢重写0bject类的toString方法, 就是让我们输出对象的时候,可以按照你想要展示的样式来输出对象
3.2、tostring重写
@Override
public String toString() {
return "Book [bid=" + bid + ", bname=" + bname + "]";
}