目录 
1.hashCode()方法: public int hashCode()
2.getClass()方法: public final Class getClass()
3.toString()方法: public String toString()
5.clone()方法: protected Object clone ()
一.了解Object类
- Object类是所有类的根类(即超类).也就是所有类的"老祖宗".所有类都直接或者间接的继承自该类!
- Object类是java.lang包下的.创建Object类对象 ,java.lang. 包下的类可以不用 import 导包.
- Object类的构造方法: public Object()
二.Object类中常用的方法
1.hashCode()方法: public int hashCode()
- 返回该对象的哈希码值。默认情况下,该方***根据对象的地址来计算.
- 不同对象的,hashCode()一般来说不会相同. 但是,同一个对象的hashCode()值肯定相同.
- 不是对象的实际地址值,可以理解为逻辑地址值.
- 支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能
public class Test {
public static void main(String[] args) {
Object obj = new Object();
System.out.println(obj); //java.lang.Object@12a3a380
int hashCode = obj.hashCode(); //312714112
System.out.println(hashCode);
//一般情况下,不同的对象他的hashCode值也不一样
Object obj2 = new Object();
System.out.println(obj2); //java.lang.Object@29453f44
int hashCode1 = obj2.hashCode();
System.out.println(hashCode1); //692404036
}
}
2.getClass()方法: public final Class getClass()
- 返回此 Object 的运行时类,即返回该类的字节码文件对象
(Object.java文件编译生成Object.class字节码文件,当 .class文件加载进内存,按照Java万物皆对象的思想,他会把.class文件看做一个对象,他就会创建 .class 文件对象)
- 可以通过Class类中的一个方法,获取对象的真实类的全名称。public String getName()
- 用Class 类型来描述 字节码文件对象。getClass()要做的就是把这个 .class 文件对应的那个对象获取出来。(字节码文件加载进内存只有一次也就只会创建一个对应的对象)
public class Test{
public static void main(String[] args) {
Object obj = new Object();
System.out.println(obj);
Class<?> aClass = obj.getClass(); //Object.class----对应的那个对象,获取出来
Object obj2 = new Object();
System.out.println(obj2);
Class<?> aClass1 = obj2.getClass();
System.out.println(obj == obj2); //false(两个对象的地址值不同)
System.out.println(aClass == aClass1); //true(两个对象的字节码文件一样,所对应的字节码文件对象也就只有一个)
}
}
3.toString()方法: public String toString()
toString()方法,以字符串形式返回对象的地址值.
public class toString {
public static void main(String[] args) {
//toString() 返回对象的地址值,以字符串形式返回。
//底层代码
// public String toString() {
// return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
// }
Object obj = new Object();
String name = obj.getClass().getName();
int i = obj.hashCode();
System.out.println(i); //312714112
String s1 = Integer.toHexString(i);
System.out.println(s1); //12a3a380
System.out.println(name + "@" + s1); //java.lang.Object@12a3a380
System.out.println(name); //java.lang.Object
//输出一个对象时,这个对象底层默认调用的就是 toString() 只是我们省略不写。
System.out.println(obj); //java.lang.Object@12a3a380
System.out.println(obj.toString()); //java.lang.Object@12a3a380
Object obj2 = new Object();
System.out.println(obj2); //java.lang.Object@29453f44
String s = obj2.toString();
System.out.println(s); //java.lang.Object@29453f44
}
//底层方法实现
public String toString() {
return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
}
}
我们的子类调用父类的toString()可以打印出对象的地址值,但是有的时候,我们觉得打印这个地址值,意义不大,我们想打印一些有意义的东西,比如打印成员变量的值.这个时候子类对父类的toString()方法实现不满意,子类就可以重写。自定义的类,比如Student 一般的重写逻辑,就是打印成员变量的值。
当然以后打印一个对象名,没有输出对象的地址值,说明该类一定重写了父类中的toString()方法。
public class MyTest2 {
public static void main(String[] args) {
Student s = new Student("张三", 23);
System.out.println(s);
}
}
class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.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;
}
@Override
public String toString() {
return "Student{" +
"姓名='" + name + '\'' +
", 年龄=" + age +
'}';
}
}
4.equals()方法
指示其他某个对象是否与此对象“相等”。默认情况下比较的是对象的引用(地址值)是否相同。
源代码:
public boolean equals(Object obj) {
return (this == obj);
}
public class Equals {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
//比较两个对象的地址值是否相同
System.out.println(obj1 == obj2); //false
// boolean equals (Object obj)
// 指示其他某个对象是否与此对象“相等”。
boolean b = obj1.equals(obj2); //false
System.out.println(b);
}
//底层代码
public boolean equals(Object obj) {
return (this == obj);
}
}
Object类的equals()方法的默认比较逻辑,是比较两个对象的地址值是否相同。但是咱们觉得老是比较两个对象的地址值是否相同是没有意义的,咱们想比较其他的,比如比较两个对象的成员变量的值是否相同。这种情况子类不满意父类equals()方法的实现,那么子类就可以重写父类的equals方法,按照子类的比较方式区别。
在咱们自定义的类中,就会比较两个对象的成员变量的值是否相同
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.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;
}
//重写之后的equals方法
@Override
public boolean equals(Object obj) { // Object obj=s2 多态 Object obj=dog;
//如果对象为空
if (obj == null) {
return false;
}
//如果是自己和自己比较,直接true
if (this == obj) { //从效率考虑
return true;
}
// instanceof:判断断一个引用或对象,是不是该类型的一个引用,或者说对象
if (!(obj instanceof Student)) { //健壮性方面考虑
return false;
}
//向下转型
Student s2 = (Student) obj;
//name我们是想要比较两个名字字面上的内容是否相同,用==号他比较的是两个字符串对象的地址值是否相同
//那我们实际上是要比较两个名字字面上的内容是否相同,我们应该用String类中的equals()方法来比较。
return this.age == s2.age && this.name.equals(s2.name);
}
}
class Dog {
}
补:instanceof
instanceof:判断断一个引用或对象,是不是该类型的一个引用,或者说对象. 如上例中的就是判断Student是不是传入的类的对象.
5.clone()方法: protected Object clone ()
clone 的步骤:
- Object类的clone ()方法,权限修饰符是受保护的,可能在外界无法直接调用.就可以重写 clone ()方法 把权限修饰符改为public 但是克隆的逻辑还是继续调用父类的,super.clone();
- 需要你这个类实现一个标记接口 Cloneable,不重写,克隆默认就不支持。
Cloneable 他里面没有任何抽象方法,这种接口,我们称为为标记接口,意思就是给这个类打个标记,想让虚拟机知道要进行克隆的操作。
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog();
dog.name = "小白";
dog.age = 3;
System.out.println(dog);
//把上面的dog对象克隆一份
Dog cloneDog = (Dog) dog.clone();
System.out.println(cloneDog);
}
}
//Dog类实现接口Cloneable
class Dog implements Cloneable {
public String name;
public int age;
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写 clone ()方法
@Override
public Object clone() throws CloneNotSupportedException {
//你的重写逻辑,还是调用父类的克隆逻辑
return super.clone();
}
}
clone的内存图 :
浅克隆和深克隆:
浅克隆:克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。使用clone()方法就是浅克隆的方式.
对象的浅克隆也不会调用到构造方法的。
深克隆(后面会深层次学习):克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候把另外一个对象也克隆一份. 采用IO流来实现 使用 ObjectOutputStream 将对象写入文件中,然后再用ObjectInputStream读取回来
(小编也在努力学习更多哟!以后会多多分享哒!)
希望对友友们有所帮助!!!!