Java进阶之Object类及常用方法详解
橙子! 人气:01. Object类
Object 类是 Java 默认提供的一个类,是所有 Java 类的祖先类,每个类都使用 Object 作为父类。
那么我们就可以使用 Object 类的引用变量指向任何类的对象。在没有明确给出一个类的父类时,Java 默认把 Object 类作为该类的父类,继承了 Object 类的所有方法。
示例:
public class Test { public static void main(String[] args) { function(new Person()); function(new Student()); } public static void function(Object obj){ System.out.println(obj); } } class Person{ private int age; private String name; } class Student{ private int grade; private String sno; }
在上面创建了两个不同类型的对象,并且作为实参传递给了 function 方法,此时相当于:
Object obj =new Person();
输出的是对象引用的值,也就是其指向对象的地址。
2. 常用的方法
Object 类中提供了一些方法,其中常用的方法有 toString()
方法,equals()
方法,hashcode()
方法等。在使用前导入 Object 类:
import java.util.Objects;
2.1 toString 方法
JDK源码中的toString方法:
//Object类中的toString()方法实现: public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); }
toString()
方法定义在 Object 类中,返回值是 String 类型,根据调用它的对象返回类名和它的引用地址。
示例:
public class Test { public static void main(String[] args) { Person person=new Person(); System.out.println(person.toString()); System.out.println(person); } } class Person{ public String name; }
在我们打印对象的引用时,实际上是默认调用了这个对象的toString
方法。返回此对象所在的类及对应的堆空间对象实体的首地址值。
该方法一般要重写后使用,一般重写是将类的对象的属性返回。在没有被重写时,返回的字符串格式是 类名@哈希值,哈希值是十六进制的。示例:
public class Test { public static void main(String[] args) { Person person=new Person(); System.out.println(person.toString()); System.out.println(person); } } class Person{ private String name="张三"; private int age=20; public String toString(){ return "Person:name "+name+" age "+age; } } /* Person:name 张三age 20 Person:name 张三age 20 */
2.2 equals 方法
JDK 源码中的equals()
方法:
// Object类中的equals方法 public boolean equals(Object obj){ return (this == obj); // 使用引用中的地址直接来进行比较 }
equal()
方法定义在 Object 类中,返回值是 boolean 类型,其作用是比较两个对象在堆区的地址是否相同。示例:
public class Test { public static void main(String[] args) { Person person1=new Person("张三",18); Person person2=new Person("李四",20); boolean b=person1.equals(person2); System.out.println(b); } } class Person{ private String name; private int age; public Person(String name,int age){ this.name=name; this.age=age; } } /* false */
需要注意的是比较的是两个引用的值是否相同,即引用执行的地址。如果想要比较对象中的内容,可以重写该方法实现。示例:
public class Test { public static void main(String[] args) { Person person1=new Person("张三",18); Person person2=new Person("张三",18); boolean b=person1.equals(person2); System.out.println(b); } } class Person{ private String name; private int age; public Person(String name,int age){ this.name=name; this.age=age; } @Override public boolean equals(Object obj) { //判断是否为空 if (obj == null) { return false ; } if(this == obj) { return true ; } // 不是Person类对象 if (!(obj instanceof Person)) { return false ; } Person per = (Person) obj ; // 向下转型,比较属性值 //此时比较时按照重写后的equal()方法的规则 return this.name.equals(per.name) && this.age==per.age ; } } /* true */
此时,我们重写了equals()
方法,用来比较对象中的内容是否相同,这部分比较难,可以仔细推敲这段代码,理解其含义。
2.3 hashcode 方法
JDK源码中的hashcode()
方法:
public native int hashCode();
hashcode()方法定义在Object类中,用于放回对象的 hash 代码值,确定对象在内存中存储的位置是否相同。
重写该方法使用:
import java.util.Objects; public class Test { public static void main(String[] args) { Person person1=new Person("张三",18); Person person2=new Person("张三",18); System.out.println(person1.hashCode()); System.out.println(person2.hashCode()); } } class Person{ private String name; private int age; public Person(String name,int age){ this.name=name; this.age=age; } @Override public int hashCode() { return Objects.hash(name, age); } } /* 24022538 24022538 */
事实上 hashCode() 在散列表中才有用,在其它情况下没用,在散列表中hashCode() 的作用是获取对象的散列码,进而确定该对象在散列表中的位置。
3. 注意事项
重写 equals() 方法时,也必须重写 hashcode() 方法吗?
答:必须,hashCode 和 equals 两个方法是用来协同判断两个对象是否相等的,采用这种方式的原因是可以提高程序插入和查询的速度,当重写equals方法后有必要将hashCode方法也重写,这样做才能保证不违背hashCode方法中相同对象必须有相同哈希值的约定。
== 和 equals 的区别是什么?
答:对于基本类型和引用类型 == 的作用效果是不同的,如下所示:
基本类型:比较的是值是否相同;
引用类型:比较的是引用是否相同
例如在比较两个字符串时:
public class Test { public static void main(String[] args) { String s1=new String("HelloWorld"); String s2=new String("HelloWorld!"); String s3="HelloWorld"; System.out.println(s1.equals(s2)); System.out.println(s1.equals(s3)); } }
运行结果是
false
true
为什么会出现这样的结果呢?这里就引出了一个新的概念,字符串常量值。字符串有两种赋值方式,一种是字面值的方式赋值,另一种是 new 一个新的对象,这两种方式在性能和内存方面都存在差异。
当使用字面值的方式创建一个对象时,JVM 会在字符串常量池中寻找是否存在这个对象 "HelloWorld"
,如果不存在,则创建这个对象,并将这个对象的引用地址返回给字符串常量 s3,如果存在,则不创建对象,直接返回池中这个对象的地址。这样我们就不难理解上面这段的代码为什么会出现这样的情况了!
4. 总结
Object 类是 Java 默认提供的一个类,是所有 Java 类的祖先类,每个类都使用Object作为父类。Object 类中提供了一些方法,这些方法为了达到想要的效果,我们一般在类中重写使用!
加载全部内容