hashCode()方法
在弄清楚hashCode之前我们需要先了解一下Object类
//Object 是我们所有类的顶层父类,所有类都是直接或间接继承自他
//创建Object类的对象 :Object obj = new Object();
Object 类和我们学过的所有类具有相同的性质,只不过它是所有类的顶层父类。
下面是hashCode()介绍
//hashCode() 返回一个对象的哈希码值
//不同对象的哈希码值不一样
public class MyTest {
public static void main(String[] args) {
//Object 是我们所有类的顶层父类,所有类都是直接或间接继承自他
Object obj = new Object(); //创建Object类的对象
//object中常用的方法
//hashCode() 返回一个对象的哈希码值
int i = obj.hashCode();
System.out.println(i);
Object o = new Object();
int i1 = o.hashCode();
System.out.println(i1);
//不同对象的哈希码值不一样
}
}
equals()方法
equals()是用来比较两个对象的地址值是否相等,调用方法为:
// boolean equals (Object obj) 返回的是真/假值(true or false)
// boolean X = a.equals(b) 比较a与b的地址值,并返回给X
equals()方法重写
因为有些时候我们并不是想去比较两个对象的地址值是否相等,而是想要比较两个对象中的成员变量是否相等,因此我们会对equals()方法进行重写。
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
//instanceof可以判断一个引用或者对象,是不是该类型的一个引用
//我认为两个对象的成员变量一模一样,我就认为两个对象一样
//向下转型
//优化比较效率
if(this==obj)
return true;
if(!(obj instanceof Student))
{
return false;
}
Student stu = (Student) obj;
//“张三”==“张三”有可能是false,string类认为父类object中的equals默认比较方式意义不大
//string类重写了equals方法,取比较两个字符串的字面内容是否相同。
return this.name.equals(stu.name)&&this.age==stu.age;
}
}
上面从@Override开始就是对equals方法的重写,不仅考虑了两个对象的成员一致问题,还考虑到了不同类之间肯定不相等的问题(这里用到了instanceof这个比较运算符)以及同一个对象必然相等的问题,这就优化了equals()方法,提高了运行效率。
当然,我们可以用快捷方式实现上述重写部分的代码(狗头狗头狗头),按住Ctrl+O选择重写equals(obj:Object):boolean,即可生成重写部分的代码,如下:
@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);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public class MyTest2 {
public static void main(String[] args) {
// boolean equals (Object obj) 比较两个对象的地址值是否相等
Object obj1 = new Object();
Object obj2 = new Object();
boolean equals = obj1.equals(obj2);
System.out.println(equals);
Object stu1 = new Student("张三", 24);
Object stu2 = new Student("李四", 23);
Object stu3 = new Student("张三", 24);
Object dog = new Dog("旺财", 2);
System.out.println(stu1.equals(dog));
System.out.println(stu1.equals(stu1));
System.out.println(stu1.equals(stu2));
System.out.println(stu1.equals(stu3));
}
}
class Dog{
String name ;
int age;
public Dog() {}
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
getClass()方法
在java中,万物皆是对象,因此 .class 文件也是一个对象(例:Student.class 加载进内存之后,JVM就会为Student.class创建一个对象),可以通过getClass()这个方法将 .class 文件获取出来。需要注意的是同一个类只有一个字节码文件,通过equals()方法来说明一下 。
public class MyTestgetClass {
public static void main(String[] args) {
//Class<?>getClass()按Java万物皆对象的思想,那么他会把.class文件看做一个对象
//Student.class 加载进内存后,JVM就会为Student.class创建一个对象
//我们可以把这个对象获取出来用,怎么获取?用getClass()这个方法来获取
Student student1 = new Student();
Student student2 = new Student();
Class aClass1 = student1.getClass();
Class aClass2 = student2.getClass();
System.out.println(student1.equals(student2));
System.out.println(aClass1.equals(aClass2));
}
}
class Student{
}
toString()方法
toString()方法的主要作用是返回对象的字符串形式,这一般不是我们想要的结果,因此,我们会对该方法进行重写。判断是否重写,只需调用该方法看返回值是否为字符串,若不是,则重写了该方法。
public String toString()
a:返回该对象的字符串表示。
源代码:
public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}
b:它的值等于:
getClass().getName() + ‘@’ + Integer.toHexString(hashCode())
c:由于默认情况下的数据对我们来说没有意义,一般建议重写该方法。
怎么重写, 一般是将该类的所有的成员变量组成返回即可
public class MyTesttoString {
public static void main(String[] args) {
Student student = new Student("张三",20);
System.out.println(student.toString());
// public String toString() {
// return getClass().getName() + "@" + Integer.toHexString(hashCode());
// }
}
}
class Student{
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
clone()方法(这里只对浅克隆做介绍)
-
克隆的创建:
// protect Object clone() 创建并返回此对象一个副本
public class MyTestClone {
public static void main(String[] args) throws CloneNotSupportedException {
//protect Object clone() 创建并返回此对象一个副本
Dog dog = new Dog();
Object clone = dog.clone();//克隆对象不会执行构造方法
}
}
//Cloneable 里面没有任何抽象方法,这种接口,我们称之为标记即可,作用就是让JVM知道,我要克隆
class Dog implements Cloneable{
}
clone()的权限修饰符是受保护的,在用的时候,让该类重写该方法,并把该方法的权限修饰符改为public, 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。Cloneable接口只不过是一个标识接口而已,没有任何方法。并且在main方法中“扔掉”了一个克隆会引起的“bug”, throws CloneNotSupportedException,这样就可以成功调用 clone()方法。
- 还要强调的是克隆对象不会调用构造方法
public class MyTestClone {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog();
Object clone = dog.clone();
Dog dog1= (Dog) clone;//克隆对象不会执行构造方法
}
}
class Dog implements Cloneable{
public Dog() {
System.out.println("构造方法执行了");
}
}
- 对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。就是说地址给了克隆对象一份,这样的话,克隆的对象也会更改地址所指向的值,使得被克隆的对象内容被改变
public class MyTestDeepClone {
//浅克隆
public static void main(String[] args) throws CloneNotSupportedException {
DogFood dogFood = new DogFood("王中王");
Dog dog1 = new Dog("旺财", 2, dogFood);
dog1.food.name = "双汇";
Dog dog2 = (Dog) dog1.clone();
dog2.name="来福";
dog2.age=2;
dog2.food.name="金锣";
System.out.println(dog1.name+"=="+dog1.age+"=="+dog1.food.name);
System.out.println(dog2.name+"=="+dog2.age+"=="+dog2.food.name);
}
}
class Dog implements Cloneable {
String name;
int age;
DogFood food;
public Dog() {
}
public Dog(String name, int age, DogFood food) {
this.name = name;
this.age = age;
this.food = food;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class DogFood {
String name;
public DogFood() {
}
public DogFood(String name) {
this.name = name;
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/14652.html