• 正文
  • 相关推荐
申请入驻 产业图谱

小米汽车薪资曝光了!

03/06 13:10
1736
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

图解学习网站:https://xiaolincoding.com

大家好,我是小林。

雷总的小米 su7 ultra 一发布,直接卖爆了,2 小时就完成了全年的销售目标,50 多万的价格就有 1500+马力,这马力可是千万级跑车的配置了,1.98 秒破百,谁看了不心动,要不是狠自己钱包太小,我都想下手了。。

于是我就好奇,小米汽车的薪资待遇如何?

正好,我在「OfferShow」那里看到了「小米汽车-校招薪资爆料」汇总数据,分享给大家看看。

城市 岗位 校招薪资爆料
北京 自动驾驶 39k*15
北京 软开 24k*15
北京 测试 23k*15
北京 软开 22k*15
上海 电池系统测试 18k*15
北京 服务端开发工程师 22*15+0.8*12
南京 机械岗 30w
上海 动力集成测试 23k*15
上海 算法 23k*15
北京 产品经理 16k*15
南京 热管理 18.5k*16

关注我的同学们大部分都是程序员,我们就专注看软开的校招薪资,小米年终奖是 3 个月,所以是 15 薪资计算:

    22k x 15 = 33w,北京24k x 15 = 36w,北京

软开的年包在 30-35w,是属于大厂范畴的薪资了,虽然和互联网一线大厂会有一点点差距,但是整体还是不错的。

那小米汽车软开岗的面试难得如何呢?

一起瞧瞧小米汽车Java软开岗面经,这次是二面的面经了,问了Spring、MySQL、设计模式、网络协议、分布式事务这些内容,最后还是一样有一个算法题。

小米汽车二面

SpringBoot的启动流程介绍一下

SpringBoot是一个服务Spring框架的框架,能够简化配置文件,快速构建web应用,内置tomcat,无需打包部署,直接运行。 当我们启动一个SpringBoot应用的时候,都会用到如下的启动类:

@SpringBootApplication
public class Application {
     public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
     }

只要加上@SpringBootApplication,然后执行run()方法,就可以启动一个应用程序,启动的流程如下:

    首先从main找到run()方法,在执行run()方法之前new一个SpringApplication对象进入run()方法,创建应用监听器SpringApplicationRunListeners开始监听然后加载SpringBoot配置环境(ConfigurableEnvironment),然后把配置环境(Environment)加入监听对象中然后加载应用上下文(ConfigurableApplicationContext),当做run方法的返回对象最后创建Spring容器,refreshContext(context),实现starter自动化配置和bean的实例化等工作。

Spring IOC、 AOP解决了什么问题?没有IOC之前怎么做?

Spring IOC 解决的问题,主要是解耦对象之间的依赖关系。在传统的编程中,对象之间的依赖关系通常是在代码中硬编码实现的,这使得代码的可维护性和可扩展性变差。IOC 通过将对象的创建和依赖关系的管理交给 Spring 容器,实现了对象之间的解耦。比如,一个业务逻辑类可能依赖于多个数据访问类,使用 IOC 后,业务逻辑类不需要知道具体的数据访问类是如何创建和获取的,只需要声明它的依赖关系,由 Spring 容器来负责注入。

也可以提高提高代码的可维护性和可测试性。当依赖关系被集中管理在 Spring 容器中时,如果需要更换某个依赖对象,只需要在配置文件或注解中进行修改,而不需要在大量的业务代码中进行查找和修改。在进行单元测试时,也可以很方便地通过 IOC 容器注入模拟的依赖对象,提高了测试的灵活性和可操作性。

在没有 IOC 框架之前,开发人员通常需要在代码中手动创建对象及其依赖对象。例如,在一个 Java 项目中,如果一个 UserService 类依赖于 UserDao 类,那么在 UserService 类中需要通过 new 关键字来创建 UserDao 的实例,如下所示:

public class UserService {
    private UserDao userDao = new UserDao();

    public void doSomething() {
        // 使用userDao进行业务操作
        userDao.saveUser();
    }
}

这样的代码存在着严重的耦合问题,如果需要更换 UserDao 的实现类或者对其进行一些初始化配置,就需要在 UserService 类中进行修改,随着项目规模的增大,维护成本会越来越高。

Spring AOP 解决的问题,主要是可以分离业务逻辑和横切关注点,提高代码的复用性。在企业级应用开发中,往往存在一些横切关注点,如日志记录、事务管理、权限控制等,这些功能会分散在各个业务逻辑代码中,导致代码的可读性和可维护性变差。AOP 允许将这些横切关注点从业务逻辑中分离出来,以切面的形式进行统一管理和实现。通过 AOP,可以将通用的横切逻辑封装在切面中,然后在多个业务逻辑中进行复用。例如,对于日志记录功能,可以创建一个日志切面,在多个不同的业务方法上都可以应用这个切面来记录日志,而不需要在每个业务方法中都编写重复的日志记录代码。

在没有 AOP 之前,要实现日志记录、事务管理等横切功能,通常需要在每个需要这些功能的方法中手动编写相关代码。以日志记录为例,可能需要在每个业务方法的开始和结束位置都添加日志记录代码,如下所示:

public class UserService {
    public void doSomething() {
        // 记录方法开始日志
        System.out.println("进入doSomething方法");
        // 业务逻辑代码
        // 记录方法结束日志
        System.out.println("离开doSomething方法");
    }
}

这样不仅会导致代码大量重复,而且当需要修改日志记录的格式或策略时,需要在多个地方进行修改,容易出现遗漏和不一致的情况。

自己项目中有用到AOP吗?

有,主要用在了日志记录功能,避免在每个业务方法里重复编写日志记录代码。

看你也会golang,golang和java的区别?

Golang是由Google设计的静态类型、编译型语言,注重简洁和高效并发。而Java是一种面向对象的语言,拥有成熟的生态系统和跨平台能力,依赖JVM运行。

在语法方面,Golang更简洁,没有类和继承,使用接口和结构体,而Java是严格的面向对象,需要更多的样板代码。并发模型方面,Golang有goroutine和channel,轻量级且易于使用;Java使用线程和线程池,相对重量级,但通过并发包提供丰富的工具。

性能方面,Golang作为编译型语言,通常启动更快,内存占用更低;Java虽然JIT优化后性能强劲,但启动和内存开销较大。

内存管理方面,两者都有垃圾回收,但Golang的GC更注重低延迟,Java的GC调优更复杂但灵活。 错误处理机制也不同,Golang采用显式错误返回,而Java使用异常机制。这可能影响代码的可读性和错误处理流程。

生态系统方面,Java有大量成熟的框架和库,适合企业级应用;Golang的生态在云原生和微服务领域发展迅速,但相对年轻。

应用场景方面,Golang适合高并发、分布式系统,云基础设施,而Java在企业应用、Android开发、大数据处理等方面占优。

MySQL建表的时候有哪些优化手段?

合理选择数据类型:根据实际存储的数据范围选择合适的数值类型,避免使用过大的数据类型造成空间浪费。例如,如果存储的整数范围在 0 - 255 之间,使用 TINYINT 即可,而不是 INT。对于固定长度的字符串,使用 CHAR 类型;对于可变长度的字符串,使用 VARCHAR 类型。同时,根据实际存储的字符串长度合理设置字段长度。

控制字段数量:避免创建过多不必要的字段,过多的字段会增加表的复杂度和存储开销,同时也会影响查询性能。可以将一些不常用的字段单独存储在其他表中,通过关联查询获取数据。

反范式化设计:可以适当引入一些数据冗余,将相关联的数据存储在同一个表中,减少表之间的关联查询。需要在范式化和反范式化之间找到一个平衡点。

合理创建索引:在经常用于 WHERE 子句、JOIN 子句和 ORDER BY 子句的字段上创建索引,以提高查询效率。避免在重复值较多的字段上创建索引,因为这样的索引效果不佳。例如,在一个性别字段上创建索引可能没有太大意义。当然,过多的索引会增加存储开销和写操作的性能开销,因此要根据实际查询需求合理创建索引,避免创建过多不必要的索引。

MySQL索引怎么建?

主键索引是一种特殊的唯一索引,它不允许有空值。通常在创建表时指定主键,MySQL 会自动创建主键索引。创建方式:

-- 在创建表时创建主键索引
CREATE TABLE table_name (
    column1 datatype PRIMARY KEY,
    column2 datatype,
    ...
);

-- 使用 ALTER TABLE 语句创建主键索引
ALTER TABLE table_name ADD PRIMARY KEY (column1, column2, ...);

创建普通索引的方式:

-- 在创建表时创建普通索引
CREATE TABLE table_name (
    column1 datatype,
    column2 datatype,
    ...
    INDEX index_name (column1, column2, ...)
);

-- 在已存在的表上创建普通索引
CREATE INDEX index_name ON table_name (column1, column2, ...);

-- 使用 ALTER TABLE 语句创建普通索引
ALTER TABLE table_name ADD INDEX index_name (column1, column2, ...);

创建唯一索引的方式,唯一索引要求索引列的值必须唯一,但允许有空值。

-- 在创建表时创建唯一索引
CREATE TABLE table_name (
    column1 datatype,
    column2 datatype,
    ...
    UNIQUE INDEX index_name (column1, column2, ...)
);

-- 在已存在的表上创建唯一索引
CREATE UNIQUE INDEX index_name ON table_name (column1, column2, ...);

-- 使用 ALTER TABLE 语句创建唯一索引
ALTER TABLE table_name ADD UNIQUE INDEX index_name (column1, column2, ...);

MySQL中的锁机制你知道哪些?

在 MySQL 里,根据加锁的范围,可以分为全局锁、表级锁和行锁三类。

锁类型 加锁范围 加锁语句 具体说明
全局锁 整个数据库 flush tables with read lock 执行该语句后数据库处于只读状态,其他线程的增删改或表结构修改操作都会阻塞
表级锁 lock tables 对表加表锁,会限制别的线程的读写,也会限制本线程接下来的读写操作
表级锁(元数据锁) 自动加锁 对表进行 CRUD 操作时加 MDL 读锁;对表做结构变更操作时加 MDL 写锁
表级锁(意向锁) 执行插入、更新、删除操作时自动加锁 执行插入、更新、删除操作时,先对表加上「意向独占锁」,然后对该记录加独占锁
行级锁(记录锁) 表中的一条记录 InnoDB 引擎自动加锁 有 S 锁(共享锁)和 X 锁(排他锁)之分,满足读写互斥,写写互斥
行级锁(间隙锁) 表中的记录间隙 InnoDB 引擎自动加锁,只存在于可重复读隔离级别 用于解决可重复读隔离级别下幻读的现象
行级锁(Next-Key Lock) 表中的一个范围及记录本身 InnoDB 引擎自动加锁 是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身

全局锁:通过flush tables with read lock 语句会将整个数据库就处于只读状态了,这时其他线程执行以下操作,增删改或者表结构修改都会阻塞。全局锁主要应用于做

全库逻辑备份,这样在备份数据库期间,不会因为数据或表结构的更新,而出现备份文件的数据与预期的不一样。

表级锁:MySQL 里面表级别的锁有这几种:

表锁:通过lock tables 语句可以对表加表锁,表锁除了会限制别的线程的读写外,也会限制本线程接下来的读写操作。元数据锁:当我们对数据库表进行操作时,会自动给这个表加上 MDL,对一张表进行 CRUD 操作时,加的是 MDL 读锁;对一张表做结构变更操作的时候,加的是 MDL 写锁;MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更。意向锁:当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。

意向锁的目的是为了快速判断表里是否有记录被加锁

行级锁:InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁。

    • 记录锁,锁住的是一条记录。而且记录锁是有 S 锁和 X 锁之分的,满足读写互斥,写写互斥间隙锁,只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的现象。Next-Key Lock 称为临键锁,是 Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。

最熟悉的设计模式有哪些?

单例模式、工厂模式、策略模式、装饰器模式这些。

    单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。工厂模式:定义一个创建对象的接口,让子类决定实例化哪个类。工厂方法使一个类的实例化延迟到其子类。策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。该模式使得算法可以独立于使用它的客户而变化。装饰器模式:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰器模式相比生成子类更为灵活。

代理模式讲一下

代理模式为其他对象提供一种代理以控制对这个对象的访问。

在代理模式中,代理对象与目标对象实现相同的接口,客户端对目标对象的访问实际上是通过代理对象来进行的,代理对象可以在调用目标对象的方法前后进行一些额外的操作,如权限验证、缓存处理、日志记录等。

代理模式实现有这些:

    • 静态代理:手动编写代理类,需实现与目标对象相同的接口。优点是简单直观,缺点是每个目标类需对应一个代理类,代码冗余。动态代码:运行时动态生成代理类,无需手动编写。JDK动态代理是基于接口,使用

java.lang.reflect.Proxy

    ,CGLIB动态代理:基于继承,可代理无接口的类。

聊聊网络,交换机和路由器的区别?

交换机:主要工作在数据链路层。它通过学习连接到其端口的设备的 MAC 地址,构建 MAC 地址表。当接收到数据帧时,根据数据帧中的目的 MAC 地址在 MAC 地址表中查找对应的端口,然后将数据帧从该端口转发出去,实现本地网络内设备之间的数据交换。

路由器:主要工作在网络层。它依据 IP 地址进行数据转发,路由器中保存着路由表,路由表包含了网络地址与下一跳地址等信息。当路由器接收到数据包时,会根据数据包中的目的 IP 地址,在路由表中查找最佳路径,然后将数据包沿着该路径转发到下一个路由器或目标设备。

现在我们视频聊天,涉及到的网络协议是什么?

对于实时性要求极高的视频和音频数据,会优先使用 UDP 进行传输,并通过一些额外的技术手段来弥补 UDP 的不可靠性;而对于控制信息和一些对可靠性要求较高的数据,则会使用 TCP 来传输,以确保视频聊天的稳定性和正确性。

分布式事务的解决方案你知道哪些?

方案 一致性 性能 复杂度 适用场景
2PC 强一致性 传统数据库、XA协议
3PC 强一致性 中低 需减少阻塞的强一致场景
TCC 最终一致性 高并发业务(支付、库存)
Saga 最终一致性 长事务、跨服务流程
消息队列 最终一致性 事件驱动架构
本地消息表 最终一致性 异步通知(订单-积分)
    两阶段提交协议(2PC):为准备阶段和提交阶段。准备阶段,协调者向参与者发送准备请求,参与者执行事务操作并反馈结果。若所有参与者准备就绪,协调者在提交阶段发送提交请求,参与者执行提交;否则发送回滚请求。实现简单,能保证事务强一致性。存在单点故障,协调者故障会影响事务流程;性能低,多次消息交互增加延迟;资源锁导致资源长时间占用,降低并发性能。适用于对数据一致性要求高、并发度低的场景,如金融系统转账业务。
    三阶段提交协议(3PC):在 2PC 基础上,将准备阶段拆分为询问阶段和准备阶段,形成询问、准备和提交三个阶段。询问阶段协调者询问参与者能否执行事务,后续阶段与 2PC 类似。降低参与者阻塞时间,提高并发性能,引入超时机制一定程度解决单点故障问题。无法完全避免数据不一致,极端网络情况下可能出现部分提交部分回滚。用于对并发性能有要求、对数据一致性要求相对较低的场景。
    TCC:将业务操作拆分为 Try、Confirm、Cancel 三个阶段。Try 阶段预留业务资源,Confirm 阶段确认资源完成业务操作,Cancel 阶段在失败时释放资源回滚操作。可根据业务场景定制开发,性能较高,减少资源占用时间。开发成本高,需实现三个方法,要处理异常和补偿逻辑,实现复杂度大。适用于对性能要求高、业务逻辑复杂的场景,如电商系统订单处理、库存管理。
    Saga:将长事务拆分为多个短事务,每个短事务有对应的补偿事务。某个短事务失败,按相反顺序执行补偿事务回滚系统状态。性能较高,短事务可并行执行减少时间,对业务侵入性小,只需实现补偿事务。只能保证最终一致性,部分补偿事务失败可能导致系统状态不一致。适用于业务流程长、对数据一致性要求为最终一致性的场景,如旅游系统订单、航班、酒店预订。
    可靠消息最终一致性方案:基于消息队列,业务系统执行本地事务时将业务操作封装成消息发至消息队列,下游系统消费消息并执行操作,失败则消息队列重试。实现简单,对业务代码修改小,系统耦合度低,能保证数据最终一致性。消息队列可靠性和性能影响大,可能出现消息丢失或延迟,需处理消息幂等性。适用于对数据一致性要求为最终一致性、系统耦合度低的场景,如电商订单支付、库存扣减。
    本地消息表:业务与消息存储在同一个数据库,利用本地事务保证一致性,后台任务轮询消息表,通过MQ通知下游服务,下游服务消费成功后确认消息,失败则重试。简单可靠,无外部依赖。消息可能重复消费,需幂等设计。适用场景是异步最终一致性(如订单创建后通知积分服务)。

阿里的seata框架了解过吗?

Seata 是开源分布式事务解决方案,支持多种模式:

AT模式:是 Seata 默认的模式,基于支持本地 ACID 事务的关系型数据库。在 AT 模式下,Seata 会自动生成回滚日志,在业务 SQL 执行前后分别记录数据的快照。当全局事务需要回滚时,根据回滚日志将数据恢复到事务开始前的状态。

TCC模式:需要开发者手动编写 Try、Confirm 和 Cancel 三个方法。Try 方法用于对业务资源进行预留,Confirm 方法用于确认资源并完成业务操作,Cancel 方法用于在业务执行失败时释放预留的资源。

SAGA 模式:将一个长事务拆分为多个短事务,每个短事务都有一个对应的补偿事务。当某个短事务执行失败时,会按照相反的顺序执行之前所有短事务的补偿事务,将系统状态回滚到初始状态。

算法

    组合总和
小米

小米

小米科技有限责任公司(Xiaomi Corporation)成立于2010年3月3日,总部位于北京市海淀区安宁庄路小米科技园,创始人雷军 ,是一家主要从事智能手机、智能汽车、芯片、 物联网和生活消费产品研发和销售业务,提供互联网服务,以及从事投资业务的中国投资控股公司。也是消费级机器人及智能硬件供应商,产品包括CyberOne、扫地机器人。

小米科技有限责任公司(Xiaomi Corporation)成立于2010年3月3日,总部位于北京市海淀区安宁庄路小米科技园,创始人雷军 ,是一家主要从事智能手机、智能汽车、芯片、 物联网和生活消费产品研发和销售业务,提供互联网服务,以及从事投资业务的中国投资控股公司。也是消费级机器人及智能硬件供应商,产品包括CyberOne、扫地机器人。收起

查看更多

相关推荐