java八股文

层次分明 主次清晰 慢条斯理

String为什么设计为不可变?

安全性:

字符串底层使用private final修饰的 char数组,保证对象不会被修改。可以适用于url,hashMap的 key等。

缓存哈希值:字符串的哈希值被缓存,提高了散列集合的性能。

字符串池:字符串常量池可以共享相同的字符串对象,节省内存空间并提高性能。

总结来说,不可变的String对象在并发环境下更安全、更高效,提供了更好的性能和安全性,同时利用字符串池可以节省内存。因此,String被设计成不可变的。

接口和抽象类的区别?

相同点:

都是不断向上抽取而来的,都是父类,都包含抽象方法,都不能被实例化。

不同点:

  1. 接口使用的是interface关键字修饰,抽象类使用的是 abstract关键字修饰。
  2. 接口的属性都是 public static final 修饰的。

抽象类的属性成员可以是各种类型。

  1. 接口可以多继承,但不可能实现多个接口。

抽象类不可以多继承,但可以实现多个接口。

  1. 一个类只能继承一个抽象类,但一个类可以 实现多个接口。
  2. 抽象类被类继承,体现的是 is-a的关系。是对类的增强。

接口被类实现,体现的是 like-a的关系。是对方法的增强。

ArrayList 和 LinkedList 和 Vector 的区别:

Arraylist:

1.ArrayList底层实现是数组,采用的是懒汉式。在对象创建时不会初始化容量, 而是在第一次添加元素时才会初始化数组容量,默认10。

扩容时容量上扩充0.5倍。

2.查询相对较快,因为数组是连续的内存。

3.增删较慢,因为数组的元素需要向前或者向后位移。

4.占用内存相对较少。

Vector:

1.Vector底层实现也是数组,采用的是饿汉式,在对象创建时就立即初始化数组 容量。默认容量也是10。扩容为原来的0.5。

2.查询和 增删与 ArrayList 相同。

3.Vector的方法含有synchronized 同步锁,可以保证安全性。

LinkedList:

1.LinkedList 底层实现是 双向链表。

2.查询慢,但增删较快。

3.占用内存相对较大

HaspMap的底层结构 为什么使用的是 数组、链表、红黑树?

  1. 使用数组是因为可以根据 key的hash值快速定位到哪个槽位。
  2. 链表是为了解决hash冲突。
  3. JDK1.8使用红黑树代替超过8个节点的链表,主要是提高查询性能。从原来的O(n) 到O(logn)。

HashMap 和 Hashtable的区别?

  1. Hashtable底层是哈希表(数组+链表),HahsMap底层是哈希表+红黑树。

  1. Hashtable在不指定容量的情况下默认是11,不要求底层数组的容量一定要为2的 整数次幂。扩容时将容量变为原来的2倍加1.

HashMap 在不指定容量的情况下默认容量是16,要求一定为2的整数次幂;扩容时, 将容量变为原来的2倍。

  1. HashMap 是线程不安全的。

Hashtable 是线程安全的 其方法上都加了synchronized的锁。

  1. HashMap 的 KV 可以是 null。

Hashtable 的 KV 不能是null会报空指针异常。

  1. 两者通过hash值散列到哈希表的算法不一样。

Hashtable 使用的是除留余数法,直接使用hashCode。

HashMap 是 强制容量为2的次幂,重新根据hashCode计算hash值,

hash & (容量-1),这样可以使得奇数、偶数、分步更均匀。

  1. HashMap 剔除了Hashtable包含的contains方法,改成了containsKey, containsValue

什么是反射?

反射在运行时环境中,对于任意一个类,可以知道这个类有哪些属性和方法。对于任意一个对象,都可以调用它的任意一个方法。这种动态获取类的信息以及动态调用对象的方法的功能都能成为java反射机制。

Java反射需要借助与四个类class,Constructor,Field,Method;

什么是 java序列化?

序列化是一种用来处理对象流的机制,所谓对象流就是将对象的内容进行流化,将数据分解成字节流,以便存储在文件中或在网络上进行传输。 可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。

使用序列化需要实现serializable 标记接口,使用ObjectOutputStream的writeObject 将对象序列化。恢复时使用ObjectInputStream 的readObject 将对象反序列化。

Http常见的状态码 有哪些?

200 OK      //客户端请求成功

301       (永久移除),请求的 URL 已移走。

302        临时重定向

400      客户端请求有语法错误,不能被服务器所理解

401      请求未经授权,这个状态代码必须和 WWW-Authenticate 报头域一起使用

403      Forbidden //服务器收到请求,但是拒绝提供服务。

404      Not Found //请求资源不存在。

500      服务器发生不可预期的错误。

503      服务器当前不能处理客户端的请求,一段时间后可能恢复正常

GET 和POST 的区别?

  1. Get请求的请求信息在url后,请求信息以?隔开,参数使用&相连。

Post请求将请求信息放置在报文体中。

  1. Get请求由于是通过URL提交数据的,而URL长度受浏览器限制,所以get请求 大小有限制。

Post请求的数据理论上不受限制。

  1. 使用场景不同,get是从 服务器上获取数据,post 是向服务器传送数据。
  2. POST 的 安全性更高。

Cookie和 Session的区别?

Cookie 和session 都是用于跟踪用户会话的技术,它们在存储位置、使用方式、安全性等方面存在差异。

  1. 存储位置:

Cookie 数据存放在客户端的浏览器上。当用户首次访问某个网站时,服务器会向用户的浏览器发送一段包含用户信息的数据(即Cookie)。浏览器接收并存储这些数据,以便在用户下次访问该网站时将其发送回服务器。

Session 数据放在服务器上。当用户访问网站时,服务器会为该用户创建一个唯一的Session ID,并将其发送给用户的浏览器。浏览器将这个Session ID存储在Cookie中(注意这里的Cookie仅用于存储Session ID,而非用户信息)。之后,每当用户与服务器进行交互时,浏览器都会将这个Session ID发送给服务器。服务器根据这个Session ID查找对应的Session数据,从而识别用户并提供服务。

  1. 安全性:

Cookie 由于存储在客户端的浏览器中,因此容易受到跨站脚本攻击(XSS)等安全威胁。攻击者可以通过窃取或篡改Cookie中的信息来冒充用户或窃取用户的敏感信息。

Session 相对更为安全,因为数据存储在服务器端,相对较难被攻击者直接访问或篡改。

3.存储内容与大小限制:

Cookie 只能存储简单的字符串数据,如用户名、密码等,且大小受浏览器限制,一般限制在4K的大小。

Session 可以存储更多的数据,没有明确的大小限制,理论上只受内存限制。

4.生命周期的控制:

Cookie 的生命周期可以通过设置过期时间来控制,如果设置了过期时间,那么即使关闭了浏览器,Cookie仍然会保存在本地硬盘中,直到过期时间到达才会被删除;如果没有设置过期时间,那么关闭浏览器时Cookie就会被删除。

Session 的过期取决于服务器的设定,例如可以设置超时限制为10分钟,用户持续请求访问,一直在限制时间内进行保活,那Session就永远不会过期。

详情在CSON 网站搜 :彻底了解Cookie和Session的区别

HashMap 的底层原理?

JDK1.8 之前 HashMap 由 数组+链表 组成。

JDK1.8 后 HashMap 由 数组+链表+红黑树 组成。

使用数组存储KV 键值对,使用链表解决哈希冲突,将发生哈希冲突的节点存储在同一 桶中,形成链表。当链表长度超过8,为了提高查询性能,会将链表转换为红黑树。

HashMap 的put流程?

hashMap添加元素的流程,hashMap在第一次添加元素时会进行扩容,默认容量为16。之后添加的元素,根据该key 的hash值与数组的容量进行按位与计算,定位到该元素的存储位置。然后插入元素的key 和之前的元素相同会替换为新值,返回旧值。

如果插入的元素的数量超过了 hashMap的临界值,会进行扩容。扩容为原来的2倍。并根据新数组容量重新计算所有元素的位置。

临界值为 默认容量 * 0.75加载因子的结果。

如果发生了hash冲突,将该元素插入到桶的末尾。当桶也就是链表的长度大于8并且数组的容量大于等于64时,会将链表转换为红黑树。如果桶中的数量小于6又将红黑树退化为链表。

HashMap为什么不一开始就使用红黑树?

因为成本问题,红黑树的空间消耗是 链表的两倍。

HashMap的转换阈值8是怎么来的?

通常如果 hash 算法正常的话,那么链表的长度也不会很长,那么红黑树也不会带来明显 的查询优势,反而会增加空间负担。所以通常情况下,并没有必要转为红黑树,所以就选择了概率非常小,小于千万分之一概率,也就是长度为 8的概率,把长度 8 作为转化的默认阈值。

链表长度符合泊松分布,各个 长度的命中概率依次递减,当长度为 8 的时候,概率仅为 0.00000006。

HashMap 为什么选择 使用 0.75 作为加载因子?

如果加载因子较大,那么只有当元素填满数组长度时才会选择去扩容,虽然加载因子较大时会提高空间的利用率,但会导致hash碰撞形成链表,导致查询效率变慢。

如果加载因子较小,虽然可以最大程度减少hash冲突,链表长度减少,频繁扩容,空间浪费比较大。

应该是为了空间以及时间上的平衡,才选择0.75作为加载因子。

HashMap初始容量为什么是2的次幂 以及 扩容为什么是2倍的形式?

因为容量是2的次幂可以均匀的分布在数组上、减少hash碰撞,避免形成链表以

降低查询效率。

HashMap 什么情况下会导致内存泄漏的问题?

HashMap 在使用对象作为key时,存入数组后,由于对象的成员被修改了,而hashCode的计算与修改的成员相关,也让hashCode也发生了变化,导致无法再次通过hashCode 取出。这样就造成了内存泄漏。

如何解决?

  1. 使用不可变对象作为hashMap 的key。
  2. 如果要使用一个类作为key,保证hashCode 的计算只与 不可变成员相关。

Comparable 和 Comparator 的区别?

Comparable 和 Comparator 都是用来实现集合中元素的比较、排序的。

Comparable 属于java.lang包,Comparable是在集合内部实现的比较、排序方式。

Comparator 属于java.util包,Comparator 是集合外部实现的比较、排序方式。 Comparator体现了一种策略模式。策略模式就是不改变对象自身,而用一个策略对象 来改变它的行为。

什么是泛型?

泛型是JDK1.5以后出现的安全机制。

泛型:是一种将数据类型明确的工作推迟到创建对象或调用方法时,才明确的特殊类型

在类、接口、方法上申明,可以应用在变量、形参、方法、类、接口上。

泛型的擦除和补偿?

泛型擦除是指在编译时将泛型加上的类型参数剔除。泛型擦除是为了 兼容运行时的类装载器。因为在jdk1.5之前是不认识泛型的,所以为了避免jvm重构 在编译时检查完泛型类型是否匹配后,就对泛型进行了擦除。

泛型补偿是指 对迭代出来的元素自动进行了强制转换。因为在编译时就已经确定了泛型的类型。

sleep 和 wait 有什么区别?

1.sleep 定义在Thread类中,是类方法。Wait定义在Object类中,属于实例方法。

2.在同步代码块中 sleep不会释放锁,wait会释放锁。

3.sleep必须指定参数。

4.sleep(0) 代表当前线程放弃CPU执行权,重新参与争抢Cpu执行权。

wait(0) 代表当前线程进入等待状态,不参与Cpu执行权。

并发的三大特性?

有序性、原子性、可见性。

为什么要使用线程池?

1.降低资源消耗

对已创建的线程重复利用,减少频繁创建和销毁线程。

2.提高响应速度

线程池预先创建一定数量的线程,任务到来时,立马执行任务。

  1. 提高线程的可管理性。例如:线程在一定时间内没有执行任务,就销毁了。

线程池的底层原理?

1.七大参

2.线程池的五大状态

3.线程池如何执行任务的

线程池的工作原理?

1.线程池刚创建时没有任何线程,等任务到来时才会创建线程,当然也可以调用

 prestartAllCoreThreads() 或者 prestartCoreThread() 方法预创建

corePoolSize个 线程。

2.调用execute提交一个任务时,如果当前工作线程数小于核心线程,就创建线程执行 任务。

3.如果工作线程数 大于等于核心线程数,之后的任务都会进入等待队列中缓存。

4.如果等待队列中的任务满了,

有哪些拒绝策略?

AbortPolicy:终止策略,直接抛出异常。

CallerRunsPolicy:由当前线程(main)执行该任务。

DiscardPolicy:忽略此任务(最新的任务),没有处理方式,空实现方法。

DiscardOldPolicy:忽略等待最久的任务。

Synchronized 与 lock 有什么区别?

1.Lock是一个接口,Synchronized是关键字,java的内置实现。

2,Lock 可以感知有没有获取锁,正在获取锁的线程可以响应中断。

  Synchronized 不能感知有没有获取锁,如果线程没有获取锁,会一直等待下去。

3.lock 可实现公平锁、锁可以绑定多个条件。提供更丰富 的 对锁的操作方法。

4.lock可以实现读读共享。

什么是ThreadLocal ?

TreadLocal是一个用于线程范围内共享的变量。线程内使用的变量,线程外独立。

ThreadLocal底层原理?

ThreadLocal底层实现基于它的内部类ThreadLocalMap,每个线程都维护了一个ThreadLocalMap,它是一个基于KV键值对的entry数组,entry对象继承了弱引用,使用threadlocal对象作为他的key,它是弱引用,传递进来的值作为它的value,使用的是强引用。

Thread的set方法,判断当前线程的ThreadLocalMap 是否为null,如果是null则进行初始化。

如果不是null,就将threadlocal对象作为key,传递进来的值作为value,封装到 entry对象并存入到数组中,根据key的hash值按位与 数组长度,得到下标位置。

什么是内存泄漏?

内存泄漏是指 无效对象还在占用着内存。

ThreadLocal 会发生内存泄漏吗?

ThreadLocal内存泄漏是指 当外部强引用被置为null,此时由于entry中的threadLocal对象是弱引用,又被gc回收,导致entry对象中的threadlocal对象变为null,无法访问到entry对象中的value。

为什么ThreadLocal对象设计成弱引用?

ThreadLocal 被设计为弱引用的原因是为了避免内存泄漏。

如果threadLocal的key 被设计为 强引用,那么计时线程执行完毕,ThreadLocal 对象及其对应的value值也可能因为强引用的存在而无法被垃圾回收器回收,从而导致内存泄漏。

什么是强引用、软引用、弱引用、虚引用?

强引用:为变量赋值一个对象,这个引用变量就是强引用。强引用的对象不会被垃圾回收器回收。 当内存空间不足时,就算java虚拟机抛出OutOfMemoryError错误,也不会回收这个对象。

软引用:软引用的对象在内存充足时不会被回收,‌但在内存不足时,‌会被垃圾回收器回收。‌

弱引用:弱引用的对象无论内存是否充足,‌都可能被垃圾回收器回收。‌

虚引用‌虚引用是最弱的引用类型,‌一个对象无论是否有其他类型的引用指向它,‌只要仅仅被一 个虚引用关联,‌那么它随时可能被垃圾回收。‌虚引用主要用于跟踪对象被垃圾回收的活动, ‌它不会对对象的生存周期构成影响,‌也不能通过它来访问对象。‌

了解volatile关键字吗?

  1. volatile 是java提供的轻量级的同步机制。保证共享变量的可见性。被volatile修饰的变量,它的值发生变化时,其他线程立即可见, 避免了脏读。
  2. volatile 禁止了指令重排,可以保证程序的有序性。但由于进制指令重排,所以jvm相关的优化没了,性能偏弱。

Volatile 与 Synchronized 有什么区别?

  1. volatile本质是告诉JVM需要从主存中读取变量的值。 synchronized则是锁定当 前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
  2. volatile 只能用于修饰变量,Synchronized 可以修饰方法、代码块。
  3. Volatile只能保证变量的可见性,不能保证原子性;而synchronized则可以保证 变量的可见性和原子性。
  4. Volatile 不会造成线程阻塞。
  5. Volatile标记的变量不会被编译器优化。

synchronized标记的变量可以被编译器优化。

什么是死锁?

死锁是指2个或2个以上的线程在执行过程中,因为争抢资源,导致互相等待的现象。

死锁产生的四个必要条件:

1.互斥,锁资源只能有一个线程拥有。

2.不可抢占,线程持有锁,别的线程不能占有,需要等当前线程主动释放。

3.线程在持有一个锁资源的同时,请求另一个锁资源。

4.循环等待。

如何解决死锁?

死锁发生了是不可逆的,只有在之前设置一些预防死锁发生的解决方案。

1.注意加锁的顺序,保证每个线程按同样的顺序进行加锁。

2.为锁 设置过期时间。

SpringMVC 的核心组件:

DispatcherServlet

HandlerMapping

HandlerAdapter

ModelAndView

ViewResolver

View

SpringMVC 的工作流程?

Spring 和 SpringMVC 的常用注解有那些?

SpringMVC 常用的注解有 @RequestMapping 。

  1. @Component 标识一个受spring管理的组件。
  2. @Controller 标识一个为 表示层的组件
  3. @Service 标识一个业务层的组件
  4. @Repository 标识一个为 持久层的组件
  5. @AutoWired 自动装配。
  6. @Qualifier("")    具体指定要装配的组件的id值,和AutoWired一起使用。
  7. @RequestMapping 完成请求映射。

Mybatis的${} 和#{} 有什么区别?

MQ 是什么? 有什么作用?

MQ是在应用程序之间进行通信的一种方式。它通过消息传递队列发送和接收消息数据。

设计模式有哪些类型?

常见的设计模式有23种。这些模式可以分为三大类:

创建型:

单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。

结构性:

适配器模式、装饰者模式、代理模式、桥接模式、外观模式、享元模式、组合模式。

行为性:

观察者模式、模版方法模式、命令模式、状态模式、责任链模式、解释器模式、

中介者模式、访问者模式、策略模式、备忘录模式、迭代器模式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值