[JAVA]面试的基本探讨1
1. 背景
虽然说对于现在来说更多的会项目的经验,但是基础的东西仍然很重要,只有这些基本的东西,才解决具体的事情有依据。 所以java的基础面试题目的答案还是需要去理解下。
2. 技术
2.1 基础知识
2.1.1 讲项目,空间索引与一般索引区别。查看
- 一般的索引主要包含主键索引,唯一索引,索引列。 这些索引主要是采用B 树的数据结构进行查找,这种结构一般试用与点的搜索。
- 空间索引主要是解决面和多维的信息的查询。如根据经纬度搜索周边的信息,这个就在空间上建立信息的关系。
2.1.2 深度优先遍历,广度优先遍历算法,在什么地方可以应用。
- 采集这一块是经典的例子。 页面采集链接,采用深度算法,在一个页面抓取链接后,会把链接记录,然后根据链接继续采集数据。
- 广度优先算法,常见的文件搜索,一般是把整个文件列表列出来一个个查找。
2.1.3 http请求头包含哪些信息?
- 请求的数据
- 基本信息,包括协议类型,url,http方法,来源地址,代理
- 更细致的信息:cookie,缓存有效期,字符编码,接受的文件类型,支持的语言
- 特殊:有些会存在etag信息。
- 返回的数据
- 返回的数据,一般是字符串
- 基本的信息:状态,修改的时间,内容的大小,字符集,最大失效时间
- 其他:日志信息,接受的服务器。
2.1.4 提升访问网页效率的方法
- 缓存:客户端缓存,cdn缓存,服务器缓存,多线程,负载均衡之类
- 前端打包压缩
2.1.5 java jvm编译,执行原理,类加载机制,内存模型与回收算法
- jvm编译原理
- 分析和输入到符号表
- 对注解的处理
- 语义分析并生成class文件
- class 执行原理
- 类加载器子系统把class文件加载
- 解析class文件,对于class方法,变量分配空间,对于操作变量放入堆栈中
- 把数据和指令交个执行引擎处理
- 类加载机制
- 加载类分为:基础的类加载器bootstrap ,扩展的加载器extension,app加载,自定义加载器
- 类检查原理:自底向上检查类是否已经加载了,自上而下来加载类。 所有一般类有命名空间,不要跟系统的加载器命名空间一致。
- 垃圾回收算法
- Mark-Sweep(标记-清除)算法。就是在类加载的时候加上引用计数器,如果计数器为0,这可以删除这对象,有需要使用的可以重新申请。
- Generational Collection(分代收集)算法。对于堆区划分老年代,新生代。 如果是老年代可以选择标记和清除的方式,对于新生代可以使用采用复制的方式。把内存按照容量划分相等的两块,一块用完了再用其他的。避免内存碎片的情况。
2.1.6 讲讲多线程,多线程的同步方法
- 多线程就是java在主进程基础上分配更细粒度的资源。这样消耗比进程少
- 线程的同步主要是加锁,synchronized
2.1.7 悲观锁与乐观锁
- 悲观每次在拿数据的时候都会上锁,每次都认为别人已经改了。如数据库的表锁,行锁(写操作)
- 乐观锁表示对别人放心,一般通过版本号号来判断是否有变化。 版本好没有变化就可以更新了。 (适合大量的读操作)
2.1.8 String StringBuffer StringBuilder的区别
- String 是final 没有继承的方式 每次new或者+都是新对象,这样容易造成申请的内存消耗比较大。 而StringBuffer 有append方法可以添加内容,而对象不会重新创建,所以性能高。
- String 和StringBuffer是线程安全的(对方法加了同步锁或者对调用的方法加了同步锁),而StringBuilder不是。
2.1.9 Servlet生命周期
- 开启->初始化配置->request请求->response操作->销毁->关闭
2.1.10 面试中描述你做的每一个项目
- 你做了什么工作?
- 这些工作你解决了什么问题?
- 还有什么困难没有解决?
- 这些困难在后续如何优化?
- 优化后可以实现什么功能?
2.2 常见的特性
2.2.2 Java 8 函数式编程
一切都是数学函数。 Lambda 表达式的引入,主要采用了方法的重载机制+匿名类的方式
Runnable multiStatement = () -> {
System.out.print("Hello");
System.out.println(" World");
};
multiStatement.run();
2.2.3 Stream
流是抽象的概念主要是对输入和输出操作的抽象。主要是数据源与程序的交互 设备可以是文件,网络,内存等。 流主要是包括字节流和字符流,方向包括输入流和输出流。
2.2.4 回调函数,函数式编程,面向对象之间区别
函数式语言:每次一个步骤方法会产生一个状态,这个状态会直接当参数传进下一步中。而不是使用全局变量。 而面向对象可以根据这个类/对象的全局和局部的状态传输
回调函数:就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
2.2.5 面向对象的三大特点,接口和抽象类区别?
- 三大特点::封装、继承、多态/抽象
2.2.6 集合类型主要有3种:set(集)、list(列表)和map(映射)。
2.2.7 ConcurrentHashMap
ConcurrentHashMap采用了分段锁的设计,只有在同一个分段内才存在竞态关系,不同的分段锁之间没有锁竞争。相比于对整个Map加锁的设计,分段锁大大的提高了高并发环境下的处理能力。
2.2.8 volatile
volatile是一个类型修饰符(type specifier),就像大家更熟悉的const一样,它是被设计用来修饰被不同线程访问和修改的变量
2.2.9 java内存模型
![[JAVA]面试的基本探讨1](https://static.blogweb.cn/article/68f42a4d5a3b4bcf94f16146835ba316.webp)
2.2.10 ThreadLocal
线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。解决修改线程的功能
2.2.11 TCP 的通信机制
![[JAVA]面试的基本探讨1](https://static.blogweb.cn/article/9dd6975453ae45c3a724d2c94aa500f5.webp)
2.2.12 select & poll
都是IO多路复用的机制。 把用户态的数据复制到内核态
- poll 解决select 的阻塞的方式,采用队列的机制,并且解决了select 对1G的大小
2.2.13 Synchronized同步性与可见性
同步表示,要么一起成功,要么一起失败。 可见性表示:一个县城操作可以被其他的线程更新到。
2.2.14 Lock与synchronized 的区别
synchronized是在JVM层面上实现的,不但可以通过一些监控工具监控synchronized的锁定,而且在代码执行时出现异常,JVM会自动释放锁定,但是使用Lock则不行,lock是通过代码实现的,要保证锁定一定会被释放,就必须将unLock()放到finally{}中
2.2.15 锁的机制
![[JAVA]面试的基本探讨1](https://static.blogweb.cn/article/804945cc830c459eb2de88b4d81862e9.webp)
2.2.16 CopyOnWriteArrayList
CopyOnWriteArrayList:CopyOnWriteArrayList这是一个ArrayList的线程安全的变体,其原理大概可以通俗的理解为:初始化的时候只有一个容器,很常一段时间,这个容器数据、数量等没有发生变化的时候,大家(多个线程),都是读取(假设这段时间里只发生读取的操作)同一个容器中的数据,所以这样大家读到的数据都是唯一、一致、安全的。
2.2.17 反射是否可以访问私有的方法
可以,但是要通过反射获取 获取Method和Field对象的时候一定要用getDeclaredField和getDeclaredMethod。反射的在编辑器中用的比较多。
2.2.18 32位系统的最大寻址空间
2的32次方大小的地址也就是4G。这就是为什么32位操作系统最大只有4个G的原因
2.2.19 判断二叉树是不是平衡二叉树(java)
如果某二叉树中任意结点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。
二叉树主要是用于搜索和排序。 B树就是根据二叉树繁衍而成的。
2.2.20 DNS解析过程 ,查看
![[JAVA]面试的基本探讨1](https://static.blogweb.cn/article/592e054778584280bb413786dc4d0b9b.webp)
2.2.21 进程间的通信方式
经常的通信方式,主要管道,信号量,消息队列,套接字,内存共享几种方式。
![[JAVA]面试的基本探讨1](https://static.blogweb.cn/article/df31233847ec45b7b12b135e28f7a520.webp)
2.2.22 创建线程的三种方式
- 集成Thread
- 实现runable接口
- 调用callable接口
通过Callable和Future创建线程,Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable功能更强大一些,被线程执行后,可以返回值,这个返回值可以被Future拿到,也就是说,Future可以拿到异步执行任务的返回值
2.2.23 各种算法-分代(generational collecting) ,查看
分为:年轻代,老年代,持久代。
年轻代,分为三个区,一个 一个Eden区,2个Survivor区。 Eden存储大部分对象,如果Eden区满了,则分配到Survivier一个区。同理,如果Survier一个区满了,就放到另外一个Survier区。
老年代:存放从年轻代复制过的对象 持久代:用于存放静态文件。如java类和方法。
2.2.24 CAP 理论
Consistency(一致性), 数据一致更新,所有数据变动都是同步的 Availability(可用性), 好的响应性能 Partition tolerance(分区容错性) 可靠性
转载自:https://juejin.cn/post/6844903928694325255