==和equals区别?
==: ==比较的是栈中的内容, 基本数据类型比较的是值, 引用类型比较的是内存地址
equals: Object的equals方法是用==实现的, 用法一样, 但是通常会重写该方法, 比如string重写后, 比较的是值内容
hashCode和equal关系?
hashCode相当于对象的指纹信息, 但是java做不到这么绝对, 但是还是能提前做一下判断
- 如果两个对象hashCode不同, 肯定是两个不同对象
- 如果两个对象hashCode相同, 不一定同一个对象
- 如果两个对象相等, 他们hashCode一定相同
equals默认是比较引用地址, 通常会重写
在java一些集合的实现, 判断对象是否相等, 会先比较两个对象的hash, 如果hash不同, 直接认定两个对象不同, 如果hash相同, 再调用equals进一步比较, 因为equals相对hash比较重
如果重写了equals, 通常也要重写hash
ArrayList和LinkList区别?
ArrayList底层结构是数组, 是一块连续的内存空间, 对内存要求更高. 随机访问性能更高, 中间增删改性能差, 需要拷贝后面所有元素
LinkList底层结构是链表, 增删改性能差, 查询只能依次遍历下一个节点.LinkList还实现了Deque, 可以当做队列
ConcurrentHashMap扩容机制, jdk7和jdk8区别?
JDK 1.7:
- 线程安全: JDK 1.7中ConcurrentHashMap使用了分段锁(Segment)的机制。整个哈希表被分成多个段,每个段都拥有一个独立的锁。在进行读操作时,只需要锁住对应的段,其他段的读操作可以并发执行。但在进行写操作时,需要锁住所有段,保证线程安全。
- 扩容策略:JDK 1.7 的扩容是通过段来实现的,每次只扩容一个段。在进行扩容时,首先创建一个新的段数组,然后将原有数组中的段逐个迁移到新数组中。
JDK 1.8:
- 线程安全:JDK 1.8中, 使用CAS和synchronized同步块保证线程安全。相比1.7的分段锁,JDK1.8使用更细粒度的锁,对桶(buckets)进行加锁,而不是整个段。
- 扩容策略: 当某个线程进行put时,如果发现ConcurrentHashMap正在进行扩容那么该线程一起进行扩容; 如果某个线程put时,发现没有正在进行扩容,则将key-value添加到ConcurrentHashMap中,然后判断是否超过阈值,超过了则进行扩容.ConcurrentHashMap是支持多个线程同时扩容的, 在转移元素时,先将原数组分组,将每组分给不同的线程来进行元素的转移,每个线程负责一组或多组的元素转移工作.
String, StringBuffer, StringBuilder区别?
- String: 不可变, 如果尝试修改, 会生成新的字符串
- StringBuffer: 可变, 线程安全
- StringBuilder: 可变, 线程不安全, 效率更高, 单线程可用
范型extends和super区别
<? extends T> 表示包括T在内的所有子类
<? super T> 表示包括T在内的所有T的父类
JDK,JRE,JVM之前区别?
- JDK: JAVA标准开发包, 提供了编译,运行java程序需要的工具和资源, 包括java编译器, java运行时环境, 常用的java类库
- JRE: JAVA运行时环境, 用来运行java字节码文件. JRE包括了JVM以及JVM工作需要的类库. 普通用户只需安装JRE来运行java程序, 开发必须按照JDK来编译和调试程序
- JVM: JAVA虚拟机, JRE的一部分, 负责运行字节码文件
java中的异常体系?
所有异常都来自顶级父类Throwable
Throwable下有两个子类Exception和Error
- Error: 表示系统层面非常严重的错误, 靠捕获异常解决不了, 比如java.lang.StackOverFlowError和Java.lang.OutOfMemoryError
- Exception: 分为RuntimeException和非RuntimeException
Exception:
- RuntimeException: 表示运行时异常, 异步是逻辑错误引起的, 比如NullPointerException、IndexOutOfBoundsException, 应该从代码层面尽量避免这类异常产生
- 非RuntimeException: 非运行期异常, 也就是检查异常, 必须处理的异常, 如果不处理程序就不能检查通过. 如IOException、SQLException
链路翻转
比如一个链表, 1 > 2 > 3 > 4 > 5, 改成54321
public class FlipList {
// 迭代
public static Node iteraor (Node node) {
Node prev = null, next;
while (node != null) {
next = node.next;
node.next = prev;
prev = node;
node = next;
}
return prev;
}
public static void main(String[] args) {
Node node5 = new Node(5, null);
Node node4 = new Node(4, node5);
Node node3 = new Node(3, node4);
Node node2 = new Node(2, node3);
Node node1 = new Node(1, node2);
Node head = iteraor(node1);
System.out.println(head);
}
static class Node{
private int val;
private Node next;
public Node(int val, Node next) {
this.val = val;
this.next = next;
}
}
}