Docker+springBoot+Dubbo+Zookeeper+mybatis+redis+rabbitmq+quartz+graphql+kotlin+elasticsearch+JWT+shiro+AOP+flyway+DataX+dblink
封装类/包装类Wrapper
1.构造器不能被继承,因此不能被重写,但可以被重载。
2.如果两个对象相同(equals方法返回true),那么它们的hashCode值一定要相同;如果两个对象的hashCode相同,它们并不一定相同;
3.JVM加载class文件的原理机制
加载/验证/准备/解析/初始化
类加载器包括:根加载器(BootStrap)、扩展加载器(Extension)、系统加载器(System)和用户自定义类加载器(java.lang.ClassLoader的子类)
双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成
类加载器-运行时数据区-执行引擎-垃圾回收机制
4.内存泄漏
理论上Java因为有垃圾回收机制(GC)不会存在内存泄露问题
然而在实际开发中,可能会存在无用但可达的对象,这些对象不能被GC回收,因此也会导致内存泄露的发生关闭(close)或清空(flush)
5.栈(先进后出(FILO)
6.是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
答:不可以,静态方法只能访问静态成员,因为非静态方法的调用要先创建对象,在调用静态方法时可能对象并没有被初始化。
7.String s = new String("xyz");创建了几个字符串对象?
答:两个对象,一个是静态区的"xyz",一个是用new创建在堆上的对象。
8.Java 中的final关键字有哪些用法?
答:(1)修饰类:表示该类不能被继承;(2)修饰方法:表示方法不能被重写;(3)修饰变量:表示变量只能一次赋值以后值不能被修改(常量)。
9.类加载顺序
父类静态代变量、
父类静态代码块、
子类静态变量、
子类静态代码块、
父类非静态变量(父类实例成员变量)、
父类构造函数、
子类非静态变量(子类实例成员变量)、
子类构造函数。
先初始化静态成员,然后调用父类构造器,再初始化非静态成员,最后调用自身构造器。
10.List、Set、Map是否继承自Collection接口?
答:List、Set 是,Map 不是。Map是键值对映射容器,与List和Set有明显的区别,而Set存储的零散的元素且不允许有重复元素(数学中的集合也是如此),List是线性结构的容器,适用于按数值索引访问元素的情形。
Collection是一个接口,它是Set、List等容器的父接口
11.List、Map、Set三个接口存取元素时,各有什么特点
List以特定索引来存取元素,可以有重复元素。
Set不能存放重复元素
Map保存键值对(key-value pair)映射,映射关系可以是一对一或多对一
ArrayList是基于索引的数据接口,它的底层是数组,它可以以O(1)时间复杂度对元素进行随机访问
LinkedList是以元素列表的形式存储它的数据,每一个元素都和它的前一个和后一个元素链接在一起,在这种情况下,查找某个元素的时间复杂度是O(n)。
相对于ArrayList,LinkedList的插入,添加,删除操作速度更快,因为当元素被添加到集合任意位置的时候,不需要像数组那样重新计算大小或者是更新索引
LinkedList比ArrayList更占内存,因为LinkedList为每一个节点存储了两个引用,一个指向前一个元素,一个指向下一个元素
LinkedList和ArrayList是另个不同变量列表的实现。ArrayList的优势在于动态的增长数组,非常适合初始时总长度未知的情况下使用。LinkedList的优势在于在中间位置插入和删除操作,速度是最快的。
LinkedList实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
ArrayList实现了可变大小的数组。它允许所有元素,包括null。 每个ArrayList实例都有一个容量(Capacity),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
LinkedHashMap则记录了插入顺序
TreeMap默认升序
12.请说出与线程同步以及线程调度相关的方法
execute 无返回值
ExecutorService service = Executors.newFixedThreadPool(100);
for(int i = 1; i <= 100; i++) {
service.execute(new AddMoneyThread(account, 1));
}
service.shutdown();
while(!service.isTerminated()) {}
System.out.println("账户余额: " + account.getBalance());
submit有返回值
List<Future<Integer>> list = new ArrayList<>();
ExecutorService service = Executors.newFixedThreadPool(10);
for(int i = 0; i < 10; i++) {
list.add(service.submit(new MyTask((int) (Math.random() * 100))));
}
int sum = 0;
for(Future<Integer> future : list) {
// while(!future.isDone()) ;
sum += future.get();
}
System.out.println(sum);
13.什么是线程池
答:先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程不用自行创建,使用完毕不需要销毁线程而是放回池中,从而减少创建和销毁线程对象的开销
14.简述synchronized 和java.util.concurrent.locks.Lock&ReentrantLock的区别
答:Lock是Java 5以后引入的新的API,和关键字synchronized相比
主要相同点:Lock 能完成synchronized所实现的所有功能;
主要不同点:Lock有比synchronized更精确的线程语义和更好的性能,而且不强制性的要求一定要获得锁。synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且最好在finally 块中释放(这是释放外部资源的最好的地方)。
synchronized是和if、else、for、while一样的关键字&ReentrantLock是类
ReentrantLock可以对获取锁的等待时间进行设置,这样就避免了死锁
ReentrantLock可以获取各种锁的信息
ReentrantLock可以灵活地实现多路通知
ReentrantLock是Lock的默认实现,在聊ReentranLock之前,我们需要先弄清楚一些概念:
- 可重入锁:可重入锁是指同一个线程可以多次获得同一把锁;ReentrantLock和关键字Synchronized都是可重入锁
- 可中断锁:可中断锁时只线程在获取锁的过程中,是否可以相应线程中断操作。synchronized是不可中断的,ReentrantLock是可中断的
- 公平锁和非公平锁:公平锁是指多个线程尝试获取同一把锁的时候,获取锁的顺序按照线程到达的先后顺序获取,而不是随机插队的方式获取。synchronized是非公平锁,而ReentrantLock是两种都可以实现,不过默认是非公平锁
- Object中wait类似的方法Condition相同
15.数据库事务的ACID是指什么
原子性/一致性/隔离性/持久性
default 可重复读 不可避免幻读 --事务A读取了符合条件的行,发现插入了事务B插入的数据
脏读
A事务读取B事务尚未提交的数据并在此基础上操作,而B事务执行回滚,那么A读取到的数据就是脏数据。
不可重复读
事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。
幻读
事务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行
16.获得一个类的类对象有哪些方式
方法1:类型.class,例如:String.class
方法2:对象.getClass(),例如:"hello".getClass()
方法3:Class.forName(),例如:Class.forName("java.lang.String")
17.如何通过反射创建对象
方法1:通过类对象调用newInstance()方法,例如:String.class.newInstance()
方法2:通过类对象的getConstructor()或getDeclaredConstructor()方法获得构造器(Constructor)对象并调用其newInstance()方法创建对象,例如:String.class.getConstructor(String.class).newInstance("Hello");
18.如何通过反射调用对象的方法
String str = "hello";
Method m = str.getClass().getMethod("toUpperCase");
System.out.println(m.invoke(str));
19.常用设计模式
共23种设计模式,包括:<