Java面试题
1.Java8新特性
https://blog.csdn.net/sanri1993/article/details/101176712
2.jdk1.7和1.8的区别:
添加了红黑树,增加查询效率
3.jvm
类装载器(ClassLoader)
主要负责加载class文件,是否能执行主要取决于执行引擎(execution engine)它是负责执行被加载类中包含的指令。有两种类加载器分别为启动类加载器和用户自定义类加载器,然而启动类加载器是JVM实现的一部分,用户自定义类加载器是Java程序一部分。
本地接口(native interface)
作用是融合不同的编程语言为Java所用,注意底层是C、C++写的,学习JVM时了解C语言一些更好,最起码能看懂,这个方法的行为就是native method stack中登记native方法,然后在execution engine执行时加载native libraries的。
Java堆(Heap)
是Java虚拟机所管理的内存中最大的一块,在虚拟机启动时创建。线程共享,此内存区域的唯一目的就是存放对象实例。
方法区(Method Area)
线程共享,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
程序计数器(Program Counter Register)
线程私有,是一块较小的内存空间,它的作用可以看做是当前线程所执行的字节码的行号指示器,也可以当作一个指针。
JVM栈(JVM Stacks)
线程私有,生命周期与线程相同。
虚拟机栈描述的是Java方法执行的内存模型:每个方法被执行的时候都会同时创建一个栈帧(Stack Frame)用于存储局部变量表、操作栈、动态链接、方法出口等信息。每一个方法被调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。
本地方法栈(Native Method Stacks)
线程私有,与虚拟机栈所发挥的作用是非常相似的,其区别不过是虚拟机栈为虚拟机执行Java方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的Native方法服务。
PS: Native Method就是一个java调用非java代码的接口
https://baijiahao.baidu.com/s?id=1662378045738605424&wfr=spider&for=pc
https://www.cnblogs.com/riches/p/11912048.html
https://blog.csdn.net/qq_41701956/article/details/80020103
https://blog.csdn.net/qq_41701956/article/details/100074023
4.gc算法(垃圾回收算法)
GC首先要知道GC的作用域是在方法区(method area)和堆(heap)的GC垃圾回收它是Java核心技术,它是怎么实现的呢,主要通过确定对象引用来判断是否收集该对象,我们平时常用的方法引用计数和对象引用便利两种方法的。
1、标记清除算法
标记-清除算法分为标记和清除两个阶段。该算法首先从根集合进行扫描,对存活的对象对象标记,标记完毕后,再扫描整个空间中未被标记的对象并进行回收
标记-清除算法的主要不足有两个:
效率问题:标记和清除两个过程的效率都不高;
空间问题:标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,因此标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
2、复制算法
复制算法将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。这种算法适用于对象存活率低的场景,比如新生代。这样使得每次都是对整个半区进行内存回收,内存分配时也就不用考虑内存碎片等复杂情况,只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
事实上,现在商用的虚拟机都采用这种算法来回收新生代。因为研究发现,新生代中的对象每次回收都基本上只有10%左右的对象存活,所以需要复制的对象很少,效率还不错。实践中会将新生代内存分为一块较大的Eden空间和两块较小的Survivor空间 ,每次使用 使用空间(Eden)和其中一块保留空间(Survivor)。当回收时,将Eden和Survivor中还存活着的对象一次地复制到另外一块Survivor空间上,最后清理掉Eden和刚才用过的Survivor空间。HotSpot虚拟机默认Eden和Survivor的大小比例是 8:1,也就是每次新生代中可用内存空间为整个新生代容量的90% ( 80%+10% ),只有10% 的内存会被“浪费”。
https://www.jianshu.com/p/3fc4450e1bbd
5.static和final关键字
1、static是一个修饰符,用于修饰成员。(成员变量,成员函数)static修饰的成员变量 称之为静态变量或类变量。
2、static修饰的成员被所有的对象共享。
3、static优先于对象存在,因为static的成员随着类的加载就已经存在。
4、static修饰的成员多了一种调用方式,可以直接被类名所调用,(类名.静态成员)。
5、static修饰的数据是共享数据,对象中的存储的是特有的数据。
也就是说,有static修饰的数据无论把该类实例化多少个,static修饰的数据都只存在一个
比如这里,调用的t1.i和t1.j,但是被t2所修改后,即使调用t1也是t2修改后的数据
public class Test1 { int id; static String i; static String j; }
public class ClassMain { public static void main(String[] args) { Test1 t1=new Test1(); Test1 t2=new Test1(); Test1 t3=new Test1(); t1.id=2; t2.id=3; t3.id=4; t1.i="张"; t1.j="三"; t2.i="李"; t2.j="四"; System.out.println(t2.id+t1.i+t1.j); } }
https://www.cnblogs.com/marsitman/p/11192096.html
在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)。
当用final修饰一个类时,表明这个类不能被继承。
当用final修饰一个方法时,表明子类是不能够存在和父类一模一样的方法的,子类不能重写父类的该方法。
final成员变量表示常量,只能被赋值一次,赋值后值不再改变。和static不同,final赋值的属性一旦赋值不可改变,static复制的属性一旦赋值可以改变
https://www.cnblogs.com/xuelisheng/p/11158110.html
6.int和integer
- Integer是int的包装类;int是基本数据类型;
- Integer变量必须实例化后才能使用;int变量不需要;
- Integer实际是对象的引用,指向此new的Integer对象;int是直接存储数据值 ;
- Integer的默认值是null;int的默认值是0。
https://blog.csdn.net/chenliguan/article/details/53888018
7.程序的结构
1、选择结构:用于判断来给定的条件,根据判断的结果判断某些条件,根据判断的结果来控制程序的流程。
2、循环结构:在程序中需要反复执行某个功能而设置的一种程序结构。它由循环体中的条件,判断继续执行某个功能还源是退出循环。
3、顺序结构的程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行。
https://zhidao.baidu.com/question/561343838.html
一.集合
https://blog.csdn.net/zhangqunshuai/article/details/80660974
https://blog.csdn.net/feiyanaffection/article/details/81394745
8.ArrayList和LinkedList区别
1、数据结构不同
ArrayList是Array(动态数组)的数据结构,LinkedList是Link(链表)的数据结构。
2、效率不同
当随机访问List(get和set操作)时,ArrayList比LinkedList的效率更高,因为LinkedList是线性的数据存储方式,所以需要移动指针从前往后依次查找。
当对数据进行增加和删除的操作(add和remove操作)时,LinkedList比ArrayList的效率更高,因为ArrayList是数组,所以在其中进行增删操作时,会对操作点之后所有数据的下标索引造成影响,需要进行数据的移动。
3、自由性不同
ArrayList自由性较低,因为它需要手动的设置固定大小的容量,但是它的使用比较方便,只需要创建,然后添加数据,通过调用下标进行使用;而LinkedList自由性较高,能够动态的随数据量的变化而变化,但是它不便于使用。
4、主要控件开销不同
ArrayList主要控件开销在于需要在lList列表预留一定空间;而LinkList主要控件开销在于需要存储结点信息以及结点指针信息。
https://www.php.cn/faq/415621.html
9.arraylist扩展机制
总的来说就是分两步:1、扩容
把原来的数组复制到另一个内存空间更大的数组中
2、添加元素
把新元素添加到扩容以后的数组中
ArrayList
没有缩容。无论是remove
方法还是clear
方法,它们都不会改变现有数组elementData
的长度。但是它们都会把相应位置的元素设置为null
,以便垃圾收集器回收掉不使用的元素,节省内存。
https://www.cnblogs.com/SunArmy/p/9844022.html
10.vector集合
ArrayList、Vector、LinkedList类均在java.util包中,均为可伸缩数组。
1)ArrayList和Vector都是基于存储元素的Object[] array来实现的,它们会在内存中开辟一块连续的空间来存储,因此支持通过下标来访问元素,同时索引数据的速度比较快,但是在插入和删除元素时速度比较慢;LinkedList是采用双向链表来实现的,对数据的索引需要从头开始遍历,因此用于随机访问的效率比较低,但是插入和删除的效率较高。
2)ArrayList和Vector都有一个初始化的容量的大小,但里面存储的元素超过这个大小时就动态的扩充它们的存储空间,ArrayList默认扩充为原来的1.5倍(没有方法可以设置扩充空间的大小),Vector默认扩充为原来的2倍(每次扩充空间的大小可是设置)
3)Vector是线程安全的,ArrayList和LinkedList不是线程安全的。ArrayList和Vector最大的区别就是synchronized(同步)的使用,ArrayList的方法都不是同步的,但Vector的绝大部分方法都是直接或者间接同步的,因此Vector的性能略逊于ArrayList。
4)在实际使用中,若对数据的主要操作是索引或者只在集合的末端增加、删除元素时,使用ArrayList和Vector效率较高;若对数据的操作主要为在指定位置的插入或者删除时,使用LinkedList效率比较高;当在多线程中使用容器时,选用Vector较为安全。
https://www.cnblogs.com/0820LL/p/9665811.html
11.hashmap结构,为什么用的是链表,为什么用的是数组
首先每一个元素都是链表的数组,当添加一个元素(key-value)时, 就首先计算元素key的hash值,以此确定插入数组的位置,但是可能存在同一hash值的元素已经被放到数组的同一位置,这是就添加到同一hash值的元素的后面,他们在数组的同一位置形成链表,同一链表上的Hash值是相同的,所以说数组存放的是链表,而当链表长度太长时,链表就转换为红黑树这样大大提高了查找效率。
当链表数组的容量超过初始容量的0.75时,再散列将链表数组扩大2倍,把原链表数组的元素搬移到新的数组中
https://www.cnblogs.com/sxkgeek/p/9341350.html
12.hashmap(数组)和hashset(数组加链表)的区别
java最基本的两种数据结构:数组和链表的区别:
数组易于快速读取(通过for循环),不便存储(数组长度有限制);链表易于存储,不易于快速读取。
哈希表的出现是为了解决链表访问不快速的弱点,哈希表也称散列表。
HashSet是通过HasMap来实现的,HashMap的输入参数有Key、Value两个组成,在实现HashSet的时候,保持HashMap的Value为常量,相当于在HashMap中只对Key对象进行处理。
HashMap的底层是一个数组结构,数组中的每一项对应了一个链表,这种结构称“链表散列”的数据结构,即数组和链表的结合体;也叫散列表、哈希表。
https://www.cnblogs.com/codercui/p/6841730.html
13.hashset和treemap的区别
https://blog.csdn.net/sinat_25444819/article/details/102457592
14.hashmap和hashtable区别
https://www.cnblogs.com/williamjie/p/9099141.html
15.排序算法
1、冒泡排序(Bubble Sort):前一个值和后一个值比较大小,小的放在前面,经过l.length次从头到尾的循环
public int[] maopao(int[] l){ for(int i=0;i<l.length-1;i++){ for (int j=0;j<l.length-1;j++){ //前一个值和后一个值比较,如果后一个值小则互换位置 if (l[j]>l[j+1]){ int temp=l[j]; l[j]=l[j+1]; l[j+1]=temp; } } } return l; }
2、选择排序(Selection Sort):选择第一个值,然后遍历后面的值,一个一个和后面的值比较哪个小,最后把最小的放在前面,然后再从第二个开始比较找最小,以此类推一直找到最后一个
//选择排序 public int[] xuanze(int[] l){ int minIndex; int temp; for (int i=0;i<l.length-1;i++){ minIndex=i; for (int j=i+1;j<l.length;j++){ // 遍历 i+1~length 的值,找到其中最小值的位置 if (l[j]<l[minIndex]){ minIndex=j; } } // 交换当前索引 i 和最小值索引 minIndex 两处的值 temp=l[i]; l[i]=l[minIndex]; l[minIndex]=temp; } return l; }
3、插入排序(Insertion Sort):选择第二个值,和前面的值比较,如果前面的值大于该值,则换位置,然后选择第三个值,和前面一个值比较,如果
前面的值大于该值则换位置,在和第一个值比较,如果第一个值大于该值则换位置,以此类推
//插入排序 public int[] charu(int[] l){ int[] p; int preIndex; int current; for (int i=1;i<l.length;i++){ preIndex=i-1;//前一个值 current=l[i];//选择的值 //如果前一个值比选择的值大则换位置,然后再往前看一个值,如果比选择的值大则换位置,直到第一个值为止 while (preIndex>=0 && l[preIndex] > current){ l[preIndex+1]=l[preIndex]; preIndex--; } //将选择的值放到前一个值的后面 l[preIndex+1]=current; } return l; }
4、希尔排序(Shell Sort)
5、归并排序(Merge Sort)
6、快速排序(Quick Sort)
7、堆排序(Heap Sort)
8、计数排序(Counting Sort)
9、桶排序(Bucket Sort)
10、基数排序(Radix Sort)
https://www.cnblogs.com/onepixel/articles/7674659.html
16.查找算法
https://www.iteye.com/blog/xiaojun-it-2291852
17.set、map、list等集合
https://blog.csdn.net/daily11/article/details/51086245
18.集合和数组的区别
数组:
数组:可以用来保存多个基本数据类型的数据,也可以用来保存多个对象。
数组:的长度是不可改变的,一旦初始化数组时就指定了数组的长度(无论是静态初始化还是动态初始化)。
数组:无法保存具有映射关系的数据。
集合:
集合:是只用于存储数量不等的对象。
集合:的长度是可变的。
集合:可以保存具有映射关系的数据。
https://www.cnblogs.com/hewanli/p/12306479.html
19.集合和数据相互转换
数组转换为集合:
Arrays.asList(数组)
集合转换为数组:
集合.toArray();
https://www.cnblogs.com/aspirant/p/10396220.html
20.网络数据模型
https://www.cnblogs.com/fakeCoder/p/5093744.html
21.网络传输协议
https://www.cnblogs.com/wangcp-2014/p/10083565.html
22.tcp三次握手四次挥手
https://baijiahao.baidu.com/s?id=1654225744653405133&wfr=spider&for=pc
23.socket和serversocket区别
https://www.cnblogs.com/mareymarey111/archive/2011/12/08/2280253.html
二、线程
https://www.cnblogs.com/jmsjh/p/7762034.html
24.线程和进程
https://www.cnblogs.com/yuxiang1/p/10608497.html
25.线程的创建方式
https://www.cnblogs.com/htyj/p/10848646.html
26.线程的周期
https://www.cnblogs.com/marsitman/p/11228684.html
27.线程池
https://www.cnblogs.com/superfj/p/7544971.html
28.线程.run和.start的区别
https://blog.csdn.net/kapukpk/article/details/53008516
这里应该是cpu
29.线程优先级
https://blog.csdn.net/qq_35400008/article/details/80219947
30.线程调度
https://www.iteye.com/blog/youyu4-2351235
31.Lock与synchronized区别
3.LOCK和SYNCHRONIZED的选择
(1)lock是一个接口,而synchronized是java的关键字,synchronized是内置的语言实现;
(2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而lock在发生异常时,如果没有主动通过unlock()去释放锁,则很可能造成死锁现象,因此使用lock()时需要在finally块中释放锁;
(3)lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不讷讷狗狗响应中断
(4)通过lock可以知道有没有成功获取锁,而synchronized却无法办到
(5)lock可以提高多个线程进行读操作的效率
在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而竞争资源非常激烈是(既有大量线程同时竞争),此时lock的性能要远远优于synchronized。所以说,在具体使用时适当情况选择。
https://msd.misuland.com/pd/3255817997595448438
synchronized可以修饰什么
32.公平锁和非公平锁
https://baijiahao.baidu.com/s?id=1663027682439855657&wfr=spider&for=pc
33.乐观锁和悲观锁
https://www.jianshu.com/p/d2ac26ca6525
34.死锁
https://blog.csdn.net/hd12370/article/details/82814348
35.Java多线程之线程交互
https://www.cnblogs.com/linjiqin/p/3208901.html
36.转发和重定向的区别
https://blog.csdn.net/weixin_40001125/article/details/88663468
37.mysql索引
https://zhuanlan.zhihu.com/p/29118331
38.mysql实现分页
https://www.cnblogs.com/nickup/p/9758691.html
39.mysql存储引擎
myisam在单方面比如只查询或者是只添加
innodb在多方面支持
https://www.cnblogs.com/aikutao/p/11207365.html
40.b+树、红黑树、二叉树概念
https://www.cnblogs.com/Ronaldo-HD/p/9849708.html
41.接口和抽象类的区别
https://blog.csdn.net/csdnlijingran/article/details/88410948
42.面向对象三大特征
https://blog.csdn.net/weixin_41922887/article/details/82595246
三、i/o流
https://blog.csdn.net/sinat_37064286/article/details/86537354
https://www.cnblogs.com/joyco773/p/7966320.html
四、j2EE
https://www.cnblogs.com/whtydn/p/4965966.html
非必要选项:
43.redis(缓存穿透、缓存雪崩)布隆过滤器,多路复用模型和非阻塞模型