当前位置: 首页>后端>正文

Java基础笔记

1、面向对象:封装、继承、多态

2、JDK、JRE、JVM之前的区别

JDK:java标准包、包含java编译器、java运行环境以及常用的java类库

JRE:java运行环境,用于运行java的字节码文件

JVM:java虚拟机,JRE的一部分,它是整个java实现跨平台的最核心部分,负责运行字节文件

3、hashcode()与equals()之间的关系

两个对象的hashcode不同,两个对象肯定不同

两个对象的hashcode相同,两个对象可能相同,可能不同

两个对象相同,两个对象的hashcode肯定相同

4、==和equals方法的区别

==:如果是基本数据类型,比较值,如果是引用对象,比较的是引用地址

equals:具体要看各个类重写equals方法之后的比较逻辑,方法内部比较的是字符串中各个字符是否全部相等

5、List和Set

List:有序,可重复,可以存储多个null,可以用迭代器(Iterator)获取全部元素,再遍历,也可以get(下标)获取元素

Set:无序,不可重复,只能存在一个null,只能用迭代器(Iterator)获取全部元素,再遍历

6、ArrayList、LinkedList、Vector区别

ArrayList、Vector底层基于数组,LinkedList底层基于链表

ArrayList适用场景:随机查找,LinkedList适用场景:增删改查

ArrayList和LinkedList都实现了List接口,LinkedList还实现了Deque接口,所以LinkedList还可以用来当做队列使用

Vector是线程安全的,使用了synchronized,实现同步要消耗时间,所以速度要慢

7、ConcurrentHashMap扩容机制

JDK1.7 基于Segment分段实现,每个Segment就是一个小型的HashMap

Java基础笔记,第1张
JDK1.7

JDK1.8 不在基于Segment分段实现

Java基础笔记,第2张
JDK1.8

8、JDK1.7到1.8发生了什么变化

1. 1.7中底层是数组+链表,1.8中底层是数组+链表+红黑树,加入红黑树的目的是提高HashMap插入和查询整体效率

2. 1.8中,只有在链表节点个数大于8个,HashMap长度大于64个的情况下,才会使用红黑树

3. 1.7中链表插入使用的是头插法,1.8中链表插入使用的是尾插法,因为1.8中插入key和value时需要判断链表元素个数,所以需要遍历链表元素个数,所以就正好使用尾插法

4. 1.7中哈希算法复杂,1.8中有了红黑树,所以就简化哈希算法,从而提高效率,节省CPU资源

9、说一下HashMap的Put方法

1. 首先根据传入的Key进行哈希算法与与运算计算出数组下标

2. 如果数组下标的位置元素为空,则将Key和Value封装成Entry对象(1.8封装成Node对象)

3. 如果数组下标的位置元素不为空,则分情况讨论

? 3.1 如果是1.7,先判断是否扩容,若果需要就扩容,如果不需要就将Key和Value封装成Entry对象,并使用头插法插入到链表当中? ? ? ? ? ? ? ?

? 3.2 如果是1.8,当前node节点是链表还是红黑树

? ? a. 如果是红黑树node,则将Key和Value封装成红黑树节点并添加到红黑树中去,在这个过程中会判断红黑树中是否存在当前key,如果存在则更新value

? ? b. 如果是链表node,则将Key和Value封装成链表节点,并使用尾插法插入到链表的最后位置,因为是尾插法,所以要遍历链表,在遍历的过程当中,会查询当前key是否存在,如果存在则更新value,如果不存在,当遍历完链表后,将新链表插入到链表后,会得到当前链表的节点个数,如果节点个数大于等于8,则会将链表转换为红黑树,

? ? c. 将Key和Value封装成node插入到红黑树或链表中之后,再进行判断是否需要扩容,如果需要就扩容,如果不需要就结束PUT方法

10、深拷贝和浅拷贝

深拷贝和浅拷贝就是指对象的拷贝,一个对象中存在两种类型属性,一种是基本数据类型,一种是实例对象引用

1. 浅拷贝就只会拷贝基本数据类型的值,以及实例对象的引用地址

2. 深拷贝既会拷贝基本数据类型的值,也会针对实例对象的引用地址所指向的对象进行复制,深拷贝出来的对象,内部的属性指向的不是一个对象

11、HashMap的扩容机制原理

1.7版本

1.先生成一个新的数组

2.遍历老数组中每个位置上的链表的每个元素

3.取每个元素的key,并根据新数组的长度,计算出每个元素在新数组中的下标

4.将元素添加到新数组当中

5.所有元素转移完成之后,将新数组赋值给HashMap的table属性

1.8版本

1.先生成一个新的数组

2.遍历老数组中每个位置上的链表和红黑树

3.如果是链表,则计算链表中每个元素的数组下标,然后添加到新数组中去

4.如果是红黑树,则先遍历红黑树,计算每个元素在新数组中下标位置

? 4.1 统计每个位置下的元素个数

? 4.2 如果该位置下的元素大于8,则生成一个新的红黑树,并将根节点添加到新数组的对应位置

? 4.3 如果该位置下的元素不大于8,则生成一个新的链表,并将链表的头节点添加到新数组的对应位置

5.所有元素转移完成之后,将新数组赋值给HashMap的table属性

12、CopyOnWriteArrayList的底层原理是怎样的

因为ArrayList是线程不安全的,所以要有一个线程安全的,因此它出现了

CopyOnWriteArrayList的底层也是通过数组实现的,先进行加锁,然后复制一份新的数组,写的时候往新的数组写,读的时候读老的数组,最后写完之后,将老数组指向新数组,然后清除老数组,适用场景:写少读多

13、什么是字节码,采用字节码的好处是什么?

实现了跨平台,提高了代码的执行性能

14、Java中的异常体系

Java中所有异常都来自于顶级父类Throwable

Throwable下有两个子类Exception和Error

Exception又分为运行时异常和非运行时异常

15、什么是反射机制?

Java反射机制是在Java运行状态时,对任意一个类,都能知道他的方法和属性,对任意一个对象,都能够调用他的方法和属性

16、Java反射机制的优缺点?

优点:运行期类型的判断,动态加载类,提高代码灵活性

缺点:性能慢,通知JVM需要做的事儿,比直接运行Java代码慢多了

17、Java反射机制使用场景?

框架设计的核心,动态代理的核心

18、实现Java反射的方式?

1.通过new对象? new AA()

2.通过路径? Class.forName()

3.通过通过类名? AA.Class.getName()

19、HashMap在多线程情况下,会有什么问题?

HashMap在多线程情况下,JDK1.7版本时,会引起死链问题对象丢失问题,JDK1.8通过尾插法解决了死链问题,但仍存在对象丢失问题,所以多线程情况下尽量使用HashTable或ConCurrentHashMap线程安全的类

20、ArrayList底层原理

1.ArrayList构造的时候,如果没有传指定容量大小,则会生成一个空数组,如果指定了容量,则构造出对应容量大小的数组

2.在添加元素时,会先判断容量是否足够,默认是10,如果不够则会扩容,扩容按1.5倍扩容,容量足够后,再把元素加到数组中

3.在添加元素时,如果指定了下标,则先检查下标是否越界,然后再判断容量是否足够,不够则扩容,然后再把新元素添加到指定位置,如果该位置后面还有元素,则后移

4.在获取元素时,先检查数组下标是否越界,然后从数组中取出对应位置的元素


https://www.xamrdz.com/backend/3yh1934412.html

相关文章: