Java基础
Java程序的运行原理?
- 一般运行一个Java程序的时候会点击运行按钮,按运行按钮的时候发生了什么呢?
- .java文件被执行编译生成.class文件,被JVM识别和加载,编译生成的.class文件在target目录
- 启动:在idea的下面Run可以看到 有个拼了很长的字符串,在里面可以找到target目录,JVM的运行只和这些字节码有关
- 跨平台性
- 怎么能让同样的一份代码与不同的系统进行通信
- 每一个平台上面都自己的JVM实现,JVM负责把统一的字节码翻译成底层的系统调用
JDK/JRE有什么区别?
- JDK = JRE + javac
- JDK包含了JRE,同时还包含了编译java源码的编译器javac,还包含了很多java程序调试和分析的工具
- JDK:Java Development Kit java(开发工具包)
- JRE:Java Runtime Environmen (java运行时环境)
- 如果需要运行java程序,只需安装JRE。如果需要编写java程序,需要安装JDK。
Java的基础类型有哪些? char/byte/
- String是基本数据类型么?
Java的参数传递是传值还是传引用?
- Java世界中的一切对象都是指针(地址)
- 函数调用永远是传值
StringBuffer/StringBuilder 的区别/线程安全性?
- 如果没有额外声明,所有的类默认都是线程不安全的
- StringBuilder更快,但是线程不安全,更加常用
- StringBuffer稍慢,但是线程安全
Object中有哪些方法?
String中有哪些方法?
面向对象
==/equals有什么区别?
- == 解读
- 基本类型:比较的是值是否相同;
- 引用类型:比较的是引用是否相同;
- equals 解读
- equals 本质上就是 ==,只不过 String 和 Integer 等重写了 equals 方法,把它变成了值比较
- == 对于基本类型来说是值比较,对于引用类型来说是比较的是引用;而 equals 默认情况下是引
用比较,只是很多类重新了 equals 方法,比如 String、Integer 等把它变成了值比较,所以一般情况下
equals 比较的是值是否相等。
深拷贝/浅拷贝有什么区别?
- 浅克隆:当对象被复制时只复制它本身和其中包含的值类型的成员变量,而引用类型的成员对象并没有
复制。 - 深克隆:除了对象本身被复制外,对象所包含的所有成员变量也将复制
接口和抽象类有什么区别/联系?
- Interface:定义功能,只能包含方法(实现),不能包含成员 变量,可以被实现若干次
- Abstract class:定义抽象的骨架实现,可以包含抽象方法或 者具体实现,也可以包含成员变量,只能沿着一条路径继承
- 实现数量:类可以实现很多个接口;但是只能继承一个抽象类。
- 访问修饰符:接口中的方法默认使用 public 修饰;抽象类中的方法可以是任意访问修饰符。
什么时候用接口/抽象类?
- 明确想不想类里面有成员变量,有成员变量只能用抽象类
- 如果没有成员变量,两个都可以用,接口更灵活,用抽象类被限制继承体系
final的作用是什么?
- 是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则表示此方法和此变量不能在
被改变,只能使用。
override和overload有什么区别?
- 重载: 发生在同一个类中,方法名必须相同,参数类型不同、个数不同、顺序不同,方法返回值和
访问修饰符可以不同,发生在编译时。 - 重写: 发生在父子类中,方法名、参数列表必须相同,返回值范围小于等于父类,抛出的异常范围
小于等于父类,访问修饰符范围大于等于父类;如果父类方法访问修饰符为 private 则子类就不能重写该方法。
集合框架
HashMap 原理?
- 扩容/并发问题
List/Set/Map 区别
List、Set、Map 的区别主要体现在两个方面:元素是否有序、是否允许元素重复。
三者之间的区别,如下表:
1、List、Set都是继承自Collection接口,Map则不是
2、List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会
覆盖掉,(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位
置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来
遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)
3、Set和List对比:
Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素
位置改变。
4、Map适合储存键值对的数据
5、线程安全集合类与非线程安全集合类 :
LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
HashMap是非线程安全的,HashTable是线程安全的;
StringBuilder是非线程安全的,StringBuffer是线程安全的。
HashMap 和HashTable 区别?
- 存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下
使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。
ConcurrentHashMap 原理?
- JDK1.7 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数
据时,其他段的数据也能被其他线程访问。 - JDK1.8 ConcurrentHashMap 取消了 Segment 分段锁,采用 CAS 和 synchronized 来保证并发安全。数据
结构跟 HashMap1.8 的结构类似,数组+链表/红黑二叉树。
synchronized 只锁定当前链表或红黑二叉树的首节点,这样只要 hash 不冲突,就不会产生并发,效
率又提升 N 倍。
HashSet原理
- HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的
实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成 - HashMap key的集合拿出来就是一个Set
TreeSet 原理?
- 元素有序,插入/删除高效
- 红黑树(自平衡的排序二叉树。)
equals/hashCode区别/何时使用?
hashCode 决定一个元素在哈希表被丢到哪个桶中去,但是有可能两个对象的hashCode是一样的,这时候怎么判断这个对象是不是我想找的对象呢,这时候用equals
hashcode是系统用来快速检索对象而使用
equals方法本意是用来判断引用的对象是否一致
如果重写了equals方法,那么一定要重写hashCode
使用和重写这两个方法时的约定
- 如果两个对象通过equals比较的结果为true, 那么它们的hashCode也必须一样
- 如果两个对象的hashCode相等,那么这两个对象不一定相等(即equals不一定返回true)
ArrayList/LinkedList 区别?
-
数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
-
随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存
储方式,所以需要移动指针从前往后依次查找。 -
增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList
增删操作要影响数组内的其他数据的下标。
ArrayList的实现用的是数组,LinkedList是基于链表,ArrayList适合查找,LinkedList适合增删
哪些集合类是线程安全的?
HashTable/ConcurrentHashSet
如何保证一个集合类不被修改?
- Collections.unmodifiableXXX
- Guava 的ImmutableXXX
ArrayList/Vector 区别
- 基于数组的自动扩容实现
- Vector线程安全,但是慢,被废弃了 ;ArrayList不安全,但是效率高
说一些常见的List/Set/Map实现?
- List
- ArrayList
- LinkedList
- Set
- HashSet
- TreeSet
- LinkedHashSet
- Map
- HashMap
- LinkedHashMap
- TreeMap
- ConcurrentHashMap
Collection 和C ollections 有什么区别?
- X是类名的话,Xs就是与之相关的工具方法集合。
Java的异常体系结构?
Throwable 任何异常/错误的超类 checked
-
Exception 异常,可以从异常状态中恢复
- RuntimeException 预料之外的异常,通常代表一个bug,unchecked
- 其他Exception 预料之中的异常,代表编程中预期的异常状态,checked
-
Error 无法恢复的异常状态 unchecked
什么是 checked/unchecked/runtime exception?
受检查的异常(checked) 必须要用 throws 语句在方法或者是构造函数上声明。
不受检查的异常(unchecked) 不需要在方法或者是构造函数上声明。
-
CheckException发生在编译阶段,必须要使用try catch (或者throws )否则译不通过。
-
UncheckedException发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的,难以排查,我们一 般都需要纵观全局才能够发现这类的异常错误,所以在程序设计中需要认真考虑,好好写代码,尽量处理异常m,即使产生了异常,也能尽量保证程序朝着有利方向友展。
-
RuntimeException 是UncheckedException 的一个别名
-
try/catch/finally 的执行顺序?
- try中任何可以被抛出的东西(异常或者Error)的语句,会阻止try中抛异常后面的语句执行,然后JVM寻找匹配的catch块
- try中没有抛出异常,则catch语句不执行,如果有finally语句,则接着执行finally语句
- 不管有木有出现异常,finally块中代码都会执行;
- 当try...catch中有return的话,finally后会执行try...catch中的return,然后不再执行后续语句
- finally前有return、finally块中也有return,先执行前面的return,保存下来,再执行finally的return,覆盖之前的结果,并返回。
-
catch 中return了 ,finally 还会执行么?
- finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,
才会执行 finally中return了,会发生什么事情?非常不建议在finally里面写
- finally 一定会执行,即使是 catch 中 return 了,catch 中的 return 会等 finally 中的代码执行完之后,
-
throw/throws 的区别
- throw 关键字用来在程序中明确的抛出异常
- throws 语句用来表明方法不能处理的异常
-
final/finally/finalize 的区别
- final:是修饰符,如果修饰类,此类不能被继承;如果修饰方法和变量,则表示此方法和此变量不能在被改变,只能使用。
- finally:是 try{} catch{} finally{} 最后一部分,表示不论发生任何情况都会执行,finally 部分可以省略,但如果 finally 部分存在,则一定会执行 finally 里面的代码。
- finalize: 是 Object 类的一个方法,在垃圾收集器执行的时候会调用被回收对象的此方法。不推荐调用。
计算机体系原理
-
进程和线程的区别?
- 进程占用独享的隔离的内存,文件等资源
- 同一个进程内的线程共享内存/文件等资源
- 一个程序下至少有一个进程,一个进程下至少有一个线程,一个进程下也可以有多个线程来增加程序的
执行速度。 - 进程是系统进行资源分配和调度的一个独立单位,最小的资源管理单位。线程是进程的一个实体,
是 CPU 调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,最小的 CPU 执行单元。
-
进程和线程是如何调度的?
-
大部分操作系统(如Windows、Linux)的任务调度是采用时间片轮转的抢占式调度方式
-
轮转调度 最简单且最公平的方法,给每个进程分配一个时间片。当时间片耗尽时,进程会下CPU并加入到就绪队列的队尾。问题的关键是选择合适的时间片。
-
在一个进程中,当一个线程任务执行几毫秒后,会由操作系统的内核(负责管理各个任务)进行调度,通过硬件的计数器中断处理器,让该线程强制暂停并将该线程的寄存器放入内存中,通过查看线程列表决定接下来执行哪一个线程,并从内存中恢复该线程的寄存器,最后恢复该线程的执行,从而去执行下一个任务。
上述过程中,任务执行的那一小段时间叫做时间片,任务正在执行时的状态叫运行状态,被暂停的线程任务状态叫做就绪状态,意为等待下一个属于它的时间片的到来。
-
线程的调度
-
线程的调度,取决于支持的是内核级线程还是用户级线程。
对于用户级线程,内核不知道线程的存在,就给了进程很大的自主权。内核只是调度进程,进程中的调度程序选择哪个线程来运行。
对于内核级线程,线程的调度就交给了系统完成。
-
Java中的线程和操作系统线程是什么关系?
-
JVM的线程和OS的线程是一一对应的
-
OS辅助调度线程
-
因此,Java的线程模型饱受诟病
-
是不是有了协程一切并发问题就不存在了呢?
- 协程解决的是让线程跑起来更快,切换更灵活
- 并发问题还会存在,并不解决多线程里 死锁/竞争/临界条件等
-
协程,英文Coroutines,是一种基于线程之上,但又比线程更加轻量级的存在,这种由程序员自己写程序来管理的轻量级线程叫做『用户空间线程』,具有对内核来说不可见的特性。
- 特点:线程的切换由操作系统负责调度,协程由用户自己进行调度,因此减少了上下文切换,提高了效率。
计算机网络
tcp/udp的区别?
- TCP:稳定可靠,纠错/重新发送,比较慢
- 保证交付
- 对质量要求很高的场景(文件传输,发送或接收邮件,远程登录等)
- UDP:快,质量低
- 尽最大可能交付
- 对质量要求不高(即时通信,qq聊天,在线视频,网络语音通话等)
TCP协议的三次握手和四次挥手?
-
三次握手
(1)第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2)第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3)第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。
-
四次挥手
(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
从浏览器发出请求到服务器接收到请求发生了什么?
- 客户端浏览器通过 DNS 解析到 www.baidu.com 的 IP 地址为 220.181.0.1,
通过这个 ip 地址找到客户端到服务器的路径,客户端浏览器发起一个 http 会话
到 220.181.0.1,然后通过 TCP 进行封装数据包,输入到网络层。 - 在客户端的传输层,把 HTTP 会话请求分成报文段,添加源和目的端口,
如服务器端用 80 端口监听客户端的请求,客户端由系统随机选择一个端口,如
5000,与客户端进行交换,服务器把相应的请求返回给客户端的 5000 端口。然
后使用 ip 层的 ip 地址查找目的端。 - 客户端的网络层不用关心应用层和传输层的东西,主要做的是通过查找路
由表确定如何到达服务器,期间可能经过多个路由器。 - 客户端的链路层,包通过链路层发送到路由器,通过邻居协议查找给定
的 ip 地址和 MAC 地址,然后发送 ARP 请求查找目的地址,如果得到回应后就可
以使用 ARP 的请求应答交换的 ip 数据包现在就可以传输了,然后发送 Ip 数据包
到达服务器的地址。
算法与数据结构
集合类中常见的数据结构
- ArrayList:数组,随机查找是常熟时间
- LinkedList:双链表,可当做队列和栈
- HashSet/HashMap:哈希表
- TreeSet/TreeMap:红黑树
- ConcurrentHashMap:分段+哈希表
- LinkedHashMap:链表+哈希表
链表和二叉查找树的时间复杂度区别
- ArrayList:寻址O(1)/更新O(n)/二分查找O(lgn)
- LinkList:寻址O(n)/更新O(1)/查找o(n)
- 哈希表:都是O(1)
- 红黑树:都是O(lgn)
- 二叉查找树:都是O(lgn)
队列和栈分别是什么?
- 队列:先进先出
- 应用场景:对于一个多叉树(常见是二叉树)树的层次遍历,最好能手写
- 栈:后进先出
- 应用场景:方法栈
Web
常见的http状态码?
- 2XX一切正常/3XX跳转/4XX客户端异常/5XX服务端异常
- 200/201/301/302/403/404/502/503/504
GET/POST有什么区别?
- GET获取资源/POST发送数据
- GET查询/获取资源,POST用于登录,修改数据
- GET是幂等的(多次发送和一次发送的结果完全相同)
GET使用URL或Cookie传参,而POST将数据放在BODY中;
GET的URL会有长度上的限制,POST的数据可以非常大;
POST比GET安全,因为数据在地址栏上不可见
Cookie和Session有什么区别?
-
Cookie:随HTTP请求一起发送的一小段标识用户身份的信息
-
Session :放在服务端的,用于通过Cookie和用户身份对应关系来鉴权的数据
不同点:
1、无论客户端做怎样的设置,session 都能够正常工作。当客户端禁用 cookie 时将无
法使用 cookie。
2、在存储的数据量方面:session 能够存储任意的 java 对象,cookie 只能存储 String
类型的对象。
什么是跨域?如何解决跨域?
- JSONP
- CORS
- nginx转发(反向代理)
类型与反射
什么是反射?
- 反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都
能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为 Java 语
言的反射机制。 - 运行时行为,动态调用
*动态代理的原理是什么?**
- 动态生成字节码完成一些功能拓展
- JDK动态代理:方便,手限制(只能代理接口)
- 字节码增强:不受限制,但是麻烦
动态代理的应用有 spring aop、hibernate 数据查询、测试框架的后端 mock、rpc,Java注解对象获取
等。
反射为什么性能较差?
- JDK无法预测被调用的方法,因此无法实施优化
什么是序列化?
- 将Java对象编程字节流的过程叫序列化 serialize
- 将字节流编程Java对象的过程叫做反序列化 deserialize
- 可读:JSON/XML
- 不可读:Java自带的序列化
Spring
什么是loC容器,为什么需要loC
- IoC控制反转,不需要手工控制各种对象的创建和依赖
- 由容器帮你完成
AOP与AOP原理
- 面向一个特定的切面编程,使得重复的逻辑可以在一起编写,方便维护,减少重复。
Bean的生命周期
-
Bean从零开始:从指定的配置文件中加载BeanDefinition,然后Spring容器根据该定义开始进行Bean的装配工作
-
Spring维护了一套完整的生命周期,每个Bean都可以自定义在生命周期任何一个阶段所完成的工作
Spring Boot相对于Spring MVC有哪些改进?
- 自动化配置:
- Spring MVC - 通过XML配置,手动指定
- SpringBoot - 通过注解或者自动化扫描
- 自带Servlet容器,可以直接启动
- Spring MVC - 不自带Servlet容器,需要额外配置
- Spring Boot - 直接打成jar包,可以直接启动
- Spring Boot对于微服务和快速开发更为友好
- 优点:大大简化了开发配置的难度
- 缺点:有很多潜在的默认约定,是的开发者更难深入了解其中的细节