==和equals区别
- ==对于基本类型来说用于比较数值是否相同,对于引用类型来说用于比较引用地址是否相同。
- 基本类型没有equasl方法,对于引用类型,如果没有重写equals方法,效果同==比较的是引用地址是否相同,如果重写了equals方法,如String类则比较的是内容是否相同。
重载和重写的区别
- 重载发生在一个类中,而重写发生在父子类中。
- 重载是编译时多态,重写是运行时多态。
- 重载要求方法名相同,参数列表不同,与方法的修饰符和返回类型无关;重写要求方法名相同,参数列表相同,方法修饰符的权限需要大于等于被重写方法修饰符权限,方法返回类型必须兼容被重写方法的方法返回值类型。
Java中静态代码块、实例代码块、静态方法和构造方法执行顺序
首先是静态代码块,其次实例代码块、最后构造方法。 juejin.cn/post/738164…
重写equals方法时,为什么还要重写hashcode方法
- 首先是,equals和hashcode方法相互配合用于比较两个对象是否相同
- 如果只重写了equals方法,会出现两个对象equals相同,而hashcode不同,会导致两个对象在hash表中的存储位置不同。
String、StringBuilder、StringBuffer区别
- 线程安全上来说,String底层采用的是final修饰的char型数组,每次对字符串对象的操作都会生成一个新的字符串,所以多线程下是线程安全的,而StringBuilder和StringBuffer每次操作都是在原有字符串的基础上操作,但是StringBuffer每次操作对象都会加锁,因此线程安全,而StringBuilder没有加锁因此线程不安全
- 性能上来说,由于StringBuilder没有加锁因此性能要强于StringBuffer.
String i = ""和String i = new String("")区别
-String i = ""这种形式首先会往字符量常量池中查找是否存在该字符串,如果有则直接返回常量池中的对象地址,如果没有则在常量池中创建一个,并返回地址。String i = new String("")这种形式会直接到堆内存中new一个对象并返回。
抽象类和接口的区别
- 1.从概念上来讲,抽象类是对一类事物进行抽象,描述的是一类事物的属性和行为。而接口是对事物的共有行为进行抽象。
- 2.类是单继承、接口可以多实现。
- 3.抽象类和接口都不能直接实例化对象。
- 4.抽象类中不仅可以包含抽象方法,还可以包含普通方法,且修饰符。接口中只能包含抽象方法和默认方法。
List和Set的区别
- List特点是存储数据有序,且可以重复。
- Set的特点是存储数据无序,且不可以重复。
ArrayList和LinkedList的区别
- ArrayList底层是数组结构,数组结构的特点是在内存中是一块连续的内存空间,因此寻址比较容易继而查询数据很快。用无参构造方法创建的对象,默认初始化容量为0,初次添加元素的时候,会进行扩容,默认是10,后续添加元素是1.5倍扩容。同时从中插入元素,会进行数据的复制和移动,因此插入效率低。
- LinkedList底层是链表结构,链表结构导致数据分散存储内存,因此查询数据效率低,但是插入元素效率高,因为只需要更改指针指向即可。
List如何一边遍历一边删除元素
使用迭代器iterator删除元素
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
// 使用迭代器删除所有元素
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next(); // 必须调用next()来移动到下一个元素,然后才能调用remove()
iterator.remove(); // 调用remove()来删除当前元素
}
System.out.println(list.size()); // 应该输出0
}
如何实现List和数组之间的转换
List转数组利用toArray方法 数组转List利用Arrays.asList方法
HashMap的实现原理
- hashMap操作元素通过Hash算法实现的,存储元素是数组+链表的结构,当添加元素时,会计算key的hash值,并通过某种算法进而计算出对应的数组下标,如果当前下标下存在元素,我们称之为hash碰撞或者hash冲突,然后通过equals方法比较内容是否相同,如果相同则替换为当前元素,如果不相同则直接挂在元素的下方形成一个链表。
- hashMap的初始化容量为16,2倍扩容。
HashMap中的key存储为null,那么key的索引位置在哪
存储在索引下标为0的位置。 来源:www.jb51.net/program/339…
HashMap和HashTable的区别?
- 1.线程安全上,HashTable是线程安全的,HashMap是线程不安全的,因为HashTable每次操作元素的方法都有synchronized同步锁。
- 2.存储元素上,hashMap存储元素的key和value都可以为null,而HashTable存储元素的key和value都不能为null。
- 3.性能上,由于HashTable存在锁的操作,因此性能上比HashMap差。
HashSet的实现原理
hashset的实现原理利用到了HashMap的key的存储原理,也是计算元素的hash值,如果hash值相同,即hash冲突,进而调用equals方法比较内容是否相同,如果相同,则替换元素,否则挂在元素下方。
------------------------------------------异常---------------------------------------------
Exception和Error的区别
- 同:Exception和Error都是Throwable下的子类
- 异:Exception是程序可以处理的异常,分为编译时异常(受检查时异常)和运行时异常(非受检查时异常)。而Error是程序无法处理的异常,如虚拟机内存溢出错误。
编译时异常和运行时异常的区别
- 编译时异常即受检查时异常,即编译时必须要处理的异常,常见的编译时异常有IOException,ClassNotFoundException,FileNotFoundException等。
- 运行时异常即非受检查时异常,即编译时不需要处理的异常。常见的运行时异常有NullPointException,IndexOutOfBoundsException.
throw和throws的区别
throw用于手动抛出一个异常,throws用于声明可能会抛出的异常。
------------------------------------------异常---------------------------------------------
------------------------------------------线程---------------------------------------------
线程的创建方式有哪些
- 继承Thread类重写run方法。
- 实现Runnable接口重写run方法。
- 实现Callable接口重写call方法,这个方法有返回值。通过FutureTask封装callable对象,通过FutureTask.get方法获取返回值。
- 通过线程池创建线程
线程有哪些状态
- NEW:新建状态,线程被创建后还没被调用start方法前的状态。
- RUNNABLE:运行状态,线程调用start方法后,并被jvm调用执行的状态。
- BLOCK:阻塞状态,线程内如等待获取锁的状态。
- TIMED_WAITING:定时等待状态,调用wait有参方法时所处的状态。
- WAITING:无限等待撞他, 调用wait无参方法时所处的状态。
- TERMINATED:终结状态,线程执行完毕所处的状态。
sleep方法和wait方法区别?
- 位置上:sleep是Thread的方法,wait是Object的方法。
- 锁的释放行:sleep方法不会释放锁,wait方法会释放锁。
- 使用范围上:sleep方法可以使用在任何代码块,休眠一段时间,获取到cpu执行权后,会自动恢复执行,而wait方法一般用在同步方法或同步代码块中,必须通过notify或notifyall方法恢复执行。
如何控制线程的执行顺序
1.通过单线程的线程池。 2.通过Thread.join方法。 2.利用CountDownLatch。
多线程如何保证事务
多线程共用一事务,通过代码的方式,手动控制事务。
线程池的创建方式
- 1.通过Executors工具类下的方法创建线程池
- 2.通过ThreadPoolExecutor设置自定义参数创建线程池
ThreadPoolExecutor的核心参数有哪些
- 核心线程数
- 最大线程数
- 线程存活时间
- 线程存活时间对应的单位
- 任务阻塞队列
- 线程工厂
- 拒绝策略
线程池的工作原理
- 当一个任务进入线程池时,首先判断当前线程是否超过核心线程,如果不超过则创建核心线程进行任务的执行。
- 如果超过核心线程数量,则判断工作队列是否已满,如果没有满,则放入队列中。
- 如果队列已满,且线程数不超过最大线程数,则创建最大线程进行任务的执行。
- 如果超过最大线程数,则执行拒绝策略。
拒绝策略有哪些
- AbortPolicy:拒绝当前任务,并抛出异常。
- DiscardPolicy:拒绝当前任务,不抛出异常。
- CallRunsPolicy:使用当前调用线程的线程执行任务,如主线程执行当前任务。
- DiscardOldestPolicy:抛弃队列中的最老的任务,并加入到队列。
如何设置合适的核心线程数和最大线程数
- CPU密集型:一般核心线程数为cpu核心数,最大线程也是cpu核心数。
- IO密集型:因为IO操作需要长时间操作磁盘,因此为了避免长期占用系统资源,可以设置为2倍核心数
线程池都有哪些状态
- RUNNING运行状态,可以接收新任务,可以处理阻塞队列中的任务。
- SHUTDOWN状态,不会接收新的任务,但会处理阻塞队列中的剩余任务。
- STOP状态,会中断正在执行的任务,并会抛弃阻塞队列中的任务。
- TIDYING状态,所有任务执行完毕,活动线程为0,即将终结的状态。
- TERMINATED状态,终结状态。
线程池中的subimt和execute方法的区别
1.submit方法可以提交Runnable和Callable类型的任务,execute只能提交Runnable类型的任务。 2.submit提交的任务发生异常时会内部处理,execute提交的任务发生异常时会抛出异常。
-----------------------------------------线程----------------------------------------------