面试经验总结——java基础篇

293 阅读4分钟

1.hashMap,ConcurrentHashMap,hashTable的区别

hashMap是线程不安全的,ConcurrentHashMap,hashTable是线程安全的

hashTable是锁整个Map,所有对map的操作都会锁住,性能很差,不推荐使用

ConcurrentHashMap本质上是把hashmap分成了很多个Segment,等同于很多个hashTable,根据hash值存储和获取,操作时,只会锁住对应的Segment,而不会锁住整个Map,既保证了线程安全又不会降低

多线程环境下ConcurrentHashMap比做了同步的hashmap好,单线程环境下hashmap性能更好

2.java的注解

其实和接口类似,属于继承接口的接口,作用主要是标记,用于生成文档,注入信息,获取注解类示例用于注入等;

分为元注解和自定义注解,元注解有4个,Target用于标记注解范围(类上用还是方法上用),Retention 用于标记使用时机(运行时用还是编译时用),还有两不常用,用于生成文档或者标记子类是否继承

spring注解实际是依赖注解和反射,通过包扫描扫描注解,然后用反射获取对应类,在容器中进行注册,初步理解按扫描到的bean构造,构造时发现有依赖则地则先初始化依赖内容,后续再扫描autoWired进行注入

3.java的接口

接口的主要作用是用于统一标准和规范,降低耦合,减少重复开发量

对于多个对象包含同一方法时,通过定义接口,只需对方法进行一次调用,通过注入不同对象,达成多个对象的方法实现

比如绘图方法,100种绘图类会绘制100个图案,如果不用接口,就要调用100次绘画的方法,如果使用接口,定义一个绘图工具接口,之后只需要写一遍绘图的方法,只要通过注入不同对象,就可以绘制出不同的图

拿Runnable接口举例,线程实例必须实现Runnable方法中的run方法,创建Thread对象时,只接收Runnable对象,将该线程实例作为Runnable对象传入,之后执行Thread的start方法,同时调用实例中的run方法

接口的意义在于,如果不实现接口,传入对象后根本不知道里面包含了什么方法,也无法调用,唯一的办法只能用反射遍历此对象中存在的方法, 按方法名匹配,而且不一定能找到,这样还会暴露整个对象的全部方法

实现了接口以后,不关心对象本身,只关心对象中的run方法,并进行调用

4.volatite的作用

java内存模型围绕原子性,可见性,有序性来进行,

volatite无法保证原子性,但可以保证可见性以及一定程度上保证有序性

5.jdk1.8的新特性

1.接口可以增加默认实现,需要default关键字,并且可以使用箭头的方式实现接口

2.lambda表达式,用于简化匿名内部类的写法

(String a, String b) -> { return b.compareTo(a); }

3.函数式接口,所谓函数式接口(Functional Interface)就是只包含一个抽象方法的声明。针对该接口类型的所有 Lambda 表达式都会与这个抽象方法匹配。{另外,只是在接口上添加default并不算抽象方法}

4.Lambda的作用范围

(1)局部变量,但局部变量不能发生改变

(2)成员和静态,可以修改

5.optionals,用来防空指针异常,不确定一个对象是否可能为空时可以用此类型包装

6.map,可以直接使用foreach遍历,可以使用remove删除map节点

7.日期对象的操作由Calendar函数改为由LocalDate,LocalTime,Clock等函数操作

6.java创建线程池的4种方式及注意事项

1、newFiexedThreadPool(int Threads):创建固定数目线程的线程池。

2、newCachedThreadPool():创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果没有可用的线程,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。

3、newSingleThreadExecutor()创建一个单线程化的Executor。

4、ewScheduledThreadPool(int corePoolSize)创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。

看起来功能还是比较强大的,又用到了工厂模式、又有比较强的扩展性,重要的是用起来还比较方便,如:

ExecutorService executor = Executors.newFixedThreadPool(nThreads) ;

声明线程池时,注意要声明阻塞队列的长度,否则按默认长度会导致内存溢出

可以直接调用ThreadPoolExecutor来自定义线程池

========================额外小知识=======================

jar包运行会从Manifest里找main-class,没有没有这个属性要自己指定

  springboot打包要用打包插件spring-boot-maven-plugin,会将main-class指定为

  org.springframework.boot.loader.JarLauncher,用于调用加载类,调用内部tomcat

  maven-surefire-plugin可以用来跳过mvn test