• Java Interview 200 Questions —— Day01 —— 备战2022年秋招 —— 经典 200 问


    📖 day01 大纲

    1️⃣ JDK、JRE、JVM 之间的区别

    2️⃣ hashCode() 与 equals() 之间的关系

    3️⃣ String、StringBuffer、StringBuilder 的区别

    4️⃣ 泛型中 extends 和 super 的区别

    5️⃣ == 和 equals() 方法的区别

    📑 JDK、JRE、JVM 之间的区别

    JDK(Java SE Development Kit)

    • Java 标准开发包,它提供了编译、运行 Java 程序所需的各种工具和资源,包括 Java 编译器、Java运行时环境,以及常用的 Java 类库等

    JRE(Java Runtime Environment)

    • Java 运行环境,用于运行Java 的字节码文件。JRE 中包括了 JVM 以及 JVM 工作所需要的类库,普通用户而只需要安装 JRE 来运行 Java 程序,而程序开发者 必须安装 JDK 来编译、调试程序。

    JVM(Java Virtual Machine)

    • Java 虚拟机 ,是 JRE 的一部分,它是整个 Java 实现跨平台的最核心的部分,负责运行字节码文件。

    📚 具体流程

    我们写 Java 代码,用 txt 就可以写,但是写出来的 Java 代码,想要运行,需要先编译成字节码,那就需要编译器,而 JDK 中就包含了编译器 javac ,编译之后的字节码,想要运行,就需要一个可以执行字节码的程序,这个程序就是 JVM (Java 虚拟机),专门用来执行 Java 字节码的。

    📚 注意点

    1️⃣ 如果我们要开发 Java 程序,那就需要 JDK ,因为要编译 Java 源文件

    2️⃣ 如果我们只想运行已经编译好的 Java 字节码文件 ,就是 *.class 文件,那么就只需要 JRE

    3️⃣ JDK 中包含了 JRE ,JRE 中包含了 JVM

    4️⃣ 另外,JVM 在执行 Java 字节码时,需要把字节码解释为 机器指令,而不同的操作系统的机器指令有可能不一样,所以就导致不同操作系统上的 JVM 是不一样的,所以我们在安装 JDK 时 需要选择操作系统。

    5️⃣ JVM 是用来执行 Java 字节码的,所以凡是某个代码编译之后是 Java 字节码,那就都能在 JVM 上运行。

    📑 hashCode() 与 equals() 之间的关系

    Demo 示例

    User.java

    /***
     * @author: Alascanfu
     * @date : Created in 2022/6/30 13:08
     * @description: User 实体类 用于演示 hashCode() 与 equals() 之间的关系
     * @modified By: Alascanfu
     **/
    public class User {
        private String name ;
        
        public User(String name ){
            this.name = name ;
        }
        
        public String getName(){
            return name ;
        }
        /**
         * 如果两个 User 对象的 name 属性 相同则认为二者 equals
         * */
        @Override
        public boolean equals(Object obj) {
            User user = (User) obj;
            return user.getName().equals(this.name);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Main.java

    /***
     * @author: Alascanfu
     * @date : Created in 2022/6/30 13:12
     * @description: Main 类 用于演示 hashCode() 与 equals() 之间的关系
     * @modified By: Alascanfu
     **/
    public class Main {
        public static void main(String[] args) {
            HashMap<User, String> map = new HashMap<>();
            map.put(new User("Alascanfu"),"201901094106");
    
            System.out.println(map.get(new User("Alascanfu"))); // null
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    运行结果

    在这里插入图片描述

    这里拿到的是 null ,这是为什么呢?

    通过查看源码

    HashMap 中的 get() 方法

    public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }
    
    • 1
    • 2
    • 3
    • 4

    实际上 在 map 的 get() 方法实际首先会通过 getNode() 去判断二者的 hashCode() 是否相同。

    final Node<K,V> getNode(int hash, Object key)

    do {
        // 这里就是判断 两个 对象的 hash 值是否相等
        // 注意这里是 && 短路逻辑与 是先要进行判断 hash 值是否相等 若相等才会进行后续判断
        if (e.hash == hash &&
            ((k = e.key) == key || (key != null && key.equals(k))))
            return e;
    } while ((e = e.next) != null);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面提出了 hash 值并非一致相等 ,hash值是根据对象进行所返回的一个 hashCode

    • 故我们需要对User 对象中的 hashCode() 方法进行重写,针对 name 属性的值生成对应的 hashCode。这样就保证 name 相同的值 生成的 hashCode 也是相同的。

    User.java 中重写 hashCode() 方法

    @Override
    public int hashCode() {
        return name.hashCode();
    }
    
    • 1
    • 2
    • 3
    • 4

    此时再去运行测试运行

    在这里插入图片描述

    📚 理论知识如何在面试中回答?—— ⭐ 背这里的

    • 如果两个对象的 hashCode 不相同,那么这两个 对象肯定是不同的两个对象(即equals()一定返回 false)。

    • 如果两个对象的 hashCode 相同,不代表这两个对象一定是同一个对象,也可能是两个对象。(即 equals() 可能返回 true 可能 返回 false)

    • 如果两个对象的相等,那么他们的 hashCode 就一定相同。

    扩展

    在 Java 的一些集合类的实现中,在比较两个对象是否相等时,会根据上面的原则,先调用对象的 hashCode 进行比较,如果不相同,直接认为这两个对象不相同,如果 hashCode 相同,那么就会进一步调用 equals() 方法进行比较。而 equals 方法,就是用来最终确定两个对象是否相等,通常 equals() 方法的实现会比较重,逻辑比较多 ,而 hashCode() 主要就是得到一个 哈希值,实际上就是一串数字,所以在比较两个对象是否相等时,通常会先根据 hashCode 进行粗略比较。

    📚 注意点:所以如果我们重写了 equals()方法,那么就要注意 hashCode() 方法,一定要保证能遵守上述规则。

    📑 String、StringBuffer、StringBuilder 的区别

    1️⃣ String 是不可变的 ,如果尝试去修改就会生成一个字符串对象,StringBuilder 与 StringBuffer 是可变的。

    2️⃣ StringBuffer 是线程安全的,StringBuilder 是线程不安全的,所以在单线程环境下 StringBuilder 更高效。

    **为什么 String 是不可变的 => **String为什么是不可变的

    StringBuffer 为什么是线程安全的?——因为其中的每个方法都加上了 synchronized 同步关键字,进而每个方法都是同步方法,保证了StringBuffer的线程安全性。

    📑 泛型中 extends 和 super 的区别

    1️⃣ <? extends T>:表示包括 T 在内的任何 T 的子类。

    2️⃣ <? super ?> : 表示包括 T 在内的任何 T 的父类。

    快速了解泛型

    MyList.java

    /***
     * @author: Alascanfu
     * @date : Created in 2022/6/30 14:30
     * @description: MyList 类用于快速了解理解泛型
     * @modified By: Alascanfu
     **/
    public class MyList<E> {
        // ...
        
        public void add(E data){
            // ... 
        }
        
        // ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    📚 在类上标注了泛型 <E> 用于让用户指定 E 代表的数据类型(即 在类中 E 就代表传入的数据类型)——可以是八大基本数据类型,也可以是引用数据类型。

    Main.java

    public class Main {
        public static void main(String[] args) {
            // 这里指明泛型类型为 BigDecimal 这个精度类 jdk 中自带的
            MyList<BigDecimal> myList = new MyList<>();
            // 使用的时候 参数类型也就泛化为 指明的泛型类型 BigDecimal
            myList.add(new BigDecimal(1));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    根据修改泛化extends 或 super 类型来指明其泛化的范围

    例如此时将其修改为 extends number

    public class MyList<E extends Number> {
        // ...
        
        public void add(E data){
            // ...
        }
        
        // ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    那么说明我们用户在指定类型泛化时 只可以是 Number 这个抽象类本身或其子类类型

    在这里插入图片描述

    此时编译报错——Type parameter 'java.lang.String' is not within its bound; should extend 'java.lang.Number'

    在这里插入图片描述

    此时就是合法的。

    当然我们也可以进行测试判断对个对象的类是否相同

    public class Main {
        public static void main(String[] args) {
            MyList<Integer> myList1 = new MyList<>();
            myList1.add(1);
            MyList<Double> myList2 = new MyList<>();
            myList2.add(1.0);
        
            System.out.println(myList1.getClass().equals(myList2.getClass()));// true 
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这里的返回结果是 true 说明在通过对象获取其类 Class 时 是忽略掉泛型的。

    📑 == 和 equals() 的区别

    1️⃣ == :如果是基本数据类型,比较是值,如果是引用数据类型,比较的是引用地址

    2️⃣ equals: 具体看各个类重写 equals 方法之后的逻辑比较,比如 String 类,虽然是 引用数据类型,但是 String 中重写了 equals 方法,方法内部比较的是字符串中的各个字符是否全部相等。

    String.equals() 方法源码

    public boolean equals(Object anObject) {
        // 如果是基本数据类型值相等 就返回 true
        if (this == anObject) {
            return true;
        }
        // 如果其类型是 String 类型的对象则在进行比较
        if (anObject instanceof String) {
            // 强制类型转换用于后续判断
            String anotherString = (String)anObject;
            // 获取 原字符串的长度
            int n = value.length;
            // 判断字符长度是否相等
            if (n == anotherString.value.length) {
                // 将两个 String 对象的字符数组中的每个字符依次比较
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
  • 相关阅读:
    MAC M芯片 Anaconda安装
    Java处理视频文件,生成打标视频
    STM32F4---通用定时器更新中断
    以报时机器人为例详细介绍tracker_store和event_broker
    TiDB 中的视图功能
    Air Quality Index,简称AQI
    python-opencv之图像滤波(blur,boxFilter,GaussianBlur,medianBlur)
    【JAVA】项目部署
    WPF 控件专题 ListView 控件详解
    【同名cookie引发的血案】多个站点平台采用同名cookie引起用户信息被覆盖
  • 原文地址:https://blog.csdn.net/fuijiawei/article/details/125540650