题目来自牛客,  题的答案都是我个人理解的或网上的参考,仅仅只作为复习用.因个人水平有限,不合理的地方请多多指正.


 

new 一个对象的过程;

java在new一个对象的时候,会先查看对象所属的类有没有被加载到内存,如果没有的话,就会先通过类的全限定名来加载。加载并初始化类完成后,再进行对象的创建工作。

一、类加载过程(第一次使用该类)

我的另一篇博客上有详细介绍: https://blog.csdn.net/wang5701071/article/details/108710486

java是使用双亲委派模型来进行类的加载的, 加载  ->   ( 验证  -> 准备   ->  解析   )   ->  初始化  ->   使用   ->  卸载

java面试题_快手一面_java面经汇总

 加载:查找并加载类的二进制数据

 验证:确保被加载的类的正确性

 准备:为类的静态变量分配内存,并将其初始化为默认值

  解析:把类中的符号引用转换为直接引用

 初始化: 为类的静态变量赋予正确的初始值

卸载:

 

jvm内存区域;

java面试题_快手一面_java面经汇总

 

堆内存分代;

堆内存是jvm中最大的区域,所有创建的对象都在堆中存放,所以这里也是GC最多的地方.为了使gc更高效,目前主流的虚拟机都采用分代. 分为 年轻代,老年代,  (永久代在最新的jvm中被元空间取代)

年轻代采用的GC算法: 复制. 因为这个地方对象众多,每次GC会清理大部分的对象,剩余小部分方便复制

老年代采用的GC算法: 标记清除/整理  老年代的对象每次GC存活率会更高.所以采用这两种算法

 

哪些可以作为 GC Roots;

jvm中判断对象是否清理的一种方法是可达性算法. 可达性算法就是采用GC Roots 为根节点, 采用树状结构,向下搜索.如果对象直接到达GC Roots ,中间没有任何中间节点.则判断对象可回收. 而堆区是GC的重点区域,所以堆区不能作为GC roots

因为可达性算法的特性,所以可以在gc接触不到的地方作为GC Roots

1.虚拟机栈(栈帧中的本地变量表)中引用的对象;

2.方法区中的类静态属性引用的对象;

3.方法区中常量引用的对象;

4.本地方法栈中JNI(即一般说的Native方法)中引用的对象

 

 

HashMap,put和resize的流程?为什么0.75?为什么2的次方?为什么8?

hashMap 初始化负载因子为0.75,负载因子的作用是计算一个扩容阀值,当容器内数量达到阀值时,HashMap会进行一次resize,把容器大小扩大一倍,同时也会重新计算扩容阀值。扩容阀值=容器数量 * 负载因子

put

  • ①如果定位到的数组位置没有元素 就直接插入。
  • ②如果定位到的数组位置有元素就和要插入的key比较,如果key相同就直接覆盖,如果key不相同,就判断p是否是一个树节点, 是将元素添加进入。如果不是就遍历链表插入(插入的是链表尾部)。

resize方法的作用就是初始化容器,以及对容器做扩容操作,扩容规则就是double
进行扩容,会伴随着一次重新hash分配,并且会遍历hash表中所有的元素,是非常耗时的。在编写程序中,要尽量避免resize。

为什么0.75? (不会),涉及到了统计学里很重要的原理——泊松分布

hashMap扩容为什么2的次方?

为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,Hash 值的范围值-2147483648 到 2147483647,前后加起来大概 40 亿的映射空间 ,只要哈希函数映射得比较均匀松散,一般应用是很难出现碰撞的。用之前还要先做对数组的长度取模运算,得到的余数才能用来要存放的位置也就是对应的数组下标。这个数组下标的计算方法是“ (n - 1) & hash”。

 

 

concurrentHashMap?为什么线程安全?

hashMap在多线程下是不安全的,可能会导致死循环.

 concurrentHashMap是线程安全的,适用于多线程情况下.,并发控制使用 synchronized 和 CAS 来操作

两则的底层结构在jdk1.8后一样,都是 数组加链表加红黑树

 

java的锁?

java面试题_快手一面_java面经汇总

juc包了解多少?

1 atomic包

核心是CAS,主要提供了一系列原子变量更新操作的类,提供非阻塞式算法基础。

2 locks包

主要提供了显示锁,如重入锁(ReentrantLock)和读写锁(ReadWriteLock)。核心是AQS这个抽象队列同步器框架。J.U.C包中很多工具类都是基于AQS

3 并发容器

并发的list ,map,set 这些

4 执行框架与线程池

java面试题_快手一面_java面经汇总

 

5 并发工具类

java面试题_快手一面_java面经汇总

线程池?

线程池优点

  • 降低资源消耗
  • 提高响应速度
  • 提高线程的可管理性

阿里巴巴开发手册强制使用 ThreadPoolExecutor  来创建线程池

其他线程池的构建最后其实都调用了ThreadPoolExecutor类的构造方法去创建线程池。而这些类型的线程池只是根据自己的需要来传入了一些默认的参数,也正是因为这些参数,才会导致可能出现OOM的问题。

ThreadPoolExecutor  核心参数

  • corePoolSize : 核心线程数线程数定义了最小可以同时运行的线程数量。
  • maximumPoolSize : 当队列中存放的任务达到队列容量的时候,当前可以同时运行的线程数量变为最大线程数。
  • workQueue: 当新任务来的时候会先判断当前运行的线程数量是否达到核心线程数,如果达到的话,新任务就会被存放在队列中。
  •  

SpringMVC常用注解?

@Controller 使用它标记的类就是一个SpringMVC Controller 对象 使用在controller层

@RequestMapping 是一个用来处理请求地址映射的注解,可用于类或方法上。

@Resource和@Autowired 都是做bean的注入时使用, @Resource默认按照ByName自动注入[email protected]注解是按照类型(byType)装配依赖对象

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出uri模板中的变量作为参数。

@ResponseBody 将返回json格式的数据

@Component 相当于通用的注解,当不知道一些类归到哪个层时使用,但是不建议

@Repository  用于注解dao层,在daoImpl类上面注解。

 

怎么注入一个bean。

1.autowire 注解

即标识符就是bean的名字。这个需要autowire的后置处理器。可参考前面的后置处理器的文章。

2.set方法注入

即添加属性后,只需要给该属性添加一个set方法即可。然后在xml文件中注入的时候,配置property属性进行注入,即property name="beanname" value=""或者ref=“”某个bean。

 

写一个算法:给一个String,判断最多去掉一个字符之后,他是不是回文串。

相关文章: