目录
前言
目标JAVA后端,23届本科生,人生第一次面试阿里大厂被HR全方面吊打,遂写博客梳理面经,恶补基础。纯为自己梳理巩固知识所用,参考的同学若发现问题请及时帮我指出,不然不止我尬住,说不定还会误导别的同学(即使没多少人看)。
一、第一个问题:面向对象三大特性
面试官简单问了一下我的项目,我坦言是临时包装的,对方说能够理解,因为应届生很难有什么很有价值的项目,就问问基础吧。这就是阿里面试官对我抛出的第一个问题,也是我人生遇到的第一个面试题。
但凡是个学过面向对象语言的人,应该都能回答出来三大特性:封装、继承和多态。
1.封装
我们在用面向对象语言写代码时就应该考虑到,为什么我们的代码要形成一个个的类,而非像C语言一样一串写下来呢?其实比起面向过程,面向对象的思想更贴合于我们的思维,举个例子,我们在使用电子器械比如洗衣机的时候,只需要操作外表的按钮就可以了,而不需要思考内部是如何帮我们洗干净衣服并甩干的,作为普通用户,我们在一般情况下更不需要拆开洗衣机的外壳,来查看内部的运作流程,这其实就是封装的思想。
回到代码层面,我们通常将一个类的属性隐藏(设置为private),将想让别人调用的方法展示(public),这样其它人在使用这个类时只能通过编写者暴露的public方法访问,无论是实现原理还是内部的属性都不会暴露出来。这样做的好处在我看来有两点,其一,调用者调用方便。在调用者眼中只有几个暴露出来的已经被封装好的方法,简洁易用;其二,被调用的类的安全性得到了一定程度的保障。方法实现的原理,内部的变量等都无法轻易被查看。
2.继承
关键字是extends,在我看来继承的存在意义就是提高代码的复用性,让代码不至于非常臃肿,当一个类的某部分比较固定时就可以将这一部分代码抽象成一个父类(或者接口),如此,当想要扩展或者这个类的功能时,就可以避免重写已有的那部分代码。
注意,虽然父类的所有属性和方法都会被继承到子类中,但子类依然无法操作父类私有的属性和方法,父辈的私有财产,即使被你继承了也不能使用。
3.多态
多态的意思是一个对象,多种状态,体现在代码中就是左父右子。这是我一直难以理解的特性,因为平时用的虽然多,但确实没能直观感受到它的优越,比如刷力扣时会经常这样声明ArrayList。
List<Integer> list = new ArrayList<>();
后来看了一些文章和视频,感觉主要有两个作用。第一比较直观的就是方便程序员啦,在new子类时左边清一色使用父类,一眼就能看出new的这些类属于哪个父类(也方便复制粘贴);第二我感觉和设计模式中的里氏代换原则有些相似,说的白话一点就是代码中父类出现的地方被其子类替换一定不会出现问题。同理,方法的参数我们可以设置为父类,这样在传参时可以根据需要直接传不同的子类就可以,而不需要每一个子类写一个对应的方法。
归根到底感觉多态也是为了提高代码可读性复用性、减少冗余、方便程序员的存在。
二、常见的数据结构和应用场景?
本来多态就没答好,这一下更把我问懵了......作为引出别的问题的问题应该挺好的,先不谈Java集合(容器)来聊聊。
2.1数组和链表
太常见了,可以说是很多其它复杂数据结构的基石,其实只聊这俩还真没啥好聊的,硬要说可以比较一下两者的区别,比如插入删除查找修改的效率比较之类的,深入一点还可以聊聊ArrayList扩容机制。
2.2栈
应用比较特化的一种数据结构,最常见的就是函数调用了,实际一点就是各种撤销回退操作。(leetcode有双栈实现队列的题目)
2.3队列(重点)
重头大哥,能聊的地方太多了。实现方式有顺序(数组)和链式(链表),写两个可能会被深挖的应用场景。
2.3.1线程池的阻塞队列
可以直接聊ThreadPoolExector,七大参数之一就是阻塞队列,自定义线程池中阻塞队列就相当于银行的候客区,候客区没满的时候新线程会在阻塞队列等候,若阻塞队列满了就会提高核心线程数(可以理解为并发量),若核心线程数达到了最大,阻塞队列也满了就会启用拒绝策略。
顺便复习一下七大参数:最初的核心线程数、最大核心线程数、阻塞队列、线程等待时间、等待时间的单位、线程的创建工厂、拒绝策略。
再聊一下四大拒绝策略:
AbortPolicy:直接抛出异常拒绝处理。
CallerRunsPolicy:调用自己的线程运行任务,调用者自己处理。
DiscardPolicy:不处理,直接扔掉,不提示。
DiscardOldestPolicy:丢弃最早未处理的任务请求。
2.3.2消息队列(RabbitMQ为例)
分布式可以问到,我自己项目上写的是RabbitMQ(虽然还没有实操过,只能大概说一下用处)。本人很菜不能结合具体业务,只能参考advanced-java随便聊聊。
消息队列三大用处:解耦、异步、削峰。
解耦的意思就是,若A服务需要给很多其它服务发送消息,没有消息队列的话只能由它自己处理消息相关的业务(比如何时发送,发给谁),消息队列可以把这个功能解耦出来,A服务自己就不用写业务无关的处理消息发送的代码了。‘
异步,按照我的理解就是,A服务若调用B服务,B服务尚未处理完成的时候,A服务可以去做别的事情,而不用一直阻塞等待B服务的结果。比如用户调用了A服务,A服务可以把处理业务的消息扔到消息队列中,然后继续响应,而不需要等待处理业务的消息全部完成才能响应。
削峰,顾名思义是减少同时打到数据库的请求,就跟大坝拦洪水一样,MQ在这里就起到了缓冲区的作用,请求虽然多,但可以用较慢的速度发送给数据库处理,在并发量高的时候能一定程度上防止数据库轻易挂掉。
2.4树
非线性的数据结构,重点关注一下二叉搜索树(改良后的红黑树可以扩展到HashMap)、B+树(数据库索引相关),算法题的树自然也很重要,但本人不想卷大厂了啊哈哈哈。如果要刷力扣,把树刷明白非常有利于你的能力提升。红黑树和B+树直接放到后面讲吧,这里不扩展太多了。
2.5堆
排序问题可能会遇到大根堆小根堆,非算法问题的堆就不得不提到JVM。JVM中的堆是存储对象实例和数组的,同时垃圾回收也是主要处理堆上的资源,JVM的堆和方法区一样被线程共享,但注意方法区只是一个定义或者规范,存储的是已被虚拟机加载的类信息、静态变量、被编译器编译后的代码等。在JVM详细讲。
总结
第一次写博客,不管在内容还是排版上可能都有问题或欠缺,纯粹是为了自己梳理知识点和方便复习,如有问题欢迎指出