2小时30分钟|阿里Java一面真题+详解

作者:不搭。

来源:牛客网

楼主7-18号投的内推,等了8天之后,昨天中午接到了杭州打来的电话,约了晚上8点视频一面,然后发来了视频地址和代码测评的地址

面了两个半小时,都赶上人家三面了

楼主双非学校,本科软件工程专业,面试官问了本科学的什么课程,楼主说了说数据结构,计算机组成原理,计算机网络,操作系统,数据库概论还有软件工程。

项目,面试官让展示一下数据库表之间的关系

PART/01

基本数据类型在内存中的分布,每个类型是几个字节,整形怎么放浮点型怎么放(考组成原理,IEEE754)

  • byte 1字节
  • short 2字节
  • int 4字节
  • long 8字节
  • char 2字节(C语言中是1字节)可以存储一个汉字
  • float 4字节
  • double 8字节
  • boolean false/true(理论上占用1bit,1/8字节,实际处理按1byte处理)

抽象类接口区别和相同点

PART/01

  • 接口和抽象类都不能实例化
  • 抽象类可以有构造方法,接口中不能有构造方法。
  • 抽象类中可以有普通成员变量,接口中没有普通成员变量
  • 抽象类中可以包含非抽象的普通方法,接口中的可以有非抽象方法,比如deafult方法
  • 抽象类中的抽象方法的访问类型可以是public,protected,但接口中的抽象方法只能是public类型的,并且默认即为public abstract类型。
  • 抽象类中可以包含静态方法,接口中不能包含静态方法
  • 抽象类和接口中都可以包含静态成员变量,抽象类中的静态成员变量的访问类型可以任意,但接口中定义的变量只能是public static final类型,并且默认即为public static final类型。
  • 一个类可以实现多个接口,但只能继承一个抽象类。

抽象类里面的方法子类必须全部实现吗,可不可以有不实现的方法,接口呢?

PART/01

  • 抽象类不一定,子类只会实现父类里的抽象方法,抽象类里可以有抽象方法也可以非抽象方法,子类不需要再去实现非抽象方法,如果子类一定要再次实现的话就叫做覆盖了
  • 接口里的方法必须全部实现,因为接口里的方法都是抽象的,默认都是public abstract

抽象类的作用是什么,什么时候用到抽象类

PART/01

封装(隐藏对象的属性和实现细节,仅对外公开接口)

继承 JAVA单继承,接口多实现

多态:多态跟返回值没关系,跟参数个数,参数类型,参数顺序有关系(只跟方法签名有关系)

进程线程的区别:进程是资源分配的基本单位,线程是处理器调度的基本单位

线程池(看这里),线程池的四个构造函数,参数,线程池的好处,以及线程池的继承体系

  • ThreadPoolExecutor继承了AbstractExecutorService,
  • AbstractExecutorService是一个抽象类,它实现了ExecutorService接口。
  • ExecutorService又是继承了Executor接口

参数

PART/01

  • corePoolSize, 核心池大小
  • maximumPoolSize, 线程池最大线程数
  • keepAliveTime, 表示线程没有任务执行时最多保持多久时间会终止
  • TimeUnit 参数keepAliveTime的时间单位,有7种取值
  • BlockingQueue,一个用来存储等待执行的任务的阻塞队列,
  • ThreadFactory, 线程工厂,主要用来创建线程
  • RejectedExecutionHandler 表示当拒绝处理任务时的策略

多线程并发,线程不安全会导致什么问题?怎么解决并发的问题(锁机制)

PART/01

  • Synchornized
  • Lock
  • ReentrantLock
  • volatile

HashMap的链表成环原因(看这里)

Spring IOC(控制反转,将对象交给容器管理)

AOP里面的名称(通知,连接点,切入点,代理,目标,织入)

bean 工厂中bean 的生命周期/9项

当您在bean 工厂容器中加载bean时,它经过各种步骤,从它的实例化直到它的销毁。下图显示了bean 工厂容器中bean的生命周期。

2小时30分钟|阿里Java一面真题+详解

在bean工厂中bean的生命周期期间执行了以下步骤:

1.实例化: 此步骤中,bean 工厂容器从XML 配置文件中提供的bean 定义实例化bean.

2.填充属性:在此步骤中,bean 工厂容器按照XML配置文件中所指定的通过DI填充所有bean 属性。

3.设置bean 名称: 在此步骤中,在创建bean 的bean工厂中设置bean 的名称。这是通过将bean 的ID 传递给BeanNameAware 接口提供的setBeanName() 方法来完成的。

4.设置bean 工厂: 在此步骤中,为bean 提供对管理它的bean工厂的引用。这是使用BeanFactoryAware 接口的setBeanFactory() 方法来完成的。

5.预初始化: 在此步骤中,您执行在初始化bean 之前需要完成的任务。这是通过在bean类中实现BeanPostProcessor 接口并定义其postProcessBeforeInitialization 方法来完成的。

6.初始化bean: 在此步骤中,您执行某些类型的初始化任务,然后bean 才可供使用。这些任务包括打开文件、打开网络或数据库连接以及分配内存。这是通过在bean 类中实现InitiallzingBean接口并定义其afterPropertiesSet ()方法来完成的。

7.初始化后: 在此步骤中,您执行在初始化bean之后需要完成的任务。这是通过在bean 类中实现BeanPostProcessor 接口并定义其postProcessAfterInitialization() 方法来完成的。

8.bean 可供使用: 此时,bean 已准各就绪,可供应用程序使用,将留在bean工厂中,直到应用程序不再需要它。

9.销毁bean: 在此步骤中,将销毁bean。如果bean实现DisposableBean 接口,将调用destroy () 方法。然而,如果为bean声明了自定义destroy方法,将调用该方法。

依赖注入的三种方式/设值注入/构造函数注入/接口注入外加集合注入可以注入哪些集合

集合注入可以注入哪些集合(List,Map,Set,面试官问还有没有了,楼主就注入过这三个,实话实说,不知道还有没有就不说)

什么是循环依赖,Spring是怎样解决循环依赖的(看这里),为了避免循环依赖最好用什么注入(接口注入)

构造函数注入能不能和设值注入一块用?不能(看这里,牛客原题),有优先级问题。

使用构造函数依赖注入时,Spring保证一个对象所有依赖的对象先实例化后,才实例化这个对象。使用set方法依赖注入时,Spring首先实例化对象,然后才实例化所有依赖的对象。

当设值注入与构造注入同时存在时,先执行设值注入?再执行构造注入:构造注入自动失效。。。。有争议

事务属性ACID(acid,酸)

事务具有ACID(四个单词的首字母)属性:

PART/01

1) 原子性(Atomicity):事务包含的操作应该作为一个单元执行,要么都成功、要么都失败。

2) 一致性(Consistency):事务完成后,数据应该处于一致的状态。例如,如果转账,则要么两个账户都更新,要么,失败的情况下,两个账户都不更新。

3) 隔离性(Isolation):事务之间应该独立,不相互影响,并发事务的操作应该隔离开,如如果一个事务在修改数据,一个在读取相同的数据,则应该保证在修改前或修改后读取数据,而不可以在修改过程中读取。

4) 持久性(Durability):事务对数据的修改在系统中永久有效,会保持下去,如对余额的修改会持久在数据库中。

事务并发会导致的问题

PART/01

1) 脏读:如一个事务A正在更新数据,另一个事务B尝试读取同一个数据,B在更新期间读取了数据,但是事务A可能最后回滚了事务,导致事务B读取的数据不准确,视为脏读。

2) 更新丢失:两个事务同时更新同一个数据,导致其中一个的更新丢失,如你修改账户,减少了100块,另一个事务也修改你的账户,减少100块,结果就是你最后发现账户少了200块。

3) 不可重复读:如一个事务在操作期间两次读取同一批数据,结果发现数据不一样,说明另一个事务在此期间更新了数据,视为不可重复读。

4) 幻象读:如一个事务操作期间两次读取同一个表的数据,结果发现第二次读取的数据多了几条,说明在此期间有其他事务插入数据到该表,跟幻觉一样,视为幻象读。

什么是幻读(看上面)

事务的隔离级别

PART/01

1)未提交读取:设置值为1,说明当一个事务修改数据的时候,另一个事务可以读取数据,这样会导致脏读、更新丢失、不可重复读和幻象读等问题,所以是最不安全的级别,不太常用。

2)提交读取:设置值为2:说明当一个事务修改数据的时候,另一个事务必须等待修改完成,才能读取数据,这样可以防止脏读,但依然可能导致更新丢失、不可重复读和幻象读等问题。是比较常用的一种隔离级别。

3)重复读:设置值为4:比提交读取安全一些,因为限制一个事务修改数据时,另一个事务不能读取该数据,同时,限制一个事务读取数据时,其他事务不能修改该数据,从而防止脏读、更新丢失和不可重复读的问题,但依然可能出现幻象读的问题。

4)序列化:设置值为8:,最安全的隔离级别,当一个事务在操作数据时,其他事务不能操作该数据,包括不能插入,从而预防各种并发问题。相当于一个事务用完该数据,另一个数据才能用。

2小时30分钟|阿里Java一面真题+详解

JVM的内存分布以及每个里面都有什么

PART/01

程序计数器(指向下一条需要选取的字节码指令),堆(成员变量,对象),方法区(常量),虚拟机栈(局部变量,方法),本地方法栈,问了每个都是存什么东西

对象都在堆里吗?(不,由于TLAB和逃逸技术的发展,或者在jvm开启在栈上分配时某些特殊的对象可以存放在栈上)

垃圾收集器都收集那些地方的东西(Eden区,survior区,老年代)

垃圾收集算法(四种,标记清除,标记整理,复制,分代收集)

怎样判断哪些是垃圾(可达性分析)

什么对象可以作为根节点:

PART/01

虚拟机栈中引用的对象

方法区中静态属性引用的对象

方法区中常量引用的对象

本地方法栈中JNI引用的对象

异常try-catch-finally中,try和finally中都有return,怎么返回

结论:

1、不管有木有出现异常,finally块中代码都会执行;

2、当try和catch中有return时,finally仍然会执行;

3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,不管finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是在finally执行前确定的;

4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。

举例:

情况1:

try {

} catch () {

} finally {

} return;

显然程序按顺序执行。

情况2:

try {

return;

} catch () {

} finally {

} return;

程序执行try块中return之前(包括return语句中的表达式运算)代码;再执行finally块,最后执行try中return;finally块之后的语句return,因为程序在try中已经return所以不再执行。

情况3:

try {

} catch () {

return;

} finally {

} return;

程序先执行try,如果遇到异常执行catch块,

有异常:则执行catch中return之前(包括return语句中的表达式运算)代码,再执行finally语句中全部代码,最后执行catch块中return. finally之后的代码不再执行。无异常:执行完try再finally再return.

情况4:

try {

return;

} catch () {

} finally {

return;

}

程序执行try块中return之前(包括return语句中的表达式运算)代码;再执行finally块,因为finally块中有return所以提前退出。

情况5:

try {

} catch () {

return;

} finally {

return;

}

程序执行catch块中return之前(包括return语句中的表达式运算)代码;再执行finally块,因为finally块中有return所以提前退出。

情况6:

try {

return;

} catch () {

return;

} finally {

return;

}

程序执行try块中return之前(包括return语句中的表达式运算)代码;有异常:执行catch块中return之前(包括return语句中的表达式运算)代码;则再执行finally块,因为finally块中有return所以提前退出。无异常:则再执行finally块,因为finally块中有return所以提前退出。

最终结论:

任何执行try 或者catch中的return语句之前,如果finally存在的话,都会先执行finally语句。如果finally中有return语句,那么程序就return了,所以finally中的return是一定会被return的,编译器把finally中的return实现为一个warning。

问了数据结构有哪些排序算法(说了冒泡,快排和选择排序,平时用的比较多),没让写

问了二叉树,翻转二叉树(不会),给他讲了AVL旋转

代码题:

PART/01

1.有N阶台阶,我们可以用两种爬发,一次一步或者两步,只能进不能退,算算有多少种爬法。

考察点:

a.递归;

b.扩展问题:1. 如果每次可以选择一次走一步到一次走M步,程序应该怎么改?

2.如何提升递归速度?(设置缓存变量例如字典,将递归中计算过的值保存下来)

2、找零钱问题:假设只有 1 分、 2 分、五分、 1 角、二角、 五角、 1元的硬币。在超市结账时,

如果需要找零钱, 收银员希望将最少的硬币数找给顾客。那么,给定需要找的零钱数目,

如何求得最少的硬币数呢

public class Main { static int[] arr = {1, 2, 5, 10, 20, 50, 100}; public int f(int N) { int m = N; int c = 0; int a = 0; int count = 0; for (int i = arr.length - 1; i >= 0; i--) {

a = m / arr[i]; c = m % (arr[i]); m = c; count = count + a; } return count; } public static void main(String[] args) {

Main m = new Main(); System.out.println(m.f(188)); }

}

3、小明中午路过一家公共停车场,出于程序员的职业习惯,他很想知道这个停车场上午的最大化利用率有多少。

经与门卫大叔沟通,他获得了该停车场上午车辆入场时间与出场时间的记录表(数据格式参考样例输入),

你能通过拿到的数据写一个函数快速的帮小明算出这家停车场,上午最多的时候同时停放了多少辆车吗?

要求时间复杂度不高于:O(n)*lgN

注意事项:

a、为方便起见,简化计算,驶入时间和开出时间以整点记录,如9点,10点。

b、如停车记录中入场时间晚于出场时间,该停车记录视为无效,如7,3

c、假定如果有多辆车同时出入场,出场车辆优先。

样例输入:

8,9;4,6;3,7;6,8 (车辆以分号分隔,车辆入场和出场时间以逗号分隔)

样例输出:

2

相关文章