(码畜日记,看官多多批评指正)Java面向对象:Object类的常见方法及浅谈clone()方法中的深复制与浅复制

虽然csdn账号注册的久,但是很少进来,也第一次发博客,因为本人比较菜目前还在学习中是一名学生,今天看了一下学习视频有一点小小的体会,权当日记了,若有大佬路过,还望不吝赐教。

1.什么是Object类

在我的理解里面Object类就类似于山顶洞人一样的存在——人类的祖先,把我们不同时期甚至是不同的人都看成是一个个类,而山顶洞人就是我们所有人共同的父类,我们都有他的特征,经过不断地进化及各种因素的影响,成了不同的人,也有了区别于祖先不同的特征(属性与方法)等。

2.常用的几种方法(不全,暂挑相对重要的讲)

Stundent类:(常规操作,可跳过)

class Student {
	private String name;
	private int age;

public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
}

(1) xxx.getclass( )

getclass( )方法是获取该对象所对应类型,是一个本地方法(native,可以查看源码),控制台中输出的是完全限定名,也就是(包路径+类名),也是后面会学的反射获取对象的其中一种方法。示例如下:

public static void main(String[] args) {
		Student stu1 =new Student("小叶",22);
		System.out.println(stu1.getClass());
}

控制台输出如下:

(2)xxx.hashcode( )

hashcode()方法也就是获取改对象的散列码,是根据物理地址的值,通过一系列的运算得到的,这是本地的方法,具体的运算细则,小叶也不太清楚,还望大佬点出。在我们new出一个对象时,就会产生一个hash值,hash值不一样,一定不会为同一对象,但是hash值一样,不一定为同一对象。

后半句怎么解释呢,因为我们自定义一个类还未重写本方法时,其对象在调用此方法时,仍是Object本身的方法。定义的类身为它的子类,是可以在类当中重写hashcode方法的,ecplise快捷键(shift+alt+s)就可以找到。同样的类中,给其不同对象赋予同样的值时,会导致hash值一样,这是因为不会像Object中此方法一样根据物理地址的值,而是会给你一个方法,根据其方法计算出hash值(也可以自己编写,这里只是讲重写),Student中的name属性是String类,String类就已经重写过hashcode()方法,在下面实例中可以看到一点,重写前后对比的代码及输出如下:

重写前代码:

public static void main(String[] args) {
		Student stu1 =new Student("小叶",22);
		Student stu2 =new Student("小叶",22);
		System.out.println(stu1.hashCode());
		System.out.println(stu2.hashCode());
}

输出为:

 重写后的在Student类中的hashcode()方法代码为:

public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

输出为:

(3)xxx.equals( )

equals( )方法是用来判断两个对象是否为同一对象的方法,此方法为java提供的方法,并非本地方法,与hashcode( )方法相似的地方则是都需要在类里通过重写Object类方法来达到equals()方法的特定功能。

在未重写之前和 == 的作用是一样的,是判断两个对象的地址是否相同,而equals()方法应该是判断两个对象的内容是否一样,和hashcode()方法一样,自定义的类若要达到功能需求,需要与其他类一样(如:String类),进行方法的重写,重写前后对比的代码及输出如下:

重写前代码:

public static void main(String[] args) {
		Student stu1 =new Student("小叶",22);
		Student stu2 =new Student("小叶",22);
		System.out.println(stu1.equals(stu2));
        System.out.println(stu1==stu2);
}

输出:

重写后的equals()方法代码:


	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

若有读不懂重写后的方法的小伙伴可以留言喔!这里就不过多注释啦

public static void main(String[] args) {
		Student stu1 =new Student("小叶",22);
		Student stu2 =new Student("小叶",22);
		System.out.println(stu1.equals(stu2));
		System.out.println(stu1==stu2);
}

输出:

 (4)xxx.clone( )

clone也就是克隆的意思,clone( )方法就是做对象的复制的,并非赋值,对象直接赋值想要完成复制功能的是错误的,若改变被赋值的对象中的属性,赋值对象的属性也会随着改变,代码及输出如下:

public static void main(String[] args) {

Student stu3 =new Student("小叶",22);
		//赋值并非复制
		Student stu4 =stu3.clone();
		stu4.setAge(10);
		System.out.println(stu3);
		System.out.println(stu4);
}

输出:

 

 原因:赋值是栈里面的赋值,堆里面只有一个对象数据,当改变对象数据时,栈里面同样地址的对象都会随其改变,因为他们共用这一份数据。

复制又分为深复制与浅复制,让我们浅谈一下两种复制的区别以及复制的内容有哪些

A.浅复制(只能复制基本数据类型,引用类型仍然共用)

因为clone方法本身为protected访问修饰符修饰的方法,只能被自身、同包、及其子类访问,所以不能再Test类中的main方法中直接调用,而应该到其子类Student类中去调用,且如果想在类外部也能调用这个方法,只能进行重写,还应该扩大访问范围,也就是将protected重写为public,如下代码所示:

public Student clone() {
		Student s =null;
		try {
			s= (Student)super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return s;
	} 

在重写中返回值类型可以为父类的子类,也就是说可以为Student类,而为什么要调用super是因为Object类中的clone()方法可以实现其功能,不需要进行功能重写,而s对象为Student类,所以要进行一次强转,这样就能将调用对象复制一份,再通过上述代码赋值给新对象,完成复制。

还没完,不仅仅重写方法,还要去实现此方法的标记接口Cloneable,要声明此类中可以被克隆,如图所示

 这样就能完成克隆了,输出如下:

B.深复制(将引用类型重新复制一次)

 若引进一个引用类型的数据,将会无法复制其数据,因为对于基本数据类型的对象来说又是一个新的对象数据,他们将会共用此对象数据(又是一次浅复制),当此对象数据发生改变时候,对应的所有对象的该数据都会发生改变。如下图所示:

引入一个Address类:

class Address{
	String add;
	int number;
	public Address(String add, int number) {
		super();
		this.add = add;
		this.number = number;
	}
	@Override
	public String toString() {
		return "Adress [add=" + add + ", number=" + number + "]";
	}
	
}

代码为:

public static void main(String[] args) {
Student stu3 =new Student("小叶",22,new Address("地球村",001));
		//赋值并非复制
		Student stu4 =stu3.clone();
		stu4.setAge(10);
		stu4.address.add=("月球村");
		System.out.println(stu3);
		System.out.println(stu4);
}

输出为:

 如何实现深复制,和浅复制同样的原理,在进行一次,将Address类实现克隆接口(不再展示),再次重写克隆方法即可,如下代码所示:

public Address clone() {
		Address a =null;
		try {
			a=(Address)super.clone();
		} catch (CloneNotSupportedException e) { 
			e.printStackTrace();
		}
		return a;
	}

输出为:

 处女秀很有多不足,现在已经凌晨2.30,没想到写了两个多小时,大家路过也可以留言,欢迎大家,各位大佬还望发表意见指正不足之处!谢谢各位

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值