Java基础
一、HashMap的源码,实现原理,JDK8中对HashMap做了怎样的优化。
二、HaspMap扩容是怎样扩容的,为什么都是2的N次幂的大小。
三、HashMap,HashTable,ConcurrentHashMap的区别。
四、极高并发下HashTable和ConcurrentHashMap哪个性能更好,为什么,如何实现的。
五、HashMap在高并发下如果没有处理线程安全会有怎样的安全隐患,具体表现是什么。
以上问题可以参考我的另一篇文章=====> 点击
六、java中四种修饰符的限制范围。
public修饰的成员,在同类、同包、子类(继承自本类)、其他包中都可以访问。
protected修饰的成员,在同类、同包、子类中可以访问,但是在其他包中不能访问。
default修饰的成员,在同类、同包中可以访问,但是在其他包中不管是不是子类都不能够访问。
private修饰的成员,只能在同类中被访问,而在同包、子类和其他包中是不能访问的。
另外需要说明的是,public和default一样都可以修饰任何类而且类名必须和文件名相同。而protected和private都不可以修饰类。
图示:
访问权限 | 本类 | 本包 | 不同包子类 | 不同包非子类 |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | |
default | √ | √ | ||
private | √ |
七、Object类中的方法:
package java.lang;
public class Object {
private static native void registerNatives();
static {
registerNatives();
}
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
protected void finalize() throws Throwable { }
}
1. registerNatives() //私有方法
2. getClass() //返回此 Object 的运行类。
3. hashCode() //用于获取对象的哈希值。
4. equals(Object obj) //用于确认两个对象是否“相同”。
5. clone() //创建并返回此对象的一个副本。
6. toString() //返回该对象的字符串表示。
7. notify() //唤醒在此对象监视器上等待的单个线程。
8. notifyAll() //唤醒在此对象监视器上等待的所有线程。
9. wait(long timeout) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或 者超过指定的时间量前,导致当前线程等待。
10. wait(long timeout, int nanos) //在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,导致当前线程等待。
11. wait() //用于让当前线程失去操作权限,当前线程进入等待序列
12. finalize() //当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
特殊说明:
native: java关键字,Native Method 用以修饰非 java 代码实现的方法(C || C++), 类似java调用非java代码的接口。
接口和抽象类的区别,注意JDK8的接口可以有实现
1、抽象类和接口都不能直接实例化,如果要实例化,抽象类变量必须指向实现所有抽象方法的子类对象,接口变量必须指向实现所有接口方法的类对象。
2、抽象类要被子类继承,接口要被类实现。
3、接口只能做方法申明,抽象类中可以做方法申明,也可以做方法实现
4、接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
5、抽象类里的抽象方法必须全部被子类所实现,如果子类不能全部实现父类抽象方法,那么该子类只能是抽象类。同样,一个实现接口的时候,如不能全部实现接口方法,那么该类也只能为抽象类。
6、抽象方法只能申明,不能实现,接口是设计的结果 ,抽象类是重构的结果
7、抽象类里可以没有抽象方法
8、如果一个类里有抽象方法,那么这个类只能是抽象类
9、抽象方法要被实现,所以不能是静态的,也不能是私有的。
10、接口可继承接口,并可多继承接口,但类只能单根继承。
注意:Java 8新特性
1、接口默认方法
默认方法是在接口中的方法签名前加上 default 关键字的实现方法。
interface InterfaceA {
default void foo() {
System.out.println("InterfaceA foo");
}
}
class ClassA implements InterfaceA {
}
public class Test {
public static void main(String[] args) {
// 打印:“InterfaceA foo”
new ClassA().foo();
}
}
为什么要有默认方法?
在Java 8之前,接口与其实现类之间的耦合度过高(tightly coupled),当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法可以为接口添加新的方法,而不会破坏已有的接口的实现。这在lambda表达式作为Java 8语言的重要特性出现之际,为升级旧接口且保持向后兼容(backward compatibility)提供了途径。
/**
* Iterable接口中的forEach默认方法
*/
public interface Iterable<T> {
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
}
默认方法的继承:
接口默认方法的继承分三种情况(分别对应下面的InterfaceB接口、InterfaceC接口和InterfaceD接口):
1、不覆写默认方法,直接从父接口中获取方法的默认实现。
2、覆写默认方法,这跟类与类之间的覆写规则相类似。
3、覆写默认方法并将它重新声明为抽象方法,这样新接口的子类必须再次覆写并实现这个抽象方法。
interface InterfaceA {
default void foo() {
System.out.println("InterfaceA foo");
}
}
interface InterfaceB extends InterfaceA {
}
interface InterfaceC extends InterfaceA {
@Override
default void foo() {
System.out.println("InterfaceC foo");
}
}
interface InterfaceD extends InterfaceA {
@Override
void foo();
}
public class Test {
public static void main(String[] args) {
// 打印:“InterfaceA foo”
new InterfaceB() {}.foo();
// 打印:“InterfaceC foo”
new InterfaceC() {}.foo();
new InterfaceD() {
@Override
public void foo() {
// 打印:“InterfaceD foo”
System.out.println("InterfaceD foo");
}
}.foo();
// 或者使用lambda表达式
((InterfaceD) () -> System.out.println("InterfaceD foo")).foo();
}
}
2、接口静态方法
interface InterfaceA {
default void foo() {
printHelloWorld();
}
static void printHelloWorld() {
System.out.println("hello, world");
}
}
public class Test {
public static void main(String[] args) {
// 打印:“hello, world”
InterfaceA.printHelloWorld();
}
}
default关键字只能在接口中使用(以及用在switch语句的default分支),不能用在抽象类中;接口默认方法不能覆写Object类的equals、hashCode和toString方法;接口中的静态方法必须是public的,public修饰符可以省略,static修饰符不能省略。
动态代理的两种方式,以及区别。
Java序列化的方式。
传值和传引用的区别,Java是怎么样的,有没有传值引用。
一个ArrayList在循环过程中删除,会不会出问题,为什么。
@transactional注解在什么情况下会失效,为什么。
数据结构和算法
B+树
快速排序,堆排序,插入排序(其实八大排序算法都应该了解
一致性Hash算法,一致性Hash算法的应用
JVM
JVM的内存结构。
JVM方法栈的工作过程,方法栈和本地方法栈有什么区别。
JVM的栈中引用如何和堆中的对象产生关联。
可以了解一下逃逸分析技术。
GC的常见算法,CMS以及G1的垃圾回收过程,CMS的各个阶段哪两个是Stop the world的,CMS会不会产生碎片,G1的优势。
标记清除和标记整理算法的理解以及优缺点。
eden survivor区的比例,为什么是这个比例,eden survivor的工作过程。
JVM如何判断一个对象是否该被GC,可以视为root的都有哪几种类型。
强软弱虚引用的区别以及GC对他们执行怎样的操作。
Java是否可以GC直接内存。
Java类加载的过程。
双亲委派模型的过程以及优势。
常用的JVM调优参数。
dump文件的分析。
Java有没有主动触发GC的方式(没有)。
多线程
Java实现多线程有哪几种方式。
Callable和Future的了解。
线程池的参数有哪些,在线程池创建一个线程的过程。
volitile关键字的作用,原理。
synchronized关键字的用法,优缺点。
Lock接口有哪些实现类,使用场景是什么。
可重入锁的用处及实现原理,写时复制的过程,读写锁,分段锁(ConcurrentHashMap中的segment)。
悲观锁,乐观锁,优缺点,CAS有什么缺陷,该如何解决。
ABC三个线程如何保证顺序执行。
线程的状态都有哪些。
sleep和wait的区别。
notify和notifyall的区别。
ThreadLocal的了解,实现原理。
数据库相关
常见的数据库优化手段索引的优缺点,什么字段上建立索引数据库连接池。durid的常用配置。
计算机网络
TCP,UDP区别。三次握手,四次挥手,为什么要四次挥手。长连接和短连接。连接池适合长连接还是短连接。
设计模式
观察者模式代理模式单例模式,有五种写法,可以参考文章单例模式的五种实现方式可以考Spring中使用了哪些设计模式
分布式相关
分布式事务的控制。分布式锁如何设计。分布式session如何设计。dubbo的组件有哪些,各有什么作用。zookeeper的负载均衡算法有哪些。dubbo是如何利用接口就可以通信的。
缓存相关
redis和memcached的区别。redis支持哪些数据结构。redis是单线程的么,所有的工作都是单线程么。redis如何存储一个String的。redis的部署方式,主从,集群。redis的哨兵模式,一个key值如何在redis集群中找到存储在哪里。redis持久化策略。
框架相关
SpringMVC的Controller是如何将参数和前端传来的数据一一对应的。Mybatis如何找到指定的Mapper的,如何完成查询的。Quartz是如何完成定时任务的。自定义注解的实现。Spring使用了哪些设计模式。Spring的IOC有什么优势。Spring如何维护它拥有的bean。一些较新的东西JDK8的新特性,流的概念及优势,为什么有这种优势。区块链了解如何设计双11交易总额面板,要做到高并发高可用