说说你对面向对象的理解。
面向对象是编程思想,万物都可归类,万物皆是对象。
首先面向对象的三大特征:封装、继承和多态。这三大特征相辅相成。
封装是封装类的内部实现机制。可以在不影响使用的情况下去改变类的内部结构,只要接口不变,那类的内部结构如何改变都可以。同时也保护了数据。
继承是从原有的类中派生出新的类,新的类吸收旧类的数据属性和行为,并扩展新的能力。
多态是指类和类的关系,封装和继承归类于多态。因为有继承的关系,存在子类重写父类方法的条件下,可以调用父类的由父类的引用指向子类对象。
这三个特征都是为了写出更好的代码,也更符合人观察世界归纳总结事物的思想、可以增加代码复用性、可移植性、灵活性。
创建线程有几种方式?
表面上有四种:
1、继承Thread类创建线程。
2、实现runable接口创建线程。
3、实现Callable接口并结合FutureTask创建线程(可以拿到线程的返回结果)。
4、利用线程池的Executors的方式创建线程(不推荐)。
实际上底层都是实现了runable接口来实现的创建线程。例如Thread也是实现了runable接口。FutureTask也是间接继承了runable接口的。
但为什么不推荐使用第四种呢?因为创建的队列LinkedBlockingQueue,是一个无界的阻塞队列。如果使用该线程池执行任务,如果任务过多会就会不断往队列中添加任务,导致内存占用不断增加,最总内存耗尽导致OOM。
创建一个线程池有几个参数?分别是什么意思?
corePoolSize
(核心线程数):指定线程池中一直保持活动的线程数量。即使线程处于空闲状态,核心线程也不会被回收销毁。maxPoolSize
(最大线程数):指定线程池中允许存在的最大线程数量,包括核心线程和非核心线程。当任务量增加时,线程池会创建新的线程,直到达到最大线程数。keepAliveTime
(线程存活时间):表示非核心线程在空闲状态下的存活时间。当线程池中的线程数量超过核心线程数且空闲一段时间后,多余的非核心线程会被回收销毁,以减少资源占用。unit
(时间单位):用于指定keepAliveTime
的时间单位,例如秒、毫秒、分钟等。workQueue
(阻塞队列):用于存储等待执行的任务的队列。当线程池中的线程都在忙碌时,新提交的任务会被放入阻塞队列中等待执行。threadFactory
(线程工厂):用于创建新线程的工厂类。线程工厂定义了线程的创建方式,例如线程的名称、优先级等。handler
(拒绝策略):当线程池无法继续接受新的任务时,拒绝策略定义了如何处理这些被拒绝的任务。常见的拒绝策略包括抛出异常、丢弃任务、丢弃最早的任务等。
通过调整这些参数,可以根据实际需求来控制线程池的行为,例如控制线程数量、任务队列大小以及拒绝策略等,以适应不同的并发场景。
HashMap的实现原理。
HashMap使用数组加链表的方式实现。当数组长度大于64,且链表长度大于等于8的时候会将链表转为红黑树,当长度下降为6时会转为链表。因为链表的查找时间复杂度为O(n),而红黑树的时间查找复杂度为O(logn),防止链表过长影响查找效率。
CAS和CQS是什么?简单说下这两者的基本原理。
CAS是compare and swap,也就是比较和交换。是在cpu层面去保证并发的原子性。
NIO
A等于某某某、B大于某某某、C小于某某某。应该如何创建索引。
在创建组合索引时候需要注意最左前缀的情况。
当创建组合索引(A, B, C)的时候,实际上是创建了三个索引分别是(A)、(A, B)、(A, B, C)
所以创建索引的时候应该把最经常使用的索引放在最左边。
数据库中的索引分为哪几种?为什么要建索引?
1、主键索引,数据列不允许、不允许为Null、一个表只能有一个主键。
2、唯一索引,数据列不允许重复、允许为Null,一个表允许多个列创建唯一索引。
3、普通索引,基本的索引类型,无唯一性约束,允许为Null值。
4、全文索引,是目前搜索引擎使用的关键技术,对文本内容进行分词和搜索。
5、覆盖索引,查询列要被所建的索引覆盖,不必独取数据行。
6、组合索引,用多列值组成索引,用于组合搜索,效率大于索引合并。
合理的建立索引可以提高查找效率,减少查找时间。有一些特殊索引可以保证数据完整性,比如唯一索引。
缺点是创建索引和维护索引需要时间。索引需要额外占用物理空间。对创建索引的表进行增加、修改、删除时会同步动态维护索引,这部分会造成性能的影响。
但只要这部分性能的影响小于查找所消耗的时间就可以接受。
innodb中执行更新语句时,数据库会上什么锁?
在InnoDB存储引擎中执行更新语句时,数据库会使用行级锁进行并发控制。具体来说,InnoDB支持两种类型的行级锁:
- 共享锁(Shared Lock):也称为读锁。当一个事务对某一行加上共享锁时,其他事务也可以对同一行加上共享锁,允许并发读取但不允许写入。共享锁之间不会互相阻塞,多个事务可以同时持有共享锁。
- 排他锁(Exclusive Lock):也称为写锁。当一个事务对某一行加上排他锁时,其他事务无法同时对同一行加上共享锁或排他锁,保证了写操作的独占性。排他锁会阻塞其他事务的读取和写入操作。
根据具体的情况,InnoDB在执行更新语句时会根据需要自动加上适当的行级锁。如果更新语句涉及的行已经被其他事务持有共享锁,那么当前事务需要等待其他事务释放共享锁或者将其升级为排他锁,才能获取到排他锁并执行更新操作。这样可以保证数据的一致性和并发控制。
需要注意的是,InnoDB的行级锁是基于索引的,而不是基于整个表。这意味着如果更新操作没有使用索引,或者使用了全表扫描的方式,那么InnoDB可能会使用更高级别的锁(如表级锁)来进行并发控制,而不是行级锁。因此,在设计数据库表结构和索引时,需要考虑到并发访问的需求,以减少锁冲突和提高性能。
简单说下IOC容器的启动过程。
IOC容器的启动过程可以概括为以下几个步骤:
- 加载配置文件:IOC容器首先会读取配置文件,通常是XML或注解方式的配置文件。配置文件中包含了定义和描述各个Bean(组件)的信息,包括类的路径、依赖关系、作用域等。
- 创建容器实例:根据配置文件的信息,IOC容器会创建一个容器实例,通常是通过特定的容器类(如ApplicationContext)来实现。容器实例是整个IOC容器的核心对象,负责管理和控制所有的Bean。
- 实例化Bean对象:IOC容器会根据配置文件中的定义,实例化所有需要管理的Bean对象。这一过程通常是通过反射机制来创建对象,调用构造函数实例化Bean。
- 处理Bean之间的依赖关系:IOC容器会解析配置文件中的依赖关系,根据依赖关系将实例化的Bean对象进行依赖注入。即将依赖的对象通过构造函数、属性注入或方法注入等方式设置到需要依赖的Bean中。
- 执行初始化操作:在完成依赖注入后,IOC容器会调用Bean的初始化方法(如init-method),对Bean进行必要的初始化操作。这个阶段可以进行一些自定义的逻辑,如数据加载、资源初始化等。
- 提供Bean的访问和管理:IOC容器会将实例化和初始化的Bean对象存储在容器内部的数据结构中,提供统一的访问接口供其他组件或应用程序使用。通过这个接口,可以获取和管理Bean的实例,以满足业务需求。
总体来说,IOC容器的启动过程包括加载配置文件、创建容器实例、实例化Bean对象、处理依赖关系、执行初始化操作以及提供Bean的访问和管理等步骤。通过这个过程,IOC容器可以实现对Bean的统一管理、依赖解耦和灵活的配置和扩展。
Bean的生命周期。
在Spring框架中,Bean的生命周期可以分为以下几个阶段:
- 实例化(Instantiation):在IOC容器启动时,根据配置信息或注解,IOC容器实例化Bean对象。这个阶段会调用Bean的构造函数来创建对象实例。
- 属性赋值(Population):在实例化后,IOC容器会将配置文件或注解中定义的属性值注入到Bean实例中。这个阶段可以通过构造函数注入、属性注入或方法注入来完成。
- 初始化(Initialization):在属性赋值完成后,IOC容器会调用Bean的初始化方法(如init-method),对Bean进行一些额外的初始化操作。这个阶段可以在Bean中自定义一些逻辑,如数据加载、资源初始化等。
- 使用(In Use):在初始化阶段完成后,Bean对象进入可用状态,可以被其他组件或应用程序使用。这个阶段是Bean正常运行和提供服务的阶段。
- 销毁(Destruction):当IOC容器关闭或销毁时,会调用Bean的销毁方法(如destroy-method),执行一些清理操作,释放资源等。这个阶段可以在Bean中进行一些善后处理,如关闭数据库连接、释放文件资源等。
需要注意的是,Bean的生命周期可以受到Spring框架提供的扩展接口的影响,例如BeanPostProcessor和InitializingBean接口。BeanPostProcessor接口可以在Bean实例化、属性赋值和初始化阶段对Bean进行自定义的处理,而InitializingBean接口可以在Bean初始化阶段进行一些特定的初始化操作。
总的来说,Bean的生命周期经历了实例化、属性赋值、初始化、使用和销毁等阶段。Spring框架通过控制和管理Bean的生命周期,提供了灵活的配置和扩展机制,使得开发者能够更好地控制和定制Bean的行为。
Spring的AOP怎么用的。
Spring的事务中,什么会导致事务失效。
Spring框架提供几种事务的传播行为
springboot相比于SSM的优势在哪劣势在哪
Spring Boot相比于传统的SSM(Spring + Spring MVC + MyBatis)框架具有以下优势和劣势:
优势:
- 简化配置:Spring Boot采用约定大于配置的原则,提供了自动化配置和默认配置,大大减少了开发者的配置工作量。通过自动依赖管理和自动配置,可以快速搭建和启动一个Spring应用程序。
- 内嵌服务器:Spring Boot集成了常用的内嵌服务器,如Tomcat、Jetty和Undertow,无需手动部署WAR文件到独立的服务器上,可以直接将Spring Boot应用程序打包成可执行的JAR文件,并通过Java命令启动应用。
- 自动装配:Spring Boot提供了丰富的自动配置功能,根据应用程序的依赖关系自动装配相关的组件和配置,简化了Spring应用程序的开发和部署。开发者只需关注业务逻辑的实现,无需过多配置和管理各种框架和组件。
- 微服务支持:Spring Boot为构建和管理微服务架构提供了一系列的解决方案和工具。通过Spring Cloud项目,可以轻松实现服务发现、负载均衡、配置管理等微服务相关功能,方便开发分布式系统。
- 生态系统:Spring Boot在Spring生态系统的基础上构建,可以无缝集成Spring框架的各个模块和第三方库。同时,Spring Boot拥有庞大的开发者社区和丰富的文档资源,提供了大量的插件和扩展,方便开发者快速解决问题。
劣势:
- 学习曲线:相对于传统的SSM框架,Spring Boot引入了一些新的概念和技术,初次接触的开发者可能需要花费一些时间来学习和理解这些新的概念和技术。
- 约束性较强:Spring Boot的约定和自动配置可以提高开发效率,但也可能限制了一些自定义需求和灵活性。在一些特殊场景下,开发者可能需要深入了解Spring Boot的工作原理,并进行一些额外的配置和调整。
- 复杂度增加:由于Spring Boot集成了很多功能和组件,其底层代码相对较复杂。在遇到问题时,需要对Spring Boot的内部机制和原理有一定的了解,才能更好地进行故障排查和调优。
- 配置管理:虽然Spring Boot提供了自动配置的功能,但在一些复杂的应用场景下,配置管理可能变得复杂。