Object类中的方法
来源:互联网 发布:淘宝总公司投诉电话 编辑:程序博客网 时间:2024/05/01 06:52
为了便于验证,定义一个User实体类如下:
public class User { private int id; private String name; private Integer age; private Date birthday; public User(int id, String name, Integer age, Date birthday) { super(); this.id = id; this.name = name; this.age = age.intValue(); this.birthday = birthday; } 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 Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", age=" + age + ", birthday=" + birthday.getTime() + "]"; }}
1.equals()
在Object类中定义的equals方法,其含义在于判断两个对象的地址是否相同,即判断两个对象是否为同一对象。这时,equals() 等价于”==”。
由于所有的类都继承自Object,所以如果自己定义的类未重写(override)equals方法,则equals判断两个对象是否为同一对象;
如果重写了equals方法,则equals的判断逻辑根据方法本身的实现。通常做法是根据业务逻辑,判断对象的属性值是否相等。
public static void main(String[] args) { User user1 = new User(1,"John",24,new Date()); User user2 = new User(1,"John",24,new Date()); System.out.println(user1.equals(user2)); //out:false System.out.println(user1.equals(user1)); //out:true System.out.println(user1 == user2); //out:false System.out.println(user1 == user1); //out:true }
覆盖equals方法:
@Override public boolean equals(Object obj) { //非空对象不可与null值相等 if(obj == null) return false; //同一对象一定相等 if(this == obj) return true; //类型不同的两个对象一定不相等 if(this.getClass() != obj.getClass()) return false; //当且仅当三个属性都相等时,两个对象相等 User person = (User)obj; return id==person.id && name.equals(person.name) && age.intValue()==person.age.intValue(); }
覆盖equals方法后,user1与user2相等:
public static void main(String[] args) { User user1 = new User(1,"John",24); User user2 = new User(1,"John",24); System.out.println(user1.equals(user2)); //out:true System.out.println(user1.equals(user1)); //out:true System.out.println(user1 == user2); //out:false System.out.println(user1 == user1); //out:true }
2.hashCode()
hashCode方法的返回值为int,用来确定一个对象在散列表中的索引位置。该方法在创建当前类的散列集(HashMap, HashSet, Hashtable)时才有意义,其它情况没有意义。
– equals为true的两个对象,hashCode一定相同;
– hashCode相同的两个对象,equals不一定为true(哈希冲突)
– 在使用散列集时,如果重写了equals方法,则一定要重写为hashCode方法,否则equals方法无效。
重写hashCode方法:
@Overridepublic int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((age == null) ? 0 : age.hashCode()); result = prime * result + ((birthday == null) ? 0 : birthday.hashCode()); result = prime * result + id; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result;}
3.clone()
首先,考虑一下使用“=”赋值运算符的情况。
在Java中的数据类型分为两大类:基本类型和引用类型
基本类型:int, long, float, double, char等。
引用类型:Integer, Long, Float, Double, String等。
将一个基本类型的变量赋值给基本类型的时候,新变量会在堆内存中开辟自己的空间,再把旧变量的值写入。因此新旧变量的内存是各自独立的堆空间,对其中一个变量的值更改不会影响另一个变量的值;
将一个引用类型的变量赋值给引用类型的时候,新变量并不会在堆内存中开辟自己的空间,而是仅仅保存了旧变量引用的堆内存地址,两个变量指向同一块堆内存空间。因此,对一个变量值的更改会影响另一个变量的值。
下边这个简单的程序说明了这一点:
int a = 5;int b = a;a = 10;System.out.println("a="+a+",b="+b);//out:a=10,b=5Integer a1 = 5;Integer b1 = a1; System.out.println("a1="+a1+",b1="+b1);//out:a1=5,b1=5
由于我们自定义的类都是引用类型的,所以,如果需要使新对象和旧对象拥有相同的值,并且对其中一个对象状态的更改不会影响另一个对象,就需要使用clone()方法。
使用clone方法需要:
1.实现Cloneable接口;(只作为标识)
2.重写Object类的clone方法,并将访问修饰符定义为public。(因为在Object类中的clone方法是protected的,只能在本类中访问)
下面在使User类实现Cloneable接口,并重写clone方法,使用默认的实现:
public class User implements Cloneable
@Override public User clone() throws CloneNotSupportedException { return (User)super.clone(); }
在测试方法里验证clone方法:
User user1 = new User(1,"user1",24, new Date());//浅拷贝User user2 = user1.clone();System.out.println("user1:"+user1);//out:"user1:User [id=1, name=user1, age=24, birthday=1430137523544]"System.out.println("user2:"+user2);//out:"user2:User [id=1, name=user1, age=24, birthday=1430137523544]"user2.setName("user2");user2.setAge(30);System.out.println("user1:"+user1);//out:"user1:User [id=1, name=user1, age=24, birthday=1430137523544]"System.out.println("user2:"+user2);//out:"user2:User [id=1, name=user2, age=30, birthday=1430137523544]"user2.getBirthday().setTime(1430137087450L);System.out.println("user1:"+user1);//out:"user1:User [id=1, name=user1, age=24, birthday=1430137087450]"System.out.println("user2:"+user2);//out:"user2:User [id=1, name=user2, age=30, birthday=1430137087450]"
可以看出在7、8行对新对象String类型和Integer类型进行更改时,并没有影响旧对象该域的值。因为这两种类型都是final类型的,为不可变类型,所以每次赋值都是堆内存中的一个新对象。
而第11行,对Date类型的值做改变的时候,旧对象的值也相应的改变。
由此可见,Object类中clone的默认实现是“浅拷贝”。
浅拷贝的意思是:当拷贝一个类的对象时,对于旧对象中基本类型的域和不可变引用类型(String, Integer等)的域 在堆内存中开辟独立的空间给新对象,而对于可变引用类型(Date, 自定义类型)的域 使新对象共享旧对象该域的堆内存空间。
我们通常需要的是深拷贝,即:所有域都开辟独立于旧对象的堆内存空间,各自的更改不影响对方。
重新定义clone方法,实现深拷贝:
@Overridepublic User clone() throws CloneNotSupportedException { User cloned = (User)super.clone(); //将所有的可变引用类型的域都clone cloned.birthday = (Date)birthday.clone(); return cloned;}
运行结果:
User user1 = new User(1,"user1",24, new Date());//深拷贝User user2 = user1.clone(); System.out.println("user1:"+user1);//out:"user1:User [id=1, name=user1, age=24, birthday=1430139233085]"System.out.println("user2:"+user2);//out:"user2:User [id=1, name=user1, age=24, birthday=1430139233085]"user2.setName("user2");user2.setAge(30);System.out.println("user1:"+user1);//out:"user1:User [id=1, name=user1, age=24, birthday=1430139233085]"System.out.println("user2:"+user2);//out:"user2:User [id=1, name=user2, age=30, birthday=1430139233085]"user2.getBirthday().setTime(1430137087450L);System.out.println("user1:"+user1);//out:"user1:User [id=1, name=user1, age=24, birthday=1430139233085]"System.out.println("user2:"+user2);//out:"user2:User [id=1, name=user2, age=30, birthday=1430137087450]"
可见新对象的birthday的改变已不在影响旧对象该域的值
- Object类中的方法
- Object类中的方法
- Object类 中的方法
- Object类中的方法
- Java Object类中的方法
- 重写Object类中的方法
- Java Object类中的方法
- Object类中的方法介绍
- Object类中的方法介绍
- Object类中的方法介绍
- 类Object中的equals()方法
- Object类中的方法介绍
- Object类中的clone方法
- Object类中的方法详解
- Java Object类中的方法
- Object 类中的 equals方法
- Object类中的方法示例
- Object 类中的 equals方法
- LeetCode twoSum
- Java垃圾回收是如何工作的?
- Objective-C - 模型的设计
- Distinctive Image Features from Scale-Invariant Keypoints-SIFT算法译文
- Android环境搭建 目录介绍
- Object类中的方法
- IOS7开发~JavaScriptCore (一)
- 自定义标签工具栏
- New files creation and Makefile
- Scala编程指南(2) 更少的字更多的事
- C++友元
- presentViewController弹出界面的大小设置
- 设计模式 笔记 享元模式 Flyweight
- Objective-C - 循环引用问题