• 【面经】华为车BU面经


    本科生、研究生阶段的项目经历
    本科生、研究生阶段的成绩排名
    讲项目,遇到问题,如何解决
    代码量多少
    JRE、JDK、JVM 的区别
    • JDK(Java Development Kit)是整个JAVA的核心,包括了 Java 运行环境(Java Runtime Envirnment),一堆 Java 工具(javac/java/jdb等)和 Java 基础的类库(即 Java API 包括 rt.jar)。

    • JRE(Java Runtime Environment,Java 运行环境),包含 JVM 标准实现及 Java 核心类库。JRE 是 Java 运行环境,并不是一个开发环境,所以没有包含任何开发工具(如编译器和调试器)。

    • JVM(Java Virtual Machine),即 Java 虚拟机, Java 运行时的环境,JVM 是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。针对 Java 用户,也就是拥有可运行的 .class 文件包(jar 或者 war)的用户。里面主要包含了 Jvm 和 Java 运行时基本类(rt.jar)。rt.jar 可以简单粗暴地理解为:它就是 Java 源码编译成的 jar 包。Java 虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。这就是 Java 的能够 “一次编译,到处运行” 的原因。

    具体地讲:

    • JDK = JRE + 开发工具集(例如 Javac 编译工具等);

    • JRE = JVM + Java SE 核心类库;

    Java 权限修饰符
    修饰符当前类同包子类其他包
    public
    protected
    default
    private
    两个 Java 的设计模式

    观察者模式:又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。

    • 角色:Subject-抽象主题,ConcreteSubject-具体主题,Observer-抽象观察者,ConcreteObserver-具体观察者。
    • 使用场景:关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。事件多级触发场景。跨系统的消息交换场景,如消息队列、事件总线的处理机制。
    • 优点:解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。
    • 缺点:在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在 Java 中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

    单例模式:单例模式是指在内存中只会创建且仅创建一次对象的设计模式。在程序中多次使用同一个对象且作用相同时,为了防止频繁地创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。

    • 类型:懒汉式-需要时才创建;饿汉式-类加载就创建。
    Java 单例模式的代码

    懒汉式:

    public class Singleton {
        
        private static Singleton singleton;
        
        private Singleton(){}	// 注意要用 private
        
        public static Singleton getInstance() {
            if (singleton == null) {
                singleton = new Singleton();
            }
            return singleton;
        }
        
    }
    

    多线程情况下保证只创建一个对象:

    public class Singleton {
        
        private static Singleton singleton;
        
        private Singleton(){}
        
        public static Singleton getInstance() {
            // 线程A和线程B同时看到singleton = null,如果不为null,则直接返回singleton
            if (singleton == null) {
                // 线程A或线程B获得该锁进行初始化
                synchronized(Singleton.class) {
                    // 其中一个线程进入该分支,另外一个线程则不会进入该分支
                    if (singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    
    抽象类和接口的区别

    成员的区别:

    • 抽象类:
      • 构造方法:有构造方法,用于子类实例化使用。
      • 成员变量:可以是变量,也可以是常量。
      • 成员方法:可以是抽象的,也可以是非抽象的。
    • 接口:
      • 构造方法:没有构造方法。
      • 成员变量:只能是常量。默认修饰符:public static final。
      • 成员方法:jdk1.7 只能是抽象的。默认修饰符:public abstract。jdk1.8 可以写以 default 和 static 开头的具体方法。

    类和接口的关系区别:

    • 类与类:继承关系,只能单继承。可以多层继承。
    • 类与接口:实现关系,可以单实现,也可以多实现。类还可以在继承一个类的同时实现多个接口。
    • 接口与接口:继承关系,可以单继承,也可以多继承。

    体现的理念不同:

    • 抽象类里面定义的都是一个继承体系中的共性内容。
    • 接口是功能的集合,是一个体系额外的功能,是暴露出来的规则。
    Java 的 List、Map、Set 的区别

    有序无序,有无重复元素,单列数据 v skey-value。

    int 和 Integer 的区别

    定义:

    • int 是 java 的基本数据类型。
    • Integer 继承了 Object 类,是对象类型,是 int 的包装类。

    区别:

    值的存储:int 存储在栈中;Integer 对象的引用存储在栈空间中,对象的数据存储在堆空间中。

    初始化:int 初始化值为0;Integer 初始化值为null。

    传参:int 是值传递,栈中的数据不可变。Integer 对象是引用传递,引用不可变,但是引用指向的堆空间地址中的值是可以改变的。

    泛型支持:泛型不支持 int,但是支持 Integer。

    运算:int 可以直接做运算,是类的特性;Integer 的对象可以调用该类的方法,但是在拆箱之前不能进行运算,需要转化为基本类型 int。

    == 和 equal 的区别
    • == 是运算符,equal 是方法。
    • 比较包装类型:== 比较的是内存地址,而 equal 比较的是值。
    • 比较 String 类型:== 比较的是内存地址,equal 比较的是值。
    • 比较对象:== 和 equal 比较的都是内存地址,因为 equal 没有被重写。没有被重写的 equal 都是 object 的 equal 方法。重写后可以比较对象的值。
    垃圾回收

    垃圾收集主要是针对堆和方法区进行。

    如何判断对象是否可以回收:

    1. 引用计数法:引用计数为 0 的对象可被回收。Java 虚拟机不使用引用计数算法。
    2. 可达性分析算法:以 GC Roots 为起始点进行搜索,可达的对象都是存活的,不可达的对象可被回收。
    3. 方法区的回收:方法区主要存放永久代对象,主要是对常量池的回收和对类的卸载。
    4. finalize()

    垃圾收集算法

    1. 标记-清除:标记:活动对象会在对象头部打上标记。清除:进行对象回收并取消标志位。
    2. 标记-整理:让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
    3. 复制:将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另一块上面,然后再把使用过的内存空间进行一次清理。现在的商业虚拟机都采用这种收集算法回收新生代,但是并不是划分为大小相等的两块,而是一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象全部复制到另一块 Survivor 上,最后清理 Eden 和使用过的那一块 Survivor。
    4. 分代收集:根据对象存活周期将内存划分为几块,不同块采用适当的收集算法。一般将堆分为新生代和老年代。新生代使用:复制算法。老年代使用:标记 - 清除 或者 标记 - 整理 算法
    强引用能回收吗,不回收最后报什么异常

    强引用的对象是可触及的,垃圾收集器就永远不会回收掉被引用的对象。

    报 OOM。

    sleep 和 wait 的区别,怎么唤醒 wait
    • 每个对象都有一个锁来控制同步访问,Synchronized 关键字可以和对象的锁交互,来实现同步方法或同步块。
      • sleep() 方法正在执行的线程主动让出 CPU(然后 CPU 就可以去执行其他任务),在 sleep 指定时间后 CPU 再回到该线程继续往下执行(注意:sleep 方法只让出了 CPU,而并不会释放同步资源锁);
      • wait() 方法则是指当前线程让自己暂时退让出同步资源锁,以便其他正在等待该资源的线程得到该资源进而运行,只有调用了notify()方法,之前调用 wait() 的线程才会解除 wait 状态,可以去参与竞争同步资源锁,进而得到执行。(注意:notify 的作用相当于叫醒睡着的人,而并不会给他分配任务,就是说 notify 只是让之前调用 wait 的线程有权利重新参与线程的调度)。
    • sleep() 方法可以在任何地方使用;wait() 方法则只能在同步方法或同步块中使用;
    • sleep() 是线程线程类(Thread)的方法,调用会暂停此线程指定的时间,但监控依然保持,不会释放对象锁,到时间自动恢复;wait() 是 Object 的方法,调用会放弃对象锁,进入等待队列,待调用 notify()/notifyAll() 唤醒指定的线程或者所有线程,才会进入锁池,不再次获得对象锁才会进入运行状态;
    notify 和 notifyall 的区别

    先解释两个概念。

    • 等待池:假设一个线程 A 调用了某个对象的 wait() 方法,线程 A 就会释放该对象的锁后,进入到了该对象的等待池,等待池中的线程不会去竞争该对象的锁。
    • 锁池:只有获取了对象的锁,线程才能执行对象的 synchronized 代码,对象的锁每次只有一个线程可以获得,其他线程只能在锁池中等待。

    区别:

    调用 notify 时,随机唤醒一个等待线程(由调度器决定),进入锁池,唤醒的线程享有公平竞争资源的权利。

    调用 notifyAll 方法,等待该锁的所有线程都会被唤醒,进入锁池,唤醒的所有线程公平竞争资源。

    try-catch-finally 的作用,try 里面用了 return,finally 会执行吗
    • try:写可能抛出异常的代码;
    • catch:捕获异常,处理异常;
    • finally:不管有没有出现异常,finally 代码块都会执行。用于为程序提供统一的出口,释放资源、关闭文件。

    有 return finally 中的语句也会执行。

    算法题两个

    一道滑动窗口,一道对字符串按字母出现的次数排序。

  • 相关阅读:
    gcc和Makefile,多文件编译器
    鲸鱼算法优化LSTM超参数-神经元个数-dropout-batch_size
    项目架构:husky + lint-staged + eslint - git提交前自动检查代码
    商城免费搭建之java商城 开源java电子商务Spring Cloud+Spring Boot+mybatis+MQ+VR全景+b2b2c
    110 个主流 Java 组件和框架整理,常用的都有,建议收藏!!
    numpy数组索引、数组切片、数组形状修改、数组类型修改和数组去重
    Vivado初体验LED工程
    【洛谷题解/AcWing题解/SCOI2005】P1896/AcWing1064 互不侵犯
    【Proteus仿真】【STM32单片机】电蒸锅温度控制系统
    React 中的 Solidity 和 Ethereum (Next JS):完整指南
  • 原文地址:https://blog.csdn.net/weixin_45545090/article/details/126954965