目录    

一.了解Object类​

二.Object类中常用的方法​

​1.hashCode()方法:  public int hashCode()

​2.getClass()方法:  public final Class getClass()

​3.toString()方法:  public String toString()

 ​4.equals()方法 

​补:instanceof

5.clone()方法:   protected Object clone ()

clone 的步骤:

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读取回来

(小编也在努力学习更多哟!以后会多多分享哒!)

希望对友友们有所帮助!!!!