个人博客 个人博客

2020 记录精彩的程序人生

目录
Java 基础常识
/  

Java 基础常识

1. ==和equals的区别

== :判断两个对象的地址是不是相等。即判断两个对象是不是同一个对象。(基本数据类型==比较的是值,引用数据类型==比较的是内存地址)

因为 Java 只有值传递,对于 == 来说,不管是比较基本数据类型,还是引用数据类型的变量,其本质比较的都是值,只是引用类型变量存的值是对象的地址。

equals() :判断两个对象是否相等,它不能用于比较基本数据类型的变量。equals()方法存在于 Object 类中,而 Object 类是所有类的直接或间接父类。

  • 默认的equals方法:默认是 Object 的 equals 方法是比较的是对象的内存地址,
    重写的equals方法: String 的 equals 方法比较的是对象的值。
  • 当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。

例:调用 Object 的 equals 方法(比较的是对象内存地址)

public static void main(String[] args) {

        Student stu1 = new Student("小明", 22);
        Student stu2 = new Student("小明", 22);

        System.out.println("内存地址:" + stu1 + ",hashCode:" + stu1.hashCode());
        System.out.println("内存地址:" + stu2 + ",hashCode:" + stu2.hashCode());

        System.out.println(stu1.equals(stu2));
    }

输出结果:

内存地址:com.wit.pojo.Student@1b6d3586,hashCode:460141958
内存地址:com.wit.pojo.Student@4554617c,hashCode:1163157884
false

重写 equals 和 hashCode 方法,调用的是 String 的 equals 方法(比较的是对象的值)

@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) &&
                Objects.equals(age, student.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

输出结果:

内存地址:com.wit.pojo.Student@165f3d8,hashCode:23458776
内存地址:com.wit.pojo.Student@165f3d8,hashCode:23458776
true

2. 为什么重写 equals 时必须重写 hashCode 方法?

如果两个对象相等,则 hashcode 一定也是相同的。两个对象相等,对两个对象分别调用 equals 方法都返回 true。但是,两个对象有相同的 hashcode 值,它们也不一定是相等的 。因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖。

为什么两个对象有相同的 hashcode 值,它们也不一定是相等的?
重写 hashCode 方法

内存地址:com.wit.pojo.Student@40f089fe,hashCode:1089505790
内存地址:com.wit.pojo.Student@40f089fe,hashCode:1089505790
false

3. 重载和重写的区别

重载: 方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和访问修饰符可以不同。
重载:对象中的构造函数就是重载

public class Student{

    public void getName() {
        System.out.println("小爱同学");
    }

    public void getName(String name){
        System.out.println(name);
    }

    public static void main(String[] args) {
        Student stu = new Student();
        stu.getName();
        stu.getName("小明同学");
    }
}

输入结果:

小爱同学
小明同学

重写就是子类对父类方法的重新改造,外部样子不能改变,内部逻辑可以改变

  1. 返回值类型、方法名、参数列表必须相同,抛出的异常范围小于等于父类,访问修饰符范围大于等于父类。
  2. 如果父类方法访问修饰符为 private/final/static 则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
  3. 构造方法无法被重写。
class School {
    public void getName() {
        System.out.println("小明同学");
    }
}

public class Student extends School {
    // @Override 强制检查重写的方法
    @Override
    public void getName() {
        System.out.println("小爱同学");
    }

    public void print() {
        super.getName();
        getName();
    }

    public static void main(String[] args) {
        Student stu = new Student();
        stu.print();
    }
}

输出结果:

小明同学
小爱同学

4. 浅拷贝 和 深拷贝

浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。