2021-03-16面试

今天面试的企业大约400人左右,条件都挺好,就是位置偏了点,交通只有公交,但提供住宿。

下面是一些我遇到的问题,有不会的也有答上来但理解不透彻的。

1.值传递与引用传递的区别
值传递:在方法调用时,传递的参数是按值的拷贝传递,也就是说传递后就互不相关了。
引用传递:传递的参数是按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。

2.重载与重写有什么区别
这两种是对多态性的不同体现,
重载(Overloading)体现编译的多态,同一个类的不同方法中,参数必须不同,可以是类型,也可以是顺序,但不规定返回值类型必须一样,可以有不同的权限修饰符,方法名必须一样,称方法与方法之间构成重载,可以抛出任意大小的异常。
重写(Overriding)体现运行时多态。重写必须发生在子父类之间,且只能是子类对父类的方法进行重写,参数列表必须和父类的一样,返回值类型需一致,权限修饰符子类需大于或等于父类方法权限修饰,子类抛的异常需不能大于父类抛出异常。

3.java里集合类有哪些
1)、List列表:有序的,可重复的;
2)、Queue队列:有序,可重复的;
3)、Set集合:不可重复;
4)、Map映射:无序,键唯一,值不唯一。
在这里插入图片描述
详细了解推荐:https://blog.csdn.net/qq_29224201/article/details/103029477

4.arraylist与linkedlist区别以及不同应用场景
arraylist与linkedlist的差别主要由于Array和LinkedList数据结构的不同。ArrayList是基于数组实现的,LinkedList是基于双链表实现的。另外LinkedList类不仅是List接口的实现类,可以根据索引来随机访问集合中的元素,除此之外,LinkedList还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双向队列,因此LinkedList可以作为双向队列 ,栈和List集合使用,功能强大。
因为Array是基于索引(index)的数据结构,它使用索引在数组中搜索和读取数据是很快的,可以直接返回数组中index位置的元素,因此在随机访问集合元素上有较好的性能。Array获取数据的时间复杂度是O(1),但是要插入、删除数据却是开销很大的,因为这需要移动数组中插入位置之后的的所有元素。
相对于ArrayList,LinkedList的随机访问集合元素时性能较差,因为需要在双向列表中找到要index的位置,再返回;但在插入,删除操作时更快的。因为LinkedList不像ArrayList一样,不需要改变数组的大小,也不需要在数组装满的时候要将所有的数据重新装入一个新的数组,这是ArrayList最坏的一种情况,时间复杂度是O(n),而LinkedList中插入或删除的时间复杂度仅为O(1)。ArrayList在插入数据时还需要更新索引(除了插入数组的尾部)。

使用场景:
(1)如果应用程序对数据有较多的随机访问,ArrayList对象要优于LinkedList对象;
( 2 ) 如果应用程序有更多的插入或者删除操作,较少的随机访问,LinkedList对象要优于ArrayList对象;
(3)不过ArrayList的插入,删除操作也不一定比LinkedList慢,如果在List靠近末尾的地方插入,那么ArrayList只需要移动较少的数据,而LinkedList则需要一直查找到列表尾部,反而耗费较多时间,这时ArrayList就比LinkedList要快。

更多学习可以去这看看:https://blog.csdn.net/followMyInclinations/article/details/51347292

5.java线程池有几种?谈谈如何保证多个线程运行时的安全?
1)、newCachedThreadPool
创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
2)、newFixedThreadPool
创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。
3)、newSingleThreadExecutor
创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。如果这个线程异常结束,会有另一个取代它,保证顺序执行。单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。
4)、newScheduleThreadPool
创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。
5)、newSingleThreadScheduledExecutor
创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行并且可定时或者延迟执行线程活动。

确保线程安全:
(1)、使用synchronized同步关键字
(2)、使用同步代码块(对象锁)
(3)、使用同步锁

6.springmvc工作流程
这道题个人感觉很重要,面试经常被问!!!
1)、 用户发送请求至前端控制器DispatcherServlet。
2)、 DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3)、 处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4)、 DispatcherServlet调用HandlerAdapter处理器适配器。
5)、 HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6)、 Controller执行完成返回ModelAndView。
7)、 HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8)、 DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9)、 ViewReslover解析后返回具体View。
10)、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11)、 DispatcherServlet响应用户。
建议学习:https://blog.csdn.net/zzh18334820165/article/details/107850500
个人感觉对于这个问题,要将他联系ssm框架整体去看,另外如果有时间建议了解一下你在浏览器输入网址到页面跳转这之间发生了什么这个问题。

7.Synchronized使用方法
三种:
1)修饰实例方法,锁是当前实例对象,进入同步代码前要获得当前实例的锁。
2)修饰静态方法,锁是当前类的 class对象,进入同步代码前要获得当前类对象的锁。
3)修饰代码块。

详细学习可以去:https://blog.csdn.net/zengdeqing2012/article/details/103037020

8.垃圾回收算法有哪些
1)复制算法
2)标记-清除算法
3)标记-整理算法
4)分代收集算法
个人感觉对于这个问题,了解一下算法名,然后选择一种深入了解比较好。
复制算法:

    将内存分为(大小相等)两部分,每次只使用其中一块进行内存分配,当内存使用完后,就出发GC,
    将存活的对象直接复制到另一块空闲的内存中,然后对当前使用的内存块一次性清除所有,然后转到另一块内存进行使用。
    优点:简单,高效。
    缺点:浪费内存,因为每次都有另一块内存空闲着。

9。java代理机制
分为动态代理与静态代理
静态代理是在编译时就将接口、实现类、代理类一股脑儿全部手动完成,但如果我们需要很多的代理,每一个都这么手动的去创建实属浪费时间,而且会有大量的重复代码,此时我们就可以采用动态代理。动态代理可以在程序运行期间根据需要动态的创建代理类及其实例,来完成具体的功能。
采用代理模式可以有效的将具体的实现与调用方进行解耦,通过面向接口进行编码完全将具体的实现隐藏在内部。

静态代理:首先创建一个接口(JDK代理都是面向接口的),然后创建具体实现类来实现这个接口,在创建一个代理类同样实现这个接口,不同指出在于,具体实现类的方法中需要将接口中定义的方法的业务逻辑功能实现,而代理类中的方法只要调用具体类中的对应方法即可,这样我们在需要使用接口中的某个方法的功能时直接调用代理类的方法即可,将具体的实现类隐藏在底层。
动态代理:spring的AOP就是动态代理。

10.final,finally,finalize的区别

1)final
用来修饰类、方法以及变量(成员变量与局部变量)
当用final修饰类的时,表明该类不能被其他类所继承,但要注意:final类中所有的成员方法都会隐式的定义为final方法。

用来修饰方法是为了把方法锁定,以防止继承类对其进行更改以及效率,final方法意味着“最后的、最终的”含义,即此方法不能被重写。注意:若父类中final方法的访问权限为private,将导致子类中不能直接继承该方法,因此,此时可以在子类中定义相同方法名的函数,此时不会与重写final的矛盾,而是在子类中重新地定义了新方法。

用来修饰变量:final成员变量表示常量,只能被赋值一次,赋值后其值不再改变。当final修饰一个基本数据类型时,表示该基本数据类型的值一旦在初始化后便不能发生变化;如果final修饰一个引用类型时,则在对其初始化之后便不能再让其指向其他对象了,但该引用所指向的对象的内容是可以发生变化的。本质上是一回事,因为引用的值是一个地址,final要求值,即地址的值不发生变化。在java中,String就被设计成final类。

2)finally
finally作为异常处理的一部分,它只能用在try/catch语句中,并且附带一个语句块,表示这段语句最终一定会被执行(不管有没有抛出异常),经常被用在需要释放资源的情况下。
注意:这里不是绝对的。首先,当try执行前程序就因为异常终止,显然finally无法执行;其次,若try语句块有 System.exit (0) ,在try中会终止虚拟机,也就是说只要执行try与catch语句块时被打断(无论外因内因),都不会执行fianlly。

3)finalize
finalize()是在java.lang.Object里定义的,也就是说每一个对象都有这么个方法。这个方法在gc启动,该对象被回收的时候被调用。其实gc可以回收大部分的对象(凡是new出来的对象,gc都能搞定,一般情况下我们又不会用new以外的方式去创建对象),所以一般是不需要程序员去实现finalize的。
特殊情况下,需要程序员实现finalize,当对象被回收的时候释放一些资源,比如:一个socket链接,在对象初始化时创建,整个生命周期内有效,那么就需要实现finalize,关闭这个链接。
一个对象的finalize()方法只会被调用一次,而且finalize()被调用不意味着gc会立即回收该对象,所以有可能调用finalize()后,该对象又不需要被回收了,然后到了真正要被回收的时候,因为前面调用过一次,所以不会调用finalize(),产生问题。 所以,推荐不要使用finalize()方法,它跟析构函数不一样。

11.memcached与redis区别
Redis 的作者 Salvatore Sanfilippo 曾对这两种基于内存的数据存储系统进行过比较:
1)Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。
2)内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。
3)性能对比:由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。

12.class文件是如何被JVM加载的

推荐学习:https://www.jianshu.com/p/afc79063b937
简单来说三个步骤:加载、链接以及初始化。
加载:
通过一个类的全限定名获取定义此类的二进制字节流。将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构。在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口。

链接:细分为验证、准备、解析
验证就是保证被加载类的正确性。比如,文件的格式、元数据、字节码、符号引用。
准备为类的静态变量分配内存,并将其初始化为默认值。举例:源码里存在 static int num=10;这里为num分配空间,并且将值初始化为默认值,也就是num=0;
解析把类中的符号引用转换为直接引用。class文件里都是采用符号描述的,这里需要将符号所代表的含义来转换成具体的操作。举例:某些符号表示需要开辟一段内存空间,那么根据符号的含义,就需要真的来开辟一段内存空间。

初始化:
对类的静态变量,静态代码块执行初始化操作。上面的准备阶段里已经介绍了需要给静态变量初始化默认值,而这里就需要将真实的数据来赋值给变量。

这里建议了解一下类加载器ClassLoader,我阿里面试被问到过T-T,只知道名字不知道具体,没答上来。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值