测试工程师都能看懂的java基础面试题(含答案)

514 阅读6分钟

你好 我是懂java的测试


前言

前几天有个小伙伴发了在群里发了Java的面试题,仔细看了下都是很基础的面试题,如果你简历上写了熟悉或了解java可能会问到,切记不要死记硬背,得在理解的基础上背诵。本篇文章就详细梳理一下这个java面试题

图片图片

Redis为什么这么快?


具体原因可阅读另两篇文章

测试工程师都能看懂的Redis 上 、测试工程师都能看懂的Redis 下

多线程有什么好处?

多线程最大的好处就是:

  • 更好地利用CPU

  • 简单的程序设计

  • 程序更多的响应

  • 多任务下CPU资源分配公平性

线程池作用,几个参数?

去年面试货拉拉的时候,面试官问过我这个问题。线程频繁创建其实很消耗资源,有了线程池,线程用完可以放入线程池中,降低了资源消耗。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
 1、corePoolSize线程池中的常驻核心线程数
 2、maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值大于等于1
 3、keepAliveTime:多余的空闲线程存活时间,当空间时间达到keepAliveTime值时,多余的线程会被销毁 
   直到剩下corePoolSize个线程为止。
   默认情况下:只有当线程池中的线程数大于corePoolSize时keepAliveTime才会起作用,知道线程中的线程 
   数不大于corepoolSIze。
 4、Unit:keepAliveTime的单位
 5、WorkQueue:任务队列,被提交但尚未被执行的任务
 6、ThreadFactory:表示生成线程池中工作线程的线程工厂,用户创建新线程,一搬用默认即可
 7、Handler:拒绝策略,表示当线程队列满了并且工作线程大于等于线程池的最大线程数 
   (maximumPoolSize)时如何来拒绝请求执行的runnable的策略

当线程池中corePoolSize使用完毕之后,多出来的任务就会进入缓存队列;当缓存队列也存放满了之后,还有大量的任务,这时将会创建线程池中支持的最大量的线程,然后执行缓存队列里面的任务,而外面的任务进入缓存队列中;当线程池中的线程达到最大时,缓存队列也存满之后,这时该线程池将会执行拒绝策略。

jmeter 测试性能主要关注啥?

接口响应时间、错误率和Tps

java三大特性?

见 Java基础之面对对象文章,里面有继承、多态的介绍

索引是什么,底层是什么?

见 Mysql相关面试题 上 文章关于索引介绍

arraylist和linkedlist区别?

arraylist底层是 动态数据,查询快和插入数组最后面较快。

注意:数据插入非尾部,涉及到下标index移位

linkedlist底层是链表,插入和查询头部元素较快。

注意:linkedlist如果查询头部元素还是比较快的。

数组查询效率高?

数组是一组连续的内存,查询的时候可以用index直接取到,时间复杂度为O(1),

HashMap底层原理是什么?

Java最经典的集合,没有之一,这个集合几乎涵盖了java所有的基础知识,如果聊起来两个小时都不够。我每次去面试java测开,hashmap被问到的概率高达90%。

底层是数组+链表,jdk 1.8以后变成数组+链表+红黑树。为什么变成了红黑树了呢?使用红黑树提高了查询效率,因为链表数据结构的查询时间复杂度是O(n),随着元素越来越多,查询效率只会越来越低,红黑树时间复杂度是 O(logn) 查询效率更高。

除了底层原理外,还有其他扩容机制、锁原理、并发访问等等知识,后面打算出一期文章,专门聊聊HashMap。

Spring的依赖注入是啥?

来自群里小伙伴的回答

图片

锁的机制了解不,什么原因导致死锁?

什么是锁呢?锁机制是实现线程同步的基础

Java中的锁无非就是JVM提供的synchronized关键字和JDK中的Lock接口实现。

在使用多线程以及多进程时,两个或两个以上的运算单元(进程、线程或协程),各自占有一些共享资源,并且互相等待其他线程占有的资源才能进行,而导致两个或者多个线程都在等待对方释放资源,就称为死锁。

String、Stringbuffer、StringBuilder区别?

老八股文了都,值得2016年刚毕业去面试的时候,面试官就问过它们三个的区别,没想到现在还有人会问,

总结:

1.String字符串是不可变的。

2.在修改字符串操作比较多的时候用StringBuilder或StringBuffer.

3.在要求线程安全的情况下用StringBuffer

4.在不要求线程安全的情况下用StringBuilder

怎么保证线程并发事件发生?

这个问题就比较诡异了,题目问道怎么保证线程并发事件发生,个人理解并发事件的发生可能会导致线程安全问题,所以这道题目其实是想问,怎么保证线程安全。

加锁,如果是单机系统,可以用JVM提供的synchronized关键字和JDK中的Lock接口实现,还可以用JUC包下并发组件,譬如,atomic原子类concurrenthashmap 等。

如果是分布式系统,且有共享的资源,那就使用分布式锁吧,后面详聊。

什么是反射?

JAVA机制反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.

bean的生命周期?

这个没办法,死记硬背吧,就是一些spring的关键类,

对于Bean的生命周期,主要步骤为:

1、实例化Bean:通过反射调用构造方法实例化对象。

2、依赖注入:装配Bean的属性

3、实现了Aware接口的Bean,执行接口方法:如顺序执行BeanNameAware、BeanFactoryAware、ApplicationContextAware的接口方法。

4、Bean对象初始化前,循环调用实现了BeanPostProcessor接口的预初始化方法(postProcessBeforeInitialization)

5、Bean对象初始化:顺序执行@PostConstruct注解方法、InitializingBean接口方法、init-method方法

6、Bean对象初始化后,循环调用实现了BeanPostProcessor接口的后初始化方法(postProcessAfterInitialization)

7、容器关闭时,执行Bean对象的销毁方法,顺序是:@PreDestroy注解方法、DisposableBean接口方法、destroy-method。

新开了java测试开发交流群,喜欢的可加入,若失效,可加我微信lvceshikaifa,拉你进群。

图片