一. java
先参考之前总结的java面试常考题
-
Java基础:集合类(put扩容之类)
【ArrayList;vector;hashmap;hashtable】
参考 -
多线程
【创建线程;线程状态;线程停止;sleep休眠;yield礼让;join合并;优先级;守护线程;同步锁;死锁】
参考 -
hashmap线程不安全的原因;concurrenthashmap为什么线程安全
hashmap底层图片;hashmap和hashtable区别5点
hashmap线程不安全:插入;resize;删除的时候
concurrenthashmap线程安全
concurrenthashmap线程安全 -
volatile关键字对可见性的保证;
参考 -
对锁有了解吗,我说volatile和synchronized,解释 volatile怎么加锁的
volatile:能保证可见性和有序性,不能够保证原子性JVM 会需要强制从内存中读写数据,保证了可见性。说到可见性,Java就是利用volatile来提供可见性的。 当一个变量被volatile修饰时,那么对它的修改会立刻刷新到主存,当其它线程需要读取该变量时,会去内存中读取新值。而普通变量则不能保证这一点。
JVM 会为 volatile 变量的读/写创建一个屏障,阻止指令的重排,保证了有序性。JMM是允许编译器和处理器对指令重排序的,但是规定了as-if-serial语义,即不管怎么重排序,程序的执行结果不能改变。但是在多线程中,指令重排可能导致问题,引用了volatile变量,就不能指令重排。 -
String和StringBuffer区别,String为什么不能被修改;
String为什么不能被修改 -
线程池基本参数
参考corePoolSize: 线程池核心线程个数
workQueue: 用于保存等待执行任务的阻塞队列
maximunPoolSize: 线程池最大线程数量【包括核心线程数】
ThreadFactory: 创建线程的工厂
RejectedExecutionHandler: 队列满,并且线程达到最大线程数量的时候,对新任务的处理策略
keeyAliveTime: 空闲线程存活时间
TimeUnit: 存活时间单位 -
面向对象与面向过程
参考 -
Java中类变量[静态变量]和实例变量的区别
参考:生命周期;调用方式;存储位置 -
抽象类和接口区别
抽象类和接口基础参考区别如下:1) 在抽象类中可以写非抽象的方法,从而避免在子类中重复书写他们,这样可以提高代码的复用性,这是抽象类的优势;接口中只能有抽象的方法。2) 一个类只能继承一个直接父类,这个父类可以是具体的类也可是抽象类;但是一个类可以实现多个接口。
-
反射怎么用
-
对象怎么创建
参考 -
异常种类,
异常种类 -
Java垃圾回收
GC机制具体知识讲解
参考
程序结束之后对象会被怎么处理(垃圾回收)什么是堆内存?堆是在 JVM 启动时创建的,主要用来维护运行时数据,如运行过程中创建的对象和数组都是基于这块内存空间。
什么是垃圾?无任何对象引用的对象。
怎么判断是否是垃圾? 引用计数法;可达性分析法,可以作为GCRoot的是哪些对象。
有哪些方法回收这些垃圾?标记清理法;标记整理法;复制法;分代收集法
什么是分代回收机制?新生代;老年代;永久代。minor GC;major GC -
数组和链表的区别,插入数据时的复杂度
参考数组利用下标定位,时间复杂度为O(1),链表定位元素时间复杂度O(n);
数组插入或删除元素的时间复杂度O(n),链表的时间复杂度O(1)。 -
红黑树:每个节点要么是红色,要么是黑色。
根节点必须是黑色
红色节点不能连续(也即是,红色节点的孩子和父亲都不能是红色)。
对于每个节点,从该点至null(树尾端)的任何路径,都含有相同个数的黑色节点。 -
为什么有JAVA虚拟机
参考JVM是一种规定好的标准规范, 定义了.class文件在其内部运行的相关标准和规范。
-
hashmap的底层实现
底层简单介绍参考
底层代码详细介绍参考
参考博客 -
继承
基础知识理解(1)子类的对象可以调用父类中的(public protected)属性和方法 ,当做自己的来使用
(2)子类可以添加自己独有的属性和方法的。
(3)子类可以重写父类的方法。子类从父类中继承过来的方法不能满足子类需要,可以在子类中重写(覆盖)父类的方法 ,更多指的是内容。
(4)单继承
(5)继承在内存中的存储形式。剥洋葱。
(6)子类中的构造函数中,默认调用了父类的构造函数
参考知识点
参考实例 -
多态的理解
基础知识理解同一个对象, 体现出来的多种不同形态(身份)
-
举个多态的例子,用Java多,那用Java写个多态。
Person和Teacher的类 -
并发编程的三大特性
原子性;可见性;有序性 -
- 拆箱装箱
拆箱装箱参考
装箱就是:自动将基本数据类型转换为包装器类型;拆箱就是:自动将包装器类型转换为基本数据类型。
只有double和float的自动装箱代码没有使用缓存,每次都是new 新的对象,其它的6种基本类型都使用了缓存策略。
使用缓存策略是因为,缓存的这些对象都是经常使用到的(如字符、-128至127之间的数字),防止每次自动装箱都创建一次对象的实例。
而double、float是浮点型的,没有特别的热的(经常使用到的)数据的,缓存效果没有其它几种类型使用效率高。Integer.valueOf("")
和Integer.parseInt("")
内部实现是一样的,它们之间唯一的区别就是Integer.valueOf(“”)
返回的是一个Integer对象,而Integer.parseInt(“”)
返回的是一个基本类型的int。 - 拆箱装箱
-
深拷贝浅拷贝
参考浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。
深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。 -
Java集合类中你了解哪些数据结构?这些结构有什么特点,适用于什么场景?
常用集合参考
HashSet和TreeSet区别
Collection Map
存储的都是value 存储的是以key-value形式存在
List Set
有序可重复 无序无重复 key无需无重复 value无需可重复
List:ArrayList; Vector;. LinkedList; Stack;Queue;
Set:HashSet; TreeSet; LinkedHashSet
Map:HashMap; Hashtable; TreeMap
-
你刚刚提到的几个结构哪些是线程安全的,哪些是非线程安全的?非线程安全的结构如果想实现线程安全怎么做?
哪些安全,哪些不安全
对于不安全的集合处理方式 -
Java垃圾回收有哪些算法?【参考31题】分代收集算法工作原理是什么样的呢?
标记清除算法;复制算法;标记整理算法;分代收集算法
-
for和for each区别:
for和for each区别
for和for each区别在ArrayList和LinkedList中的应用
Random Access接口
for、foreach和Iterator遍历foreach循环是利用迭代器的使用循环。
foreach适用于只是进行集合或数组遍历,for则在较复杂的循环中效率更高。
foreach不能对数组或集合进行修改(添加删除操作),如果想要修改就要用for循环。 -
StringBuffer 和 StringBuilder 的区别
StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都 会引发新的String对象的生成;StringBuffer和StringBuilder则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。
区别在于StringBufferd支持并发操作,线性安全的,适 合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。 -
HashMap 和 HashTable 的区别
参考博客 -
方法重载和重写
重载,一般是用于在一个类内实现若干重载的方法,这些方法的名称相同而参数形式不同。
重写(覆盖)了一个方法,以实现不同的功能。一般是用于子类在继承父类时,重写(重新实现)父类中的方法。
方法的重写与方法的重载的区别:
(1)方法的重写参数一定要相同;方法重载参数一定不同
(2)方法的重写是子类重写父类的方法,至少要两个类;而方法的重载是发生在一个类中。
(3)方法的重写返回值类型必须相同;而方法的重载的返回值类型可以相同也可以不同。
(4)方法的重写要求方法的访问权限不小于父类中被覆盖方法的访问权限;而方法的重载对权限不作要求。
方法的重写与方法的重载的相同点:
唯一的相同点就是方法名称必须相同。 -
重载:参数顺序不同是否是重载,返回类型不同是否是重载
概念:一个类中的一组方法,相同的方法名字 ,不同的参数列表 ,这样的一组方法构成了方法重载。
参数列表的不同体现在哪里?
参数的个数;参数的类型;参数的顺序。
返回类型不能重载。 -
多线程按照顺序打印数字
暂时参考 -
如何判断对象是否进入老年代
-
Threadlocal变量
-
对线程池了解,常见的类方法,常见参数
自己写的博客参考
线程池的继承关系;系统封装的线程池
为什么使用线程池
线程池
线程池理解为什么要区分核心线程和非核心线程
创建线程是有代价的,不能每次要执行一个任务时就创建一个线程,但是也不能在任务非常多的时候,只有少量的线程在执行,这样任务是来不及处理的,而是应该创建合适的足够多的线程来及时的处理任务。随着任务数量的变化,当任务数明显很小时,原本创建的多余的线程就没有必要再存活着了,因为这时使用少量的线程就能够处理的过来了,所以说真正工作的线程的数量,是随着任务的变化而变化的。 -
jvm参数,默认初始值
-
final和static关键字
参考final意味着”不可改变的”,一般应用于数据、方法和类。修饰:修饰变量;修饰属性;修饰方法;修饰类本身。
static的意思是“静态的”,一个类中仅有一份。可以修饰:修饰属性;修饰方法;修饰块;修饰类(内部类)。 -
Set中元素如何做到不重复的(如何实现不可重复)
参考Set的底层是HashMap,HashMap在put一个Key时会判断,将要放进去的Key的hash值与 目前HashMap中定位到的那个Key的hash值比较。
如果hash值相当,继续比较 这两个对象的地址或者内容是否相当。
如果相当:判断出来要添加的Key与HashMap中的Key重复,把Value的值给替换成最新的。 -
Object方法有哪些
参考 -
数据结构二叉树相关知识
各类树的简介
平衡二叉树平衡机制
红黑树
红黑树和平衡二叉树区别 -
常见的数据结构
一些常见的数据结构: -
Synchronized的同步方法和同步块的区别:
同步方法默认使用this或者当前类做为锁。
同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不是整个方法。
同步方法使用synchronized修饰,而同步代码块使用synchronized(this){}修饰。 -
类执行过程
---------静态元素加载:类加载的时候就加载了
1.先加载父类,父类产生自己的静态空间
2.执行父类静态块
3.加载子类,子类产生自己静态空间
4.执行子类静态块
-----------new Person:new之后才加载
5.开辟对象空间
6.加载父类普通方法等
7.执行父类块
8.加载子类普通方法
9.执行子类块
10.将对象空间地址引用给变量存储 -
java异常
异常和错误参考
运行时异常和非运行时异常:对于非运行时异常必须进行处理;对于运行时异常可以进行处理,也可以不进行处理,通常情况下不进行处理,但是自己在写代码时注意逻辑不要让其出现异常错误:常见的有程序进入死循环,内存泄漏等。这种情况,程序运行时本身无法解决,只能通过其他方法干预。对应的类为Error类
异常:常见的有除数为0,数组越界等。这种情况,不向错误那样,程序运行时本身可以解决,由异常代码调整程序运行方向,使程序仍可继续运行直至正常结束。对应的类为Exception类。
异常和错误的区别是:异常能被程序本身可以处理,错误是无法处理
public class Main34 extends Main33{
public static void main(String[] args) throws Exception {
int[] arr= new int[]{1,2,3};
try {
System.out.println(arr[4]);
}catch (Exception e){
System.out.println("cdjf");
e.printStackTrace();
}
System.out.println("dfj");
}
/*
cdjf
dfj
java.lang.ArrayIndexOutOfBoundsException: 4
at Main34.main(Main34.java:12)
*/
- throws和throw区别
参考1、throws出现在方法函数头;而throw出现在函数体。
2、throws表示出现异常的一种可能性,并不一定会发生这些异常;throw则是抛出了异常,执行throw则一定抛出了某种异常对象。
3、两者都是消极处理异常的方式(这里的消极并不是说这种方式不好),只是抛出或者可能抛出异常,但是不会由函数去处理异常,真正的处理异常由函数的上层调用处理。
二. 手撕代码
-
编程:股票最大利润
参考 -
算法.数组中出现次数超过一半的数字
参考 -
自己创建一个单链表,返回中间结点的值
先求size,然后求出中间的位置,遍历得到中间节点。
-
算法题青蛙跳格子
参考 -
算法题:罗马字符转整数
参考 -
两个list合并成一个有序无重复的list
参考:把相等的时候单独拿出来即可 -
二叉树的遍历
参考 -
算法题:一个排列好的数组输出所有不相同数字的个数
用set
-
算法题:输入{’‘abc’’,’‘bac’’,’‘cab’’,’‘atc’’,’‘act’’,’‘aac’’,’‘fbc’’};
输出二维数组每一行为相同字母拼接成的字符串{{’‘abc’’,’‘bac’’,’‘cab’’},{’‘atc’’,’‘act’’
},{’‘aac’’},{’‘fbc’’}}
利用排序,然后hashmap -
按序增长的一个数组求出小于m的最大的数
参考 -
一个链表中删除一个值返回这个链表
参考 -
单例设计模式
详细介绍参考饿汉式:三步走,创建时直接实例化
懒汉式:修改上面 -
JVM加载过程
加载-----连接(验证;准备;解析)-----初始化
下面的参考是具体的理解:
JVM分为三个区:栈;堆;方法区
java栈中程序的运行
java程序运行的完整过程自己理解的堆和方法区:方法区中的字节码文件,作为一个类模板。堆中存放的是new出来的对象,里面是方法区的复制品,对于属性以及变量等参数是对象实例自己的。但是当运行方法的时候,是映射到堆中指向方法区中的方法区运行的。
-
多线程同步的方式
java线程同步参考 -
手撕代码:给一个字符串,找出最长的不重复的子串;
参考 -
手撕代码:力扣41 困难难度,缺失的第一个整数
参考 -
对含有重复数字的数组去重并排序
去重参考可以用hashset么
-
快排
代码参考 -
排序算法及时间复杂度,写快排,快排是否稳定
参考
冒泡排序
快排
排序算法稳定性的理解
插入排序法
选择排序算法
归并排序
堆排序算法 -
最大不重复子串,说思路,时间复杂度
参考 -
输入一个字符串,如“127.0.0.1”,判断是否是十进制表示的ipv4地址
-
输入一个数组{1,2,3,2,2,4,4,1};输出数组中数字重复出现的最大次数,写出它的测试用例
注意hashmap的遍历~以及包装类和基本数据类型的拆箱和装箱
-
代码题:滑动窗口最大值
参考 -
代码题:两个字符串求最长公共子串
-
字符串变形。“Hello World"变形后就变成了"wORLD hELLO”
参考