那些让你稳进大厂Java面试题,你都掌握了多少?

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之前,我们需要先弄清楚一些概念:

  1. 可重入锁:可重入锁是指同一个线程可以多次获得同一把锁;ReentrantLock和关键字Synchronized都是可重入锁
  2. 可中断锁:可中断锁时只线程在获取锁的过程中,是否可以相应线程中断操作。synchronized是不可中断的,ReentrantLock是可中断的
  3. 公平锁和非公平锁:公平锁是指多个线程尝试获取同一把锁的时候,获取锁的顺序按照线程到达的先后顺序获取,而不是随机插队的方式获取。synchronized是非公平锁,而ReentrantLock是两种都可以实现,不过默认是非公平锁
  4. 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种设计模式,包括:<

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值