Java面试总结


一、Java基础

1. 简单说说HashMap底层原理

  • JDK7以前用的是数组和链表实现存储
  • JDK8用数组、链表和红黑树实现存储

插入数据:put(key, value)

  1. 根据key通过HashCode算法、求模得到下标index值;
  2. 当node[index]为空,直接把value值存入该数组位置;
  3. 当node[index]不为空,这个时候就要使用链表或者红黑树;
  4. 当链表元素的个数小于等于8,使用链表,new一个node对象,其值为value,当前值node[index]的next指向新的node对象(尾插法,Jdk7使用的是头插法);
  5. 当链表元素的个数大于8,使用红黑树。

获取数据:get(key)类似

HashMap因为需要扩容的原因,所以线程不安全。

其他参考:

2. ArrayList线程安全问题(不安全)

  • ArrayList是基于数组实现的,是一个动态的数字,可以自动扩容
  • ArrayList不是线程安全的,效率比较高,只能用于单线程的环境中,在多线程环境中可以使用Collections.synchronizedList(List list)函数返回一个线程安全的ArrayList集合,或者使用concurrent并发包下的CopyOnWriteArrayList的。
    //使用Collections.synchronizedList(List list)方法实现线程安全
    List<?> list = Collections.synchronizedList(new ArrayList<>());
    
  • Vector是线程安全的,所以可以在多线程里面使用,替换ArrayList。eg:
    List list= new ArrayList(); 替换为
    List list= new Vector<>();
  • 对线程加同步操作:synchronized(){},也可以避免线程不安全的问题。

例子:

public class TestArrayList {
    public static List arrayList = new ArrayList();
    public static void main(String[] args) {
        // 定义100个线程
        Thread []threadArray = new Thread[100];
        for(int i=0;i<threadArray.length;i++){
            threadArray[i] = new UnsafeArrayListThread();
            threadArray[i].start();
        }
        for (Thread thread : threadArray) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=0;i<arrayList.size();i++){
            System.out.println("第" + (i + 1) + "个元素为:" + arrayList.get(i));
        }
    }
}

class UnsafeArrayListThread extends Thread{
    public void run(){
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        TestArrayList.arrayList.add(Thread.currentThread().getName() + " " + System.currentTimeMillis());
        // 对每一个线程加一个锁:synchronized,可以避免线程不安全的问题
//        synchronized (TestArrayList.arrayList) {
//            TestArrayList.arrayList.add(Thread.currentThread().getName() + " " + System.currentTimeMillis());
//        }
    }
}

在不加synchronized()时,输出会出现 null、数组越界异常、某些线程没有值的情况,会出问题的部分在于: 1. 增加元素 2. 扩充数组长度

各个集合的安全性:
在这里插入图片描述

3. jdk5新增的泛型有什么特性?

3.1 jdk5新增的特性

自动拆装箱
Foreach
静态导入
可变参数 Var args
枚举
格式化输出
泛型
ProcessBuilder
内省
线程并发库(JUC)
监控和管理虚拟机
元数据

3.2 泛型

早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
JDK5之前使用Object传输,然后进行向下转型,这里可能在运行期强转失败抛ClassCastException异常,导致程序异常终止。

引入泛型可以将此运行期异常转移到编译异常,在编写代码时就可以检测出问题。
避免了向下转型,提高了代码的扩展性。

泛型类型必须是引用类型;
泛型只在编译期有效,在运行期就擦除了。

泛型机制:是一种将数据类型的明确工作,推迟到创建对象或调用方法时才去明确的一种机制。

泛型格式:<>

  1. 泛型类:public class MyClass<E> {}
  2. 定义在函数中:public<T> void show(T t){xxx}
  3. 定义在接口上:public interface MyInterface<E> {}

详情请阅读: JDK5 之 泛型

4. jdk7和jdk8的区别

jdk8 主要新特性:

  1. 接口可以添加默认方法和静态方法,default。
  2. lambda表达式,对于接口可以直接用()->{}方式来表达,小括号表示方法入参,花括号内表示方法返回值,如Collections的sort()方法。
  3. 函数式接口:定义一个接口,然后在这个接口里面只能有一个抽象方法。
  4. Iterable 接口中的 forEach()方法。
  5. HashMap中的优化
  6. 新的日期和时间API。
  7. 并发增强。
  8. 支持多重注解:一个注解在一个地方多次使用。
  9. 反射的加强:它允许你直接通过反射获取参数的名字。
  10. 用于集合上批量数据操作的 Java Stream API。
  11. JavaScript引擎Nashorn。
  12. 移出永久代,元空间替换。

5. foreach和for的区别

foreach又叫做增强for循环,相当于for循环的简化版,因此在一些较复杂的循环中不适用。

foreach(元素类型 元素名称:循环对象(数组、集合)){
	循环语句    
}

foreach适用于只是进行集合或数组遍历,for则在较复杂的循环中效率更高。

区别:

  1. for循环是可以中断循环(利用break语句或return语句),但forEach不可以中断循环。
  2. foreach循环时循环对象(数组、集合)被锁定,不能对循环对象中的内容进行增删改操作。
  3. foreach在循环次数未知效率比for循环高。
  4. foreach适用于只是进行集合或数组遍历,for则在较复杂的循环中效率更高。

6. 接口和抽象类的区别

  1. 抽象类要被子类继承,接口要被类实现。
  2. 接口只能做方法声明,抽象类中可以作方法声明,也可以做方法实现。(jdk8开始接口可以添加默认方法和静态方法)
  3. 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量。
  4. 接口是设计的结果,抽象类是重构的结果。
  5. 抽象类和接口都是用来抽象具体对象的,但是接口的抽象级别最高。
  6. 抽象类可以有具体的方法和属性,接口只能有抽象方法和不可变常量。
  7. 抽象类主要用来抽象类别,接口主要用来抽象功能。

7. double 和 float的区别

8. jsp 和 servlet 有什么区别

9. http 和 tcp 的区别

 

二、Spring

相关阅读 Spring 基础知识

1. Spring IoC原理

控制反转(Inversion of Control,英文缩写为 IoC)其实是一个重要的面向对象编程的法则,可以用来削减计算机程序的耦合度,也是轻量级的Spring框架的核心。
通过控制反转(IoC),对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也就是说,依赖被注入到对象中。
所以,控制反转是,关于一个对象如何获取它所依赖的对象的引用,这个责任的反转
IoC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。

IoC实现的背后原理—反射与工厂模式

反射实现的一个重要原因是因为每个类在加载的过程中都会生成一个代表这个类的java.lang.Class对象作为方法区数据访问的入口,所谓反射,就是通过获取某个类的class对象后反向的获取某个类或对象的属性及方法信息。
Spring提供了两种容器(工厂):Spring BeanFactory 容器、 Spring ApplicationContext 容器。在Spring中BeanFactory容器 是 IoC容器的实际代表者。

2. 什么是AOP?

 

三、Spring Boot

1. Spring Boot 常用注解有哪些

@SpringBootApplication,@EnableAutoConfiguration,@ComponentScan,@Configuration
@Component,@Autowired,@Resource,@Qualifier
@Repository,@Service,@RestController,@Controller,@ResponseBody,@RequestMapping

详情请阅读: SpringBoot常用注解

2. Spring Boot 自动配置原理

详情请阅读: Spring Boot 自动配置原理

3. Spring 和 Spring Boot 区别

Spring Boot基本上是Spring框架的扩展,它消除了设置Spring应用程序所需的XML配置,为更快,更高效的开发生态系统铺平了道路。
Springboot是一个微服务框架,延续了spring框架的核心思想IOC和AOP,简化了应用的开发和部署。Spring Boot是为了简化Spring应用的创建、运行、调试、部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置。

 

四、SpringMVC

1. SpringMVC有哪些处理器

前端控制器DispatcherServlet(也叫中央处理器):作为前端控制器,整个流程控制的中心,控制其它组件执行,统一调度,降低组件之间的耦合性,提高每个组件的扩展性。

处理器映射器HandlerMappering:通过扩展处理器映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。

处理器适配器HandlerAdapter:通过扩展处理器适配器,支持更多类型的处理器。

视图解析器ViewReslover:通过扩展视图解析器,支持更多类型的视图解析,例如:jsp、freemarker、pdf、excel等。

2. SpringMVC工作原理

  1. 客户端请求提交到DispatcherServlet
  2. 由DispatcherServlet控制器查询一个或多个HandlerMapping,找到处理请求的Controller
  3. DispatcherServlet将请求提交到Controller
  4. Controller调用业务逻辑处理后,返回ModelAndView
  5. DispatcherServlet查询一个或多个ViewResoler视图解析器,找到ModelAndView指定的视图,并将结果显示到客户

详情请阅读:SpringMVC 工作原理

3. SpringMVC有哪些注解

详情请阅读: SpringMVC 常用注解

 

四、数据库/缓存

1. SQL存储过程

2. Oracle有哪些函数

3. Oracle如何剔重

4. SQL优化

5. SQL事务

详情请阅读: SQL 之 事务(Transaction)

6. MyBatis底层原理

7. MyBatis获取数据,传参区别#{},${}的区别

8. MyBatis标签

9. redis击穿,穿透,雪崩

10. char 和 varchar 的区别

  1. 定长和变长

char 是定长的,长度固定,varchar 是变长的,长度可变。
char的存取速度还是要比varchar快得多,方便程序的存储与查找;
但是char也为此付出的是空间的代价,因为其长度固定,所以会占据多余的空间,可谓是以空间换取时间效率。
varchar则刚好相反,以时间换空间。

  1. 存储的容量不同

varchar 存储容量比 char 大很多。
对 char 来说,最多能存放的字符个数 255,和编码无关。
而 varchar 呢,最多能存放 65532 个字符。varchar的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是 65,532字节。

 

五、微服务/分布式

1. 微服务的理解

2. 为什么使用dubbo?

随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA)。
也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架。
就这样为分布式系统的服务治理框架就出现了,dubbo也就这样产生了。
dubbo在整个分布式系统的架构中,按照分层的架构来架构,使得各个层级之间最大限度的松耦合。

  1. 使用 dubbo 管理不同服务之间的通信;
  2. 管理服务之间的调用和依赖关系;
  3. 降低各个分层之间的耦合度;

 

六、算法

1. 说下常用排序算法

详情请阅读:常用排序算法

  1. 冒泡排序(Bubble Sort)
  2. 选择排序(Selection Sort)
  3. 插入排序(Insertion Sort)
  4. 快速排序(Quick Sort)
  5. 希尔排序(Shell Sort)
  6. 归并排序(Merge Sort)
  7. 堆排序(Heap Sort)
  8. 基数排序(Basic Sort)
  9. 桶排序

 

七、多线程

线程池的底层工作原理

线程池内部是通过队列+线程实现的,当我们利用线程池执行任务时:

  1. 若此时线程池中的线程数量 < corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理新增的任务;
  2. 若此时线程池中的线程数量 = corePoolSize,但缓冲队列workQueue未满,那么任务放进workQueue中;
  3. 若此时线程池中的线程数量 >= corePoolSize,且缓冲队列workQueue已满,且线程池中的数量 < maximumPoolSize,则建新的线程来处理新增的任务;
  4. 若此时线程池中的线程数量 > corePoolSize,且缓冲队列workQueue已满,且线程池中的数量 = maximumPoolSize,则通过handler所指定的策略来处理此任务;
  5. 当线程池中的线程数量 > corePoolSize时,若某线程的空闲时间超过keepAliveTime,该线程将被终止。这样,线程池可以动态的调整池中的线程数。

线程池为什么是先添加队列而不是先创建最大线程

当线程池中的核心线程都在运行中,若继续向线程池中添加新任务,会优先添加到队列中进行等待,队列满了之后才会创建新线程。

  1. 平衡资源利用率
  2. 减低内存占用
  3. 合理的调度和管理
  4. 提高线程池的性能和效率

八、前端

1. vue.js

 

九、其他框架

1. shiro原理,数据库模型

2. solr原理


未完待续~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL的优化可以从多个方面入手。首先,可以通过优化查询来提高MySQL的性能。这包括使用合适的索引、避免全表扫描、优化查询语句等。其次,可以通过调整MySQL的配置参数来提升性能,例如增加缓冲区大小、调整并发连接数等。此外,还可以考虑使用缓存技术,如使用Redis作为缓存层,减少对数据库的访问。另外,对于大数据量的表,可以考虑分库分表的方式来提高查询效率。总之,MySQL的优化是一个综合性的工作,需要根据具体的场景和需求进行调整和优化。 参考资料: \[1\] 【Java面试总结】MySQL篇·SQL优化篇 \[2\] MySQL 精选 60 道面试题(含答案) \[3\] MySQL如何保证ACID #### 引用[.reference_title] - *1* [【Java面试总结】MySQL篇·优化篇](https://blog.csdn.net/Gherbirthday0916/article/details/129097938)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Java面试题之 mysql面试题](https://blog.csdn.net/qq_40036754/article/details/126608721)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值